uh-layout 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -0
- data/lib/uh/layout/arrangers/fixed_width.rb +30 -0
- data/lib/uh/layout/arrangers/stack.rb +24 -0
- data/lib/uh/layout/arrangers/vert_tile.rb +28 -0
- data/lib/uh/layout/client_column_mover.rb +33 -0
- data/lib/uh/layout/column.rb +20 -10
- data/lib/uh/layout/container.rb +4 -3
- data/lib/uh/layout/tag.rb +11 -0
- data/lib/uh/layout/version.rb +1 -1
- data/lib/uh/layout.rb +26 -18
- data/spec/support/factories.rb +14 -0
- data/spec/uh/layout/arrangers/fixed_width_spec.rb +72 -0
- data/spec/uh/layout/arrangers/stack_spec.rb +42 -0
- data/spec/uh/layout/arrangers/vert_tile_spec.rb +49 -0
- data/spec/uh/layout/client_column_mover_spec.rb +96 -0
- data/spec/uh/layout/column_spec.rb +52 -12
- data/spec/uh/layout/container_spec.rb +5 -5
- data/spec/uh/layout/screen_spec.rb +1 -1
- data/spec/uh/layout/tag_spec.rb +32 -3
- data/spec/uh/layout_spec.rb +39 -34
- data/uh-layout.gemspec +1 -2
- metadata +20 -12
- data/Gemfile-custom.rb +0 -7
- data/lib/uh/layout/column/arranger.rb +0 -66
- data/lib/uh/layout/geo_accessors.rb +0 -10
- data/spec/uh/layout/column/arranger_spec.rb +0 -181
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47a100f2229b06ab1aa01eeb35e1b8baba73f804
|
4
|
+
data.tar.gz: 3cc639552ca1d7cfa766a0d6afb03dab85532b86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c0c3f914c932e129fb9eaf10c18a6fe7cc90335adec8f4822aecda6a6856204ceff06e832016d59716de7b08506450f49b0c56c36b53198d6e29bce3a31f621
|
7
|
+
data.tar.gz: 8a7ce44e77e6edad1746dc478253a0a742c404538e0b9d771e605ad67a6ecc6c19843a1f984cdec1ed4841d697a467574134aa6568d7105edcbe726f7943328c
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
module Arrangers
|
4
|
+
class FixedWidth
|
5
|
+
DEFAULT_WIDTH = 484
|
6
|
+
|
7
|
+
def initialize(entries, geo, width: DEFAULT_WIDTH)
|
8
|
+
@entries = entries
|
9
|
+
@geo = geo
|
10
|
+
@width = width
|
11
|
+
end
|
12
|
+
|
13
|
+
def arrange
|
14
|
+
return if @entries.empty?
|
15
|
+
@entries.each_with_index do |column, i|
|
16
|
+
column.x = @width * i + @geo.x
|
17
|
+
column.y = @geo.y
|
18
|
+
column.width = @width
|
19
|
+
column.height = @geo.height
|
20
|
+
end
|
21
|
+
@entries.last.width = @geo.width - (@entries.last.x - @geo.x)
|
22
|
+
end
|
23
|
+
|
24
|
+
def max_count?
|
25
|
+
(@geo.width / (@entries.size + 1)) < @width
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
module Arrangers
|
4
|
+
class Stack
|
5
|
+
def initialize(entries, geo)
|
6
|
+
@entries = entries
|
7
|
+
@geo = geo
|
8
|
+
end
|
9
|
+
|
10
|
+
def arrange
|
11
|
+
@entries.each { |e| e.geo = @geo.dup }
|
12
|
+
end
|
13
|
+
|
14
|
+
def each_visible
|
15
|
+
yield @entries.current if @entries.current
|
16
|
+
end
|
17
|
+
|
18
|
+
def each_hidden
|
19
|
+
([*@entries] - [@entries.current]).each { |e| yield e }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
module Arrangers
|
4
|
+
class VertTile
|
5
|
+
def initialize(entries, geo)
|
6
|
+
@entries = entries
|
7
|
+
@geo = geo
|
8
|
+
end
|
9
|
+
|
10
|
+
def arrange
|
11
|
+
entry_height = @geo.height / @entries.size - 1
|
12
|
+
@entries.each_with_index do |entry, i|
|
13
|
+
entry.geo = @geo.dup
|
14
|
+
entry.y = (entry_height + 1) * i
|
15
|
+
entry.height = entry_height
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def each_visible
|
20
|
+
@entries.each { |e| yield e }
|
21
|
+
end
|
22
|
+
|
23
|
+
def each_hidden
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
class ClientColumnMover
|
4
|
+
def initialize(columns, columns_max_count)
|
5
|
+
@columns = columns
|
6
|
+
@columns_max_count = columns_max_count
|
7
|
+
end
|
8
|
+
|
9
|
+
def move_current(direction)
|
10
|
+
@columns.current.remove client = @columns.current.current_client
|
11
|
+
dest_column = get_or_create_column direction
|
12
|
+
dest_column << client
|
13
|
+
dest_column.current_client = client
|
14
|
+
@columns.current = dest_column
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_or_create_column(direction)
|
18
|
+
if candidate = @columns.get(direction)
|
19
|
+
candidate
|
20
|
+
elsif @columns_max_count
|
21
|
+
@columns.get direction, cycle: true
|
22
|
+
else
|
23
|
+
Column.new(Geo.new).tap do |o|
|
24
|
+
case direction
|
25
|
+
when :pred then @columns.unshift o
|
26
|
+
when :succ then @columns << o
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/uh/layout/column.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
module Uh
|
2
2
|
class Layout
|
3
3
|
class Column
|
4
|
+
MODES = {
|
5
|
+
stack: Arrangers::Stack,
|
6
|
+
tile: Arrangers::VertTile
|
7
|
+
}.freeze
|
8
|
+
|
4
9
|
include GeoAccessors
|
5
10
|
|
6
11
|
extend Forwardable
|
@@ -9,11 +14,12 @@ module Uh
|
|
9
14
|
def_delegator :@clients, :current=, :current_client=
|
10
15
|
def_delegator :current_client, :==, :current_client?
|
11
16
|
|
12
|
-
attr_reader :geo, :clients
|
17
|
+
attr_reader :geo, :clients, :mode
|
13
18
|
|
14
19
|
def initialize(geo)
|
15
20
|
@geo = geo.dup
|
16
21
|
@clients = Container.new
|
22
|
+
@mode = :stack
|
17
23
|
end
|
18
24
|
|
19
25
|
def to_s
|
@@ -26,18 +32,22 @@ module Uh
|
|
26
32
|
self
|
27
33
|
end
|
28
34
|
|
35
|
+
def mode_toggle
|
36
|
+
@mode = MODES.keys[(MODES.keys.index(@mode) + 1) % MODES.keys.size]
|
37
|
+
end
|
38
|
+
|
39
|
+
def arranger
|
40
|
+
MODES[@mode].new @clients, @geo
|
41
|
+
end
|
42
|
+
|
29
43
|
def arrange_clients
|
30
|
-
|
31
|
-
|
32
|
-
client.moveresize
|
33
|
-
end
|
44
|
+
arranger.arrange
|
45
|
+
clients.each &:moveresize
|
34
46
|
end
|
35
47
|
|
36
|
-
def show_hide_clients
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
@clients.current.show if @clients.current && @clients.current.hidden?
|
48
|
+
def show_hide_clients(arranger: self.arranger)
|
49
|
+
arranger.each_visible { |client| client.show if client.hidden? }
|
50
|
+
arranger.each_hidden { |client| client.hide unless client.hidden? }
|
41
51
|
end
|
42
52
|
end
|
43
53
|
end
|
data/lib/uh/layout/container.rb
CHANGED
@@ -4,8 +4,8 @@ module Uh
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
extend Forwardable
|
7
|
-
def_delegators :@entries, :<<, :[], :each, :empty?, :
|
8
|
-
:size, :unshift
|
7
|
+
def_delegators :@entries, :<<, :[], :each, :empty?, :fetch, :first,
|
8
|
+
:index, :last, :size, :unshift
|
9
9
|
|
10
10
|
def initialize(entries = [])
|
11
11
|
@entries = entries
|
@@ -19,7 +19,8 @@ module Uh
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def current=(entry)
|
22
|
-
|
22
|
+
fail ArgumentError, 'unknown entry' unless include? entry
|
23
|
+
@current_index = @entries.index entry
|
23
24
|
end
|
24
25
|
|
25
26
|
def remove(entry)
|
data/lib/uh/layout/tag.rb
CHANGED
@@ -9,6 +9,7 @@ module Uh
|
|
9
9
|
def_delegator :@columns, :each, :each_column
|
10
10
|
def_delegator :current_column, :==, :current_column?
|
11
11
|
def_delegator :clients, :each, :each_client
|
12
|
+
def_delegator :arranger, :max_count?, :columns_max_count?
|
12
13
|
|
13
14
|
attr_reader :id, :geo, :columns
|
14
15
|
|
@@ -39,6 +40,16 @@ module Uh
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
def arranger
|
44
|
+
Arrangers::FixedWidth.new(@columns, @geo)
|
45
|
+
end
|
46
|
+
|
47
|
+
def arrange_columns
|
48
|
+
@columns.remove_if &:empty?
|
49
|
+
arranger.arrange
|
50
|
+
@columns.each &:arrange_clients
|
51
|
+
end
|
52
|
+
|
42
53
|
def hide
|
43
54
|
clients.each &:hide
|
44
55
|
end
|
data/lib/uh/layout/version.rb
CHANGED
data/lib/uh/layout.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
|
-
require 'uh/layout/
|
3
|
+
require 'uh/layout/arrangers/fixed_width'
|
4
|
+
require 'uh/layout/arrangers/stack'
|
5
|
+
require 'uh/layout/arrangers/vert_tile'
|
4
6
|
require 'uh/layout/bar'
|
7
|
+
require 'uh/layout/client_column_mover'
|
5
8
|
require 'uh/layout/container'
|
6
9
|
require 'uh/layout/column'
|
7
|
-
require 'uh/layout/column/arranger'
|
8
10
|
require 'uh/layout/dumper'
|
9
11
|
require 'uh/layout/screen'
|
10
12
|
require 'uh/layout/tag'
|
11
13
|
|
12
14
|
module Uh
|
13
15
|
class Layout
|
16
|
+
Error = Class.new(StandardError)
|
17
|
+
ArgumentError = Class.new(Error)
|
18
|
+
|
14
19
|
extend Forwardable
|
15
20
|
def_delegator :@screens, :current, :current_screen
|
16
21
|
def_delegator :current_screen, :==, :current_screen?
|
@@ -36,10 +41,6 @@ module Uh
|
|
36
41
|
screens.any? { |screen| screen.include? client }
|
37
42
|
end
|
38
43
|
|
39
|
-
def arranger_for_current_tag
|
40
|
-
Column::Arranger.new(current_tag.columns, current_tag.geo)
|
41
|
-
end
|
42
|
-
|
43
44
|
def update_widgets
|
44
45
|
@widgets.each &:update
|
45
46
|
@widgets.each &:redraw
|
@@ -63,8 +64,7 @@ module Uh
|
|
63
64
|
def remove(client)
|
64
65
|
screen, tag, column = find_client client
|
65
66
|
column.remove client
|
66
|
-
|
67
|
-
tag.each_column &:arrange_clients
|
67
|
+
tag.arrange_columns
|
68
68
|
column.show_hide_clients
|
69
69
|
current_client.focus if current_client
|
70
70
|
update_widgets
|
@@ -94,14 +94,11 @@ module Uh
|
|
94
94
|
|
95
95
|
def handle_tag_set(tag_id)
|
96
96
|
return unless current_client && current_tag.id != tag_id
|
97
|
+
previous_tag_id = current_tag.id
|
97
98
|
remove client = current_client
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
Column::Arranger.new(tag.columns, tag.geo).redraw
|
102
|
-
tag.each_column &:arrange_clients
|
103
|
-
current_client.focus if current_client
|
104
|
-
update_widgets
|
99
|
+
handle_tag_sel tag_id
|
100
|
+
push client
|
101
|
+
handle_tag_sel previous_tag_id
|
105
102
|
end
|
106
103
|
|
107
104
|
def handle_column_sel(direction)
|
@@ -111,6 +108,13 @@ module Uh
|
|
111
108
|
update_widgets
|
112
109
|
end
|
113
110
|
|
111
|
+
def handle_column_mode_toggle
|
112
|
+
return unless current_column
|
113
|
+
current_column.mode_toggle
|
114
|
+
current_column.arrange_clients
|
115
|
+
current_column.show_hide_clients
|
116
|
+
end
|
117
|
+
|
114
118
|
def handle_client_sel(direction)
|
115
119
|
return unless current_client
|
116
120
|
current_column.clients.sel direction
|
@@ -125,10 +129,10 @@ module Uh
|
|
125
129
|
update_widgets
|
126
130
|
end
|
127
131
|
|
128
|
-
def handle_client_column_set(direction,
|
132
|
+
def handle_client_column_set(direction, mover: client_mover_for_current_tag)
|
129
133
|
return unless current_client
|
130
|
-
|
131
|
-
current_tag.
|
134
|
+
mover.move_current direction
|
135
|
+
current_tag.arrange_columns
|
132
136
|
current_tag.each_column &:show_hide_clients
|
133
137
|
update_widgets
|
134
138
|
end
|
@@ -157,5 +161,9 @@ module Uh
|
|
157
161
|
current_screen.tags << tag
|
158
162
|
end
|
159
163
|
end
|
164
|
+
|
165
|
+
def client_mover_for_current_tag
|
166
|
+
ClientColumnMover.new(current_tag.columns, current_tag.columns_max_count?)
|
167
|
+
end
|
160
168
|
end
|
161
169
|
end
|
data/spec/support/factories.rb
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
module Factories
|
2
|
+
class Entry
|
3
|
+
include Uh::GeoAccessors
|
4
|
+
|
5
|
+
attr_accessor :geo
|
6
|
+
|
7
|
+
def initialize(geo)
|
8
|
+
@geo = geo
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
2
12
|
def build_client
|
3
13
|
Uh::WM::Client.new(instance_spy Uh::Window)
|
4
14
|
end
|
5
15
|
|
16
|
+
def build_entry(geo = build_geo)
|
17
|
+
Entry.new(geo)
|
18
|
+
end
|
19
|
+
|
6
20
|
def build_geo(x = 0, y = 0, width = 640, height = 480)
|
7
21
|
Uh::Geo.new(x, y, width, height)
|
8
22
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
module Arrangers
|
4
|
+
describe FixedWidth do
|
5
|
+
let(:geo) { build_geo 20, 0, 640, 480 }
|
6
|
+
let(:entry) { build_entry }
|
7
|
+
let(:entries) { Container.new([entry, build_entry]) }
|
8
|
+
subject(:arranger) { described_class.new entries, geo, width: 300 }
|
9
|
+
|
10
|
+
describe '#arrange' do
|
11
|
+
it 'decreases first entry width as the optimal width' do
|
12
|
+
arranger.arrange
|
13
|
+
expect(entries[0].width).to eq 300
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'offsets entries with given geo' do
|
17
|
+
arranger.arrange
|
18
|
+
expect(entries[0].x).to eq 20
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'moves second entry aside the first entry' do
|
22
|
+
arranger.arrange
|
23
|
+
expect(entries[1].x).to eq 320
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'increases last entry width to occupy remaining width' do
|
27
|
+
arranger.arrange
|
28
|
+
expect(entries[1].width).to eq 340
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'copies given geo y' do
|
32
|
+
entries[0].y = nil
|
33
|
+
arranger.arrange
|
34
|
+
expect(entries[0].y).to eq 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'copies given geo height' do
|
38
|
+
entries[0].height = nil
|
39
|
+
arranger.arrange
|
40
|
+
expect(entries[0].height).to eq 480
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'without entry' do
|
44
|
+
let(:entries) { Container.new([]) }
|
45
|
+
|
46
|
+
it 'does not raise any error' do
|
47
|
+
expect { arranger.arrange }.not_to raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#max_count?' do
|
53
|
+
context 'when a new entry fits in current geo' do
|
54
|
+
let(:entries) { Container.new([entry]) }
|
55
|
+
|
56
|
+
it 'returns false' do
|
57
|
+
expect(arranger.max_count?).to be false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when current geo can not contain more entry' do
|
62
|
+
let(:entries) { Container.new([entry, entry.dup]) }
|
63
|
+
|
64
|
+
it 'returns true' do
|
65
|
+
expect(arranger.max_count?).to be true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
module Arrangers
|
4
|
+
describe Stack do
|
5
|
+
let(:entry) { build_entry }
|
6
|
+
let(:other_entry) { build_entry }
|
7
|
+
let(:entries) { Container.new([entry, other_entry]) }
|
8
|
+
let(:geo) { build_geo 0, 0, 300, 480 }
|
9
|
+
subject(:arranger) { described_class.new entries, geo }
|
10
|
+
|
11
|
+
describe '#arrange' do
|
12
|
+
it 'sets given geo on all entries' do
|
13
|
+
arranger.arrange
|
14
|
+
expect(entries.map(&:geo)).to all eq geo
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#each_visible' do
|
19
|
+
it 'yields current entry' do
|
20
|
+
expect { |b| arranger.each_visible &b }
|
21
|
+
.to yield_successive_args entry
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'with no current entry' do
|
25
|
+
let(:entries) { Container.new([]) }
|
26
|
+
|
27
|
+
it 'does not yield' do
|
28
|
+
expect { |b| arranger.each_visible &b }.not_to yield_control
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#each_hidden' do
|
34
|
+
it 'yields all entries except current one' do
|
35
|
+
expect { |b| arranger.each_hidden &b }
|
36
|
+
.to yield_successive_args other_entry
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
module Arrangers
|
4
|
+
describe VertTile do
|
5
|
+
let(:entry) { build_entry }
|
6
|
+
let(:other_entry) { build_entry }
|
7
|
+
let(:entries) { Container.new([entry, other_entry]) }
|
8
|
+
let(:geo) { build_geo 0, 0, 300, 480 }
|
9
|
+
subject(:arranger) { described_class.new entries, geo }
|
10
|
+
|
11
|
+
describe '#arrange' do
|
12
|
+
it 'sets x offset from given geo on all entries' do
|
13
|
+
arranger.arrange
|
14
|
+
expect(entries.map(&:x)).to all eq 0
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'sets width from given geo on all entries' do
|
18
|
+
arranger.arrange
|
19
|
+
expect(entries.map(&:width)).to all eq 300
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'splits entries height equally' do
|
23
|
+
arranger.arrange
|
24
|
+
expect(entries.map(&:height)).to all eq 239
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'adds a margin between entries' do
|
28
|
+
arranger.arrange
|
29
|
+
expect(entries[1].y - entries[0].height - entries[0].y).to eq 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#each_visible' do
|
34
|
+
it 'yields all entries' do
|
35
|
+
expect { |b| arranger.each_visible &b }
|
36
|
+
.to yield_successive_args entry, other_entry
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#each_hidden' do
|
41
|
+
it 'yields no entry' do
|
42
|
+
expect { |b| arranger.each_hidden &b }.not_to yield_control
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Uh
|
2
|
+
class Layout
|
3
|
+
describe ClientColumnMover do
|
4
|
+
let(:client) { build_client }
|
5
|
+
let(:column) { Column.new(build_geo) }
|
6
|
+
let(:columns) { Container.new([column]) }
|
7
|
+
let(:columns_max_count) { false }
|
8
|
+
subject(:mover) { described_class.new columns, columns_max_count }
|
9
|
+
|
10
|
+
describe '#move_current' do
|
11
|
+
shared_examples 'moves current client' do |expected_column_index|
|
12
|
+
it 'removes current client from origin column' do
|
13
|
+
mover.move_current :succ
|
14
|
+
expect(column).not_to include client
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'adds current client in the destination column' do
|
18
|
+
mover.move_current :succ
|
19
|
+
expect(columns[expected_column_index]).to include client
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'updates destination column as the current one' do
|
23
|
+
mover.move_current :succ
|
24
|
+
expect(columns.current).to be columns[expected_column_index]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'preserves current client as the current one' do
|
28
|
+
expect { mover.move_current :succ }
|
29
|
+
.not_to change { columns.current.current_client }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'given one column with one client' do
|
34
|
+
before { column << client }
|
35
|
+
|
36
|
+
include_examples 'moves current client', 1
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'given one column with many clients' do
|
40
|
+
before { column << client << client.dup }
|
41
|
+
|
42
|
+
include_examples 'moves current client', 1
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'given two columns' do
|
46
|
+
let(:columns) { Container.new([column, Column.new(build_geo)]) }
|
47
|
+
|
48
|
+
before { columns[1] << client.dup }
|
49
|
+
|
50
|
+
context 'when origin column has many clients' do
|
51
|
+
before { column << client << client.dup }
|
52
|
+
|
53
|
+
include_examples 'moves current client', 1
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when origin column has one client' do
|
57
|
+
before { column << client }
|
58
|
+
|
59
|
+
include_examples 'moves current client', 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#get_or_create_column' do
|
65
|
+
let(:columns) { Container.new([column, Column.new(build_geo)]) }
|
66
|
+
|
67
|
+
it 'returns the consecutive column in given direction' do
|
68
|
+
expect(mover.get_or_create_column :succ).to be columns[1]
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when current column is last in given direction' do
|
72
|
+
before { columns.current = columns[1] }
|
73
|
+
|
74
|
+
context 'when max columns count is not reached' do
|
75
|
+
it 'appends a new column' do
|
76
|
+
expect(mover.get_or_create_column :succ).to be columns[2]
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'prepends a new column' do
|
80
|
+
columns.current = columns[0]
|
81
|
+
expect(mover.get_or_create_column :pred).to be columns[0]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when max columns count is reached' do
|
86
|
+
let(:columns_max_count) { true }
|
87
|
+
|
88
|
+
it 'returns the consecutive column in given direction' do
|
89
|
+
expect(mover.get_or_create_column :succ).to be columns[0]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -5,7 +5,7 @@ module Uh
|
|
5
5
|
let(:other_geo) { build_geo 640, 0, 320, 240 }
|
6
6
|
let(:client) { build_client }
|
7
7
|
let(:other_client) { build_client }
|
8
|
-
subject(:column) { described_class.new
|
8
|
+
subject(:column) { described_class.new geo }
|
9
9
|
|
10
10
|
it 'has a copy to given geo' do
|
11
11
|
expect(column.geo).to eq(geo).and not_be geo
|
@@ -15,6 +15,10 @@ module Uh
|
|
15
15
|
expect(column).to be_empty
|
16
16
|
end
|
17
17
|
|
18
|
+
it 'has :stack as default mode' do
|
19
|
+
expect(column.mode).to be :stack
|
20
|
+
end
|
21
|
+
|
18
22
|
describe '#<<' do
|
19
23
|
before { column << client }
|
20
24
|
|
@@ -31,13 +35,43 @@ module Uh
|
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
38
|
+
describe '#mode_toggle' do
|
39
|
+
it 'toggles mode from stack to tile' do
|
40
|
+
expect { column.mode_toggle }
|
41
|
+
.to change { column.mode }.from(:stack).to(:tile)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'toggles mode from tile to stack' do
|
45
|
+
column.mode_toggle
|
46
|
+
expect { column.mode_toggle }
|
47
|
+
.to change { column.mode }.from(:tile).to(:stack)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#arranger' do
|
53
|
+
context 'when column mode is stack' do
|
54
|
+
it 'returns a stack arranger' do
|
55
|
+
expect(column.arranger).to be_an Arrangers::Stack
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when column mode is tile' do
|
60
|
+
it 'returns a vertical tile arranger' do
|
61
|
+
column.mode_toggle
|
62
|
+
expect(column.arranger).to be_an Arrangers::VertTile
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
34
67
|
describe '#arrange_clients' do
|
35
68
|
before { column << client << other_client }
|
36
69
|
|
37
|
-
it '
|
38
|
-
|
70
|
+
it 'arranges clients' do
|
71
|
+
arranger = instance_spy Arrangers::Stack
|
72
|
+
allow(column).to receive(:arranger) { arranger }
|
73
|
+
expect(arranger).to receive :arrange
|
39
74
|
column.arrange_clients
|
40
|
-
expect(column.clients.map(&:geo)).to all eq column.geo
|
41
75
|
end
|
42
76
|
|
43
77
|
it 'moveresizes clients' do
|
@@ -47,18 +81,24 @@ module Uh
|
|
47
81
|
end
|
48
82
|
|
49
83
|
describe '#show_hide_clients' do
|
50
|
-
|
84
|
+
let(:arranger) { double 'arranger', each_visible: nil, each_hidden: nil }
|
51
85
|
|
52
|
-
it 'shows
|
86
|
+
it 'shows visible clients when they are hidden' do
|
87
|
+
allow(arranger).to receive(:each_visible)
|
88
|
+
.and_yield(client.hide)
|
89
|
+
.and_yield(other_client.show)
|
90
|
+
expect(client).to receive :show
|
53
91
|
expect(other_client).not_to receive :show
|
54
|
-
|
55
|
-
column.show_hide_clients
|
92
|
+
column.show_hide_clients arranger: arranger
|
56
93
|
end
|
57
94
|
|
58
|
-
it 'hides
|
59
|
-
|
60
|
-
|
61
|
-
|
95
|
+
it 'hides hidden clients except those already hidden' do
|
96
|
+
allow(arranger).to receive(:each_hidden)
|
97
|
+
.and_yield(client.show)
|
98
|
+
.and_yield(other_client.hide)
|
99
|
+
expect(client).to receive :hide
|
100
|
+
expect(other_client).not_to receive :hide
|
101
|
+
column.show_hide_clients arranger: arranger
|
62
102
|
end
|
63
103
|
end
|
64
104
|
end
|
@@ -42,9 +42,9 @@ module Uh
|
|
42
42
|
end
|
43
43
|
|
44
44
|
context 'when given argument is not an entry' do
|
45
|
-
it '
|
46
|
-
expect { container.current = :
|
47
|
-
.
|
45
|
+
it 'raises ArgumentError' do
|
46
|
+
expect { container.current = :unknown_entry }
|
47
|
+
.to raise_error Layout::ArgumentError
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -91,10 +91,10 @@ module Uh
|
|
91
91
|
end
|
92
92
|
|
93
93
|
context 'when given entry is the only one' do
|
94
|
-
let(:entries) { [:
|
94
|
+
let(:entries) { [:bar] }
|
95
95
|
|
96
96
|
it 'has no more current entry' do
|
97
|
-
container.remove :
|
97
|
+
container.remove :bar
|
98
98
|
expect(container.current).to be nil
|
99
99
|
end
|
100
100
|
end
|
@@ -4,7 +4,7 @@ module Uh
|
|
4
4
|
let(:geo) { build_geo }
|
5
5
|
let(:other_geo) { build_geo 640, 0, 320, 240 }
|
6
6
|
let(:client) { build_client }
|
7
|
-
subject(:screen) { described_class.new
|
7
|
+
subject(:screen) { described_class.new 0, geo }
|
8
8
|
|
9
9
|
it 'has one default tag with id 1 assigned' do
|
10
10
|
expect(screen.tags).to include an_object_having_attributes id: '1'
|
data/spec/uh/layout/tag_spec.rb
CHANGED
@@ -6,11 +6,12 @@ module Uh
|
|
6
6
|
let(:client) { build_client }
|
7
7
|
let(:other_client) { build_client }
|
8
8
|
let(:column) { Column.new(geo) }
|
9
|
-
subject(:tag) { described_class.new
|
9
|
+
subject(:tag) { described_class.new '1', geo }
|
10
10
|
|
11
11
|
describe '.new' do
|
12
12
|
it 'raises error unless id converts to string' do
|
13
|
-
expect { described_class.new
|
13
|
+
expect { described_class.new 1, geo }
|
14
|
+
.to raise_error(Layout::ArgumentError)
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -40,7 +41,7 @@ module Uh
|
|
40
41
|
end
|
41
42
|
|
42
43
|
it 'returns the new column' do
|
43
|
-
expect(tag.current_column_or_create).to
|
44
|
+
expect(tag.current_column_or_create).to be tag.columns.fetch 0
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
@@ -57,6 +58,34 @@ module Uh
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
61
|
+
|
62
|
+
describe '#arranger' do
|
63
|
+
it 'returns a fixed width arranger' do
|
64
|
+
expect(tag.arranger).to be_an Arrangers::FixedWidth
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#arrange_columns' do
|
69
|
+
before { tag.columns << column }
|
70
|
+
|
71
|
+
it 'purges empty columns' do
|
72
|
+
tag.arrange_columns
|
73
|
+
expect(tag.columns).to be_empty
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'arranges columns' do
|
77
|
+
arranger = instance_spy Arrangers::FixedWidth
|
78
|
+
allow(tag).to receive(:arranger) { arranger }
|
79
|
+
expect(arranger).to receive :arrange
|
80
|
+
tag.arrange_columns
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'arranges columns clients' do
|
84
|
+
column << client
|
85
|
+
expect(column).to receive :arrange_clients
|
86
|
+
tag.arrange_columns
|
87
|
+
end
|
88
|
+
end
|
60
89
|
end
|
61
90
|
end
|
62
91
|
end
|
data/spec/uh/layout_spec.rb
CHANGED
@@ -23,17 +23,6 @@ module Uh
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
describe '#arranger_for_current_tag' do
|
27
|
-
it 'returns an arranger for current tag columns and geo' do
|
28
|
-
expect(layout.arranger_for_current_tag)
|
29
|
-
.to respond_to(:update_geos)
|
30
|
-
.and have_attributes(
|
31
|
-
columns: layout.current_tag.columns,
|
32
|
-
geo: layout.current_tag.geo
|
33
|
-
)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
26
|
describe '#update_widgets' do
|
38
27
|
it 'updates widgets' do
|
39
28
|
expect(layout.widgets).to all receive :update
|
@@ -110,13 +99,8 @@ module Uh
|
|
110
99
|
expect(layout).not_to include client
|
111
100
|
end
|
112
101
|
|
113
|
-
it '
|
114
|
-
|
115
|
-
layout.remove client
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'arranges clients in removed client tag columns' do
|
119
|
-
expect(layout.current_tag.columns).to all receive :arrange_clients
|
102
|
+
it 'arranges columns in removed client tag' do
|
103
|
+
expect(layout.current_tag).to receive :arrange_columns
|
120
104
|
layout.remove client
|
121
105
|
end
|
122
106
|
|
@@ -229,8 +213,8 @@ module Uh
|
|
229
213
|
expect(origin_tag).not_to include client
|
230
214
|
end
|
231
215
|
|
232
|
-
it '
|
233
|
-
expect(layout
|
216
|
+
it 'removes current client from layout' do
|
217
|
+
expect(layout).to receive(:remove).with client
|
234
218
|
layout.handle_tag_set '2'
|
235
219
|
end
|
236
220
|
|
@@ -245,10 +229,9 @@ module Uh
|
|
245
229
|
expect(dest_tag).to include client
|
246
230
|
end
|
247
231
|
|
248
|
-
it '
|
249
|
-
layout.current_screen.tags << tag = Layout::Tag.new('2', geo)
|
250
|
-
expect(tag.current_column_or_create).to receive :arrange_clients
|
232
|
+
it 'preserves current tag' do
|
251
233
|
layout.handle_tag_set '2'
|
234
|
+
expect(layout.current_tag.id).to eq '1'
|
252
235
|
end
|
253
236
|
|
254
237
|
it 'updates widgets' do
|
@@ -290,6 +273,33 @@ module Uh
|
|
290
273
|
end
|
291
274
|
end
|
292
275
|
|
276
|
+
describe '#handle_column_mode_toggle' do
|
277
|
+
context 'without column' do
|
278
|
+
it 'does not raise any error' do
|
279
|
+
expect { layout.handle_column_mode_toggle }.not_to raise_error
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'with a column' do
|
284
|
+
before { layout << client }
|
285
|
+
|
286
|
+
it 'toggles current column mode' do
|
287
|
+
expect(layout.current_column).to receive :mode_toggle
|
288
|
+
layout.handle_column_mode_toggle
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'arranges current column clients' do
|
292
|
+
expect(layout.current_column).to receive :arrange_clients
|
293
|
+
layout.handle_column_mode_toggle
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'shows and hides clients in current column' do
|
297
|
+
expect(layout.current_column).to receive :show_hide_clients
|
298
|
+
layout.handle_column_mode_toggle
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
293
303
|
describe '#handle_client_sel' do
|
294
304
|
context 'without client' do
|
295
305
|
it 'does not raise any error' do
|
@@ -358,22 +368,17 @@ module Uh
|
|
358
368
|
end
|
359
369
|
|
360
370
|
context 'with one column and two clients' do
|
361
|
-
let(:
|
371
|
+
let(:mover) { instance_spy Layout::ClientColumnMover }
|
362
372
|
|
363
373
|
before { layout << other_client << client }
|
364
374
|
|
365
|
-
it 'moves current client with column
|
366
|
-
expect(
|
367
|
-
layout.handle_client_column_set :succ,
|
368
|
-
end
|
369
|
-
|
370
|
-
it 'updates columns geos with column arranger' do
|
371
|
-
expect(arranger).to receive :update_geos
|
372
|
-
layout.handle_client_column_set :succ, arranger: arranger
|
375
|
+
it 'moves current client with given client column mover' do
|
376
|
+
expect(mover).to receive(:move_current).with(:succ)
|
377
|
+
layout.handle_client_column_set :succ, mover: mover
|
373
378
|
end
|
374
379
|
|
375
|
-
it 'arranges
|
376
|
-
expect(layout.current_tag
|
380
|
+
it 'arranges current tag columns' do
|
381
|
+
expect(layout.current_tag).to receive :arrange_columns
|
377
382
|
layout.handle_client_column_set :succ
|
378
383
|
end
|
379
384
|
|
data/uh-layout.gemspec
CHANGED
@@ -15,8 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = s.files.grep(/\Abin\//) { |f| File.basename(f) }
|
16
16
|
|
17
17
|
|
18
|
-
s.
|
19
|
-
|
18
|
+
s.add_development_dependency 'uh'
|
20
19
|
s.add_development_dependency 'rake', '~> 10.4'
|
21
20
|
s.add_development_dependency 'rspec', '~> 3.2'
|
22
21
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uh-layout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibault Jouan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uh
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,23 +60,28 @@ extra_rdoc_files: []
|
|
60
60
|
files:
|
61
61
|
- ".gitignore"
|
62
62
|
- ".rspec"
|
63
|
+
- ".travis.yml"
|
63
64
|
- Gemfile
|
64
|
-
- Gemfile-custom.rb
|
65
65
|
- Guardfile
|
66
66
|
- Rakefile
|
67
67
|
- lib/uh/layout.rb
|
68
|
+
- lib/uh/layout/arrangers/fixed_width.rb
|
69
|
+
- lib/uh/layout/arrangers/stack.rb
|
70
|
+
- lib/uh/layout/arrangers/vert_tile.rb
|
68
71
|
- lib/uh/layout/bar.rb
|
72
|
+
- lib/uh/layout/client_column_mover.rb
|
69
73
|
- lib/uh/layout/column.rb
|
70
|
-
- lib/uh/layout/column/arranger.rb
|
71
74
|
- lib/uh/layout/container.rb
|
72
75
|
- lib/uh/layout/dumper.rb
|
73
|
-
- lib/uh/layout/geo_accessors.rb
|
74
76
|
- lib/uh/layout/screen.rb
|
75
77
|
- lib/uh/layout/tag.rb
|
76
78
|
- lib/uh/layout/version.rb
|
77
79
|
- spec/spec_helper.rb
|
78
80
|
- spec/support/factories.rb
|
79
|
-
- spec/uh/layout/
|
81
|
+
- spec/uh/layout/arrangers/fixed_width_spec.rb
|
82
|
+
- spec/uh/layout/arrangers/stack_spec.rb
|
83
|
+
- spec/uh/layout/arrangers/vert_tile_spec.rb
|
84
|
+
- spec/uh/layout/client_column_mover_spec.rb
|
80
85
|
- spec/uh/layout/column_spec.rb
|
81
86
|
- spec/uh/layout/container_spec.rb
|
82
87
|
- spec/uh/layout/screen_spec.rb
|
@@ -109,7 +114,10 @@ summary: Simple layout for uh
|
|
109
114
|
test_files:
|
110
115
|
- spec/spec_helper.rb
|
111
116
|
- spec/support/factories.rb
|
112
|
-
- spec/uh/layout/
|
117
|
+
- spec/uh/layout/arrangers/fixed_width_spec.rb
|
118
|
+
- spec/uh/layout/arrangers/stack_spec.rb
|
119
|
+
- spec/uh/layout/arrangers/vert_tile_spec.rb
|
120
|
+
- spec/uh/layout/client_column_mover_spec.rb
|
113
121
|
- spec/uh/layout/column_spec.rb
|
114
122
|
- spec/uh/layout/container_spec.rb
|
115
123
|
- spec/uh/layout/screen_spec.rb
|
data/Gemfile-custom.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
module Uh
|
2
|
-
class Layout
|
3
|
-
class Column
|
4
|
-
class Arranger
|
5
|
-
OPTIMAL_WIDTH = 484
|
6
|
-
|
7
|
-
attr_reader :columns, :geo
|
8
|
-
|
9
|
-
def initialize(columns, geo, column_width: OPTIMAL_WIDTH)
|
10
|
-
@columns = columns
|
11
|
-
@geo = geo
|
12
|
-
@column_width = column_width
|
13
|
-
end
|
14
|
-
|
15
|
-
def redraw
|
16
|
-
purge
|
17
|
-
update_geos
|
18
|
-
yield if block_given?
|
19
|
-
end
|
20
|
-
|
21
|
-
def purge
|
22
|
-
@columns.remove_if &:empty?
|
23
|
-
end
|
24
|
-
|
25
|
-
def move_current_client(direction)
|
26
|
-
return self unless @columns.current.current_client
|
27
|
-
@columns.current.remove client = @columns.current.current_client
|
28
|
-
dest_column = get_or_create_column direction
|
29
|
-
dest_column << client
|
30
|
-
dest_column.current_client = client
|
31
|
-
purge
|
32
|
-
@columns.current = dest_column
|
33
|
-
self
|
34
|
-
end
|
35
|
-
|
36
|
-
def get_or_create_column(direction)
|
37
|
-
if candidate = @columns.get(direction)
|
38
|
-
candidate
|
39
|
-
elsif max_columns_count?
|
40
|
-
@columns.get direction, cycle: true
|
41
|
-
else
|
42
|
-
Column.new(@geo).tap do |o|
|
43
|
-
case direction
|
44
|
-
when :pred then @columns.unshift o
|
45
|
-
when :succ then @columns << o
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def max_columns_count?
|
52
|
-
(@geo.width / (@columns.size + 1)) < @column_width
|
53
|
-
end
|
54
|
-
|
55
|
-
def update_geos
|
56
|
-
return if @columns.empty?
|
57
|
-
@columns.each_with_index do |column, i|
|
58
|
-
column.x = @column_width * i + @geo.x
|
59
|
-
column.width = @column_width
|
60
|
-
end
|
61
|
-
@columns.last.width = @geo.width - (@columns.last.x - @geo.x)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,181 +0,0 @@
|
|
1
|
-
module Uh
|
2
|
-
class Layout
|
3
|
-
class Column
|
4
|
-
describe Arranger do
|
5
|
-
let(:geo) { build_geo }
|
6
|
-
let(:client) { build_client }
|
7
|
-
let(:column_width) { 300 }
|
8
|
-
let(:column) { Column.new(geo) }
|
9
|
-
let(:columns) { Container.new([column]) }
|
10
|
-
subject(:arranger) { described_class.new columns, geo,
|
11
|
-
column_width: column_width }
|
12
|
-
|
13
|
-
describe '#redraw' do
|
14
|
-
it 'purges columns' do
|
15
|
-
expect(arranger).to receive :purge
|
16
|
-
arranger.redraw
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'updates columns geo' do
|
20
|
-
expect(arranger).to receive :update_geos
|
21
|
-
arranger.redraw
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'yields given block' do
|
25
|
-
expect { |b| arranger.redraw &b }.to yield_control
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe '#purge' do
|
30
|
-
it 'removes empty columns' do
|
31
|
-
arranger.purge
|
32
|
-
expect(columns).to be_empty
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#move_current_client' do
|
37
|
-
shared_examples 'moves current client' do |expected_column_index|
|
38
|
-
it 'removes current client from origin column' do
|
39
|
-
arranger.move_current_client :succ
|
40
|
-
expect(column).not_to include client
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'adds current client in the destination column' do
|
44
|
-
arranger.move_current_client :succ
|
45
|
-
expect(columns[expected_column_index]).to include client
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'updates destination column as the current one' do
|
49
|
-
arranger.move_current_client :succ
|
50
|
-
expect(columns.current).to be columns[expected_column_index]
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'preserves current client as the current one' do
|
54
|
-
expect { arranger.move_current_client :succ }
|
55
|
-
.not_to change { columns.current.current_client }
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'does not leave empty columns' do
|
59
|
-
expect(columns.none? &:empty?).to be true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'returns self' do
|
64
|
-
expect(arranger.move_current_client :succ).to be arranger
|
65
|
-
end
|
66
|
-
|
67
|
-
context 'given one column with one client' do
|
68
|
-
before { column << client }
|
69
|
-
|
70
|
-
include_examples 'moves current client', 0
|
71
|
-
end
|
72
|
-
|
73
|
-
context 'given one column with many clients' do
|
74
|
-
before { column << client << client.dup }
|
75
|
-
|
76
|
-
include_examples 'moves current client', 1
|
77
|
-
end
|
78
|
-
|
79
|
-
context 'given two columns' do
|
80
|
-
let(:columns) { Container.new([column, Column.new(geo)]) }
|
81
|
-
|
82
|
-
before { columns[1] << client.dup }
|
83
|
-
|
84
|
-
context 'when origin column has many clients' do
|
85
|
-
before { column << client << client.dup }
|
86
|
-
|
87
|
-
include_examples 'moves current client', 1
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'when origin column has one client' do
|
91
|
-
before { column << client }
|
92
|
-
|
93
|
-
include_examples 'moves current client', 0
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
describe '#get_or_create_column' do
|
99
|
-
let(:columns) { Container.new([column, Column.new(geo)]) }
|
100
|
-
|
101
|
-
it 'returns the consecutive column in given direction' do
|
102
|
-
expect(arranger.get_or_create_column :succ).to be columns[1]
|
103
|
-
end
|
104
|
-
|
105
|
-
context 'when current column is last in given direction' do
|
106
|
-
before { columns.current = columns[1] }
|
107
|
-
|
108
|
-
context 'when max columns count is not reached' do
|
109
|
-
before { geo.width = 4096 }
|
110
|
-
|
111
|
-
it 'appends a new column' do
|
112
|
-
expect(arranger.get_or_create_column :succ).to be columns[2]
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'prepends a new column' do
|
116
|
-
columns.current = columns[0]
|
117
|
-
expect(arranger.get_or_create_column :pred).to be columns[0]
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context 'when max columns count is reached' do
|
122
|
-
it 'returns the consecutive column in given direction' do
|
123
|
-
expect(arranger.get_or_create_column :succ).to be columns[0]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe '#max_columns_count?' do
|
130
|
-
context 'when a new column fits in current geo' do
|
131
|
-
it 'returns false' do
|
132
|
-
expect(arranger.max_columns_count?).to be false
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context 'when current geo can not contain more column' do
|
137
|
-
let(:columns) { Container.new([column, Column.new(geo)]) }
|
138
|
-
|
139
|
-
it 'returns true' do
|
140
|
-
expect(arranger.max_columns_count?).to be true
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
describe '#update_geos' do
|
146
|
-
let(:columns) { Container.new([column, Column.new(geo)]) }
|
147
|
-
|
148
|
-
before { geo.x = 20 }
|
149
|
-
|
150
|
-
it 'decreases first column width as the optimal column width' do
|
151
|
-
arranger.update_geos
|
152
|
-
expect(columns[0].width).to eq 300
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'offsets each column with given geo' do
|
156
|
-
arranger.update_geos
|
157
|
-
expect(columns[0].x).to eq 20
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'moves second column aside the first column' do
|
161
|
-
arranger.update_geos
|
162
|
-
expect(columns[1].x).to eq 320
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'increases last column width to occupy remaining width' do
|
166
|
-
arranger.update_geos
|
167
|
-
expect(columns[1].width).to eq 340
|
168
|
-
end
|
169
|
-
|
170
|
-
context 'without columns' do
|
171
|
-
let(:columns) { Container.new([]) }
|
172
|
-
|
173
|
-
it 'does not raise any error' do
|
174
|
-
expect { arranger.update_geos }.not_to raise_error
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|