shoes-swt 4.0.0.pre3 → 4.0.0.pre4

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/bin/shoes-swt +2 -2
  3. data/lib/shoes/swt.rb +90 -72
  4. data/lib/shoes/swt/app.rb +5 -0
  5. data/lib/shoes/swt/click_listener.rb +0 -1
  6. data/lib/shoes/swt/color.rb +7 -7
  7. data/lib/shoes/swt/common/fill.rb +9 -3
  8. data/lib/shoes/swt/common/painter.rb +14 -11
  9. data/lib/shoes/swt/common/stroke.rb +9 -3
  10. data/lib/shoes/swt/dialog.rb +2 -2
  11. data/lib/shoes/swt/gradient.rb +13 -11
  12. data/lib/shoes/swt/image.rb +1 -3
  13. data/lib/shoes/swt/image_pattern.rb +2 -2
  14. data/lib/shoes/swt/line.rb +0 -2
  15. data/lib/shoes/swt/list_box.rb +6 -1
  16. data/lib/shoes/swt/progress.rb +9 -8
  17. data/lib/shoes/swt/redrawing_aspect.rb +1 -1
  18. data/lib/shoes/swt/shape.rb +3 -1
  19. data/lib/shoes/swt/shoes_layout.rb +38 -24
  20. data/lib/shoes/swt/text_block.rb +41 -12
  21. data/lib/shoes/swt/text_block/cursor_painter.rb +1 -1
  22. data/lib/shoes/swt/text_block/fitter.rb +8 -3
  23. data/lib/shoes/swt/text_block/painter.rb +9 -28
  24. data/lib/shoes/swt/text_block/text_segment.rb +16 -6
  25. data/lib/shoes/swt/text_block/text_segment_collection.rb +17 -5
  26. data/lib/shoes/swt/tooling/leak_hunter.rb +1 -1
  27. data/lib/shoes/swt/version.rb +1 -1
  28. data/shoes-swt.gemspec +2 -2
  29. data/spec/shoes/cli_spec.rb +1 -1
  30. data/spec/shoes/swt/app_spec.rb +15 -6
  31. data/spec/shoes/swt/color_spec.rb +8 -7
  32. data/spec/shoes/swt/common/painter_spec.rb +30 -5
  33. data/spec/shoes/swt/disposed_protection_spec.rb +0 -1
  34. data/spec/shoes/swt/font_spec.rb +2 -2
  35. data/spec/shoes/swt/gradient_spec.rb +5 -2
  36. data/spec/shoes/swt/image_pattern_spec.rb +11 -1
  37. data/spec/shoes/swt/list_box_spec.rb +24 -4
  38. data/spec/shoes/swt/mouse_move_listener_spec.rb +1 -1
  39. data/spec/shoes/swt/oval_spec.rb +0 -1
  40. data/spec/shoes/swt/progress_spec.rb +3 -4
  41. data/spec/shoes/swt/radio_group_spec.rb +4 -4
  42. data/spec/shoes/swt/radio_spec.rb +1 -1
  43. data/spec/shoes/swt/shape_spec.rb +8 -1
  44. data/spec/shoes/swt/shared_examples/paintable.rb +0 -1
  45. data/spec/shoes/swt/shared_examples/pattern.rb +2 -6
  46. data/spec/shoes/swt/shared_examples/swt_app_context.rb +0 -1
  47. data/spec/shoes/swt/shell_control_listener_spec.rb +4 -4
  48. data/spec/shoes/swt/shoes_layout_spec.rb +84 -0
  49. data/spec/shoes/swt/slot_spec.rb +1 -1
  50. data/spec/shoes/swt/spec_helper.rb +2 -0
  51. data/spec/shoes/swt/text_block/cursor_painter_spec.rb +2 -2
  52. data/spec/shoes/swt/text_block/fitter_spec.rb +19 -4
  53. data/spec/shoes/swt/text_block/painter_spec.rb +15 -189
  54. data/spec/shoes/swt/text_block/text_segment_collection_spec.rb +10 -5
  55. data/spec/shoes/swt/text_block/text_segment_spec.rb +4 -4
  56. data/spec/shoes/swt/text_block_spec.rb +28 -15
  57. metadata +8 -6
@@ -28,4 +28,3 @@ shared_context "swt app" do
28
28
  gui: parent, x_dimension: double.as_null_object,
29
29
  y_dimension: double.as_null_object)}
30
30
  end
31
-
@@ -6,18 +6,18 @@ describe Shoes::Swt::ShellControlListener do
6
6
  let(:resize_callbacks) {[]}
7
7
  let(:dsl_app) {double('DSL App', resize_callbacks: resize_callbacks).as_null_object}
8
8
  let(:block) {double 'Block', call: nil}
9
- let(:resize_event) {double'resize_event', widget: shell}
9
+ let(:resize_event) {double 'resize_event', widget: shell}
10
10
  let(:real) {double('Swt Real').as_null_object}
11
11
 
12
12
  subject {Shoes::Swt::ShellControlListener.new(app)}
13
13
  before :each do
14
14
  subject.controlResized(resize_event)
15
15
  end
16
-
16
+
17
17
  describe 'resize' do
18
- let(:resize_callbacks ){[block]}
18
+ let(:resize_callbacks){[block]}
19
19
  it 'calls the resize block' do
20
- expect(block).to have_received(:call)
20
+ expect(block).to have_received(:call)
21
21
  end
22
22
  end
23
23
  end
@@ -0,0 +1,84 @@
1
+ require 'shoes/swt/spec_helper'
2
+
3
+ describe Shoes::Swt::ShoesLayout do
4
+
5
+ subject do
6
+ result = Shoes::Swt::ShoesLayout.new
7
+ result.gui_app = gui_app
8
+ result
9
+ end
10
+
11
+ let(:gui_app) { double('gui_app', dsl: dsl, real: real, shell: shell) }
12
+ let(:real) { double('real', set_size: nil,
13
+ location: location, :location= => nil) }
14
+ let(:size) { double('size', height: 0, width: 0) }
15
+ let(:location) { double('location', :y= => nil) }
16
+ let(:dsl) { double('dsl', top_slot: top_slot,
17
+ height: 100, width: 100) }
18
+ let(:top_slot) { double('top_slot', contents_alignment: 0,
19
+ :width= => nil, :height= => nil) }
20
+ let(:shell) { double('shell', vertical_bar: vertical_bar) }
21
+ let(:vertical_bar) { double('vertical_bar', :increment= => nil,
22
+ :visible= => nil, :maximum= => nil,
23
+ :thumb= => nil, thumb: 0) }
24
+
25
+ let(:scroll_height) { dsl.height * 2 }
26
+
27
+ before do
28
+ allow(real).to receive(:compute_trim) do |_, _, width, height|
29
+ double('size', width: width, height: height)
30
+ end
31
+ end
32
+
33
+ it "sets size on real element" do
34
+ expect(real).to receive(:set_size).with(dsl.width, dsl.height)
35
+ subject.layout
36
+ end
37
+
38
+ it "sets height on real element to scrollable height when that's bigger" do
39
+ when_contents_scroll
40
+ expect(real).to receive(:set_size).with(dsl.width, scroll_height)
41
+ subject.layout
42
+ end
43
+
44
+ it "sets size on top slot" do
45
+ expect(top_slot).to receive(:width=).with(dsl.width)
46
+ expect(top_slot).to receive(:height=).with(dsl.height)
47
+ subject.layout
48
+ end
49
+
50
+ it "sets height on top slot to scrollable height when that's bigger" do
51
+ when_contents_scroll
52
+ expect(top_slot).to receive(:width=).with(dsl.width)
53
+ expect(top_slot).to receive(:height=).with(scroll_height)
54
+ subject.layout
55
+ end
56
+
57
+ it "shows scrollbar" do
58
+ when_contents_scroll
59
+ expect(vertical_bar).to receive(:visible=).with(true)
60
+ subject.layout
61
+ end
62
+
63
+ it "updates settings on scrollbar when visible" do
64
+ when_contents_scroll
65
+ [:thumb=, :maximum=, :increment=].each do |m|
66
+ expect(vertical_bar).to receive(m)
67
+ end
68
+ subject.layout
69
+ end
70
+
71
+ it "hides scrollbar" do
72
+ expect(vertical_bar).to receive(:visible=).with(false)
73
+ subject.layout
74
+ end
75
+
76
+ it "sets gui location when scrollbar hidden" do
77
+ expect(real).to receive(:location=).with(location)
78
+ subject.layout
79
+ end
80
+
81
+ def when_contents_scroll
82
+ allow(top_slot).to receive(:contents_alignment) { scroll_height }
83
+ end
84
+ end
@@ -21,4 +21,4 @@ describe Shoes::Swt::Slot do
21
21
  expect(content).to have_received :hide
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -1,6 +1,8 @@
1
1
  require "shoes/swt"
2
2
  require "spec_helper"
3
3
 
4
+ Shoes.load_backend("swt").initialize_backend
5
+
4
6
  RSpec.configure do |config|
5
7
  config.before(:each) do
6
8
  allow(Swt).to receive(:event_loop)
@@ -3,7 +3,7 @@ require 'shoes/swt/spec_helper'
3
3
  describe Shoes::Swt::TextBlock::CursorPainter do
4
4
  include_context "swt app"
5
5
 
6
- let(:dsl) { double("dsl", app: shoes_app, textcursor: textcursor, has_textcursor?: true) }
6
+ let(:dsl) { double("dsl", app: shoes_app, textcursor: textcursor, textcursor?: true) }
7
7
  let(:textcursor) { double("textcursor", left:0, top: 0, height: 10) }
8
8
  let(:segment_collection) { double('segment collection',
9
9
  cursor_height: 12,
@@ -21,7 +21,7 @@ describe Shoes::Swt::TextBlock::CursorPainter do
21
21
  end
22
22
 
23
23
  it "shouldn't do anything without text cursor" do
24
- allow(dsl).to receive(:has_textcursor?) { nil}
24
+ allow(dsl).to receive(:textcursor?) { nil}
25
25
  subject.draw
26
26
  expect(dsl).to_not have_received(:textcursor=)
27
27
  end
@@ -144,18 +144,19 @@ describe Shoes::Swt::TextBlock::Fitter do
144
144
  context "to empty first segment" do
145
145
  before(:each) do
146
146
  allow(dsl).to receive_messages(containing_width: 100)
147
+ expect(segment).to receive(:fill_background=).with(true)
147
148
  end
148
149
 
149
150
  it "rolls to second segment when 0 remaining width" do
150
151
  allow(dsl).to receive_messages(desired_width: 0)
151
152
  segments = when_fit_at(x: 0, y: 75, next_line_start: 95)
152
- expect_segments(segments, [26, 76], [1, 97])
153
+ expect_segments(segments, [26, 76], [1, 96])
153
154
  end
154
155
 
155
156
  it "rolls to second segment when negative remaining width" do
156
157
  allow(dsl).to receive_messages(desired_width: -1)
157
158
  segments = when_fit_at(x: 0, y: 75, next_line_start: 95)
158
- expect_segments(segments, [26, 76], [1, 97])
159
+ expect_segments(segments, [26, 76], [1, 96])
159
160
  end
160
161
  end
161
162
 
@@ -174,13 +175,27 @@ describe Shoes::Swt::TextBlock::Fitter do
174
175
  it "bumps down a line if not at start" do
175
176
  allow(dsl).to receive_messages(element_left: 20, left: 20)
176
177
  segments = when_fit_at(x: 20, y: 75, next_line_start: 95)
177
- expect_segments(segments, [20, 76], [1, 96])
178
+ expect_segments(segments, [20, 76], [1, 95])
178
179
  end
179
180
 
180
181
  it "if unbounded height, still bumps down properly" do
181
182
  allow(dsl).to receive_messages(absolute_top: 95, element_left: 20, left: 20, margin_left: 1)
182
183
  segments = when_fit_at(x: 20, y: 75, next_line_start: 95)
183
- expect_segments(segments, [20, 76], [1, 96])
184
+ expect_segments(segments, [20, 76], [1, 95])
185
+ end
186
+ end
187
+
188
+ context "doesn't fit" do
189
+ it "with no width and unbounded height" do
190
+ allow(dsl).to receive_messages(desired_width: 0)
191
+ segments = when_fit_at(x: 0, y: 0, next_line_start: 0)
192
+ expect(segments).to be_empty
193
+ end
194
+
195
+ it "with no width and 0 height" do
196
+ allow(dsl).to receive_messages(desired_width: 0, containing_width: 0)
197
+ segments = when_fit_at(x: 0, y: 0, next_line_start: 1)
198
+ expect(segments).to be_empty
184
199
  end
185
200
  end
186
201
  end
@@ -3,210 +3,36 @@ require 'shoes/swt/spec_helper'
3
3
  describe Shoes::Swt::TextBlock::Painter do
4
4
  include_context "swt app"
5
5
 
6
- let(:dsl_style) { {justify: true, leading: 10, underline: "single"} }
7
- let(:gui) { double("gui", dispose: nil) }
8
- let(:dsl) { double("dsl", app: shoes_app, gui: gui,
9
- text: text, cursor: nil, style: dsl_style,
10
- element_width: 200, element_height: 180,
11
- element_left: 0, element_top: 10, font: "font",
12
- size: 16, margin_left: 0, margin_top: 0,
13
- text_styles: text_styles, :hidden? => false).as_null_object
14
- }
15
-
16
- let(:segment) do
17
- allow(::Swt::Font).to receive(:new) { font }
18
- allow(::Swt::TextLayout).to receive(:new) { text_layout }
19
- allow(::Swt::TextStyle).to receive(:new) { style }
20
-
21
- Shoes::Swt::TextBlock::TextSegment.new(dsl, text, 200).position_at(0, 10)
22
- end
23
-
24
- let(:text_layout) { double("text layout", text: text).as_null_object }
25
-
6
+ let(:dsl) { double("dsl", app: shoes_app, gui: gui, hidden?: false) }
7
+ let(:gui) { double("gui", dispose: nil, segments: segment_collection) }
26
8
  let(:event) { double("event").as_null_object }
27
- let(:style) { double(:style).as_null_object }
28
- let(:font) { double(:font, font_data: [font_data]).as_null_object }
29
- let(:font_data) { double(name: "font", height: 16.0, style: ::Swt::SWT::NORMAL) }
30
-
31
- let(:blue) { Shoes::Color.new(0, 0, 255) }
32
- let(:swt_blue) { Shoes::Swt::Color.new(blue).real}
33
- let(:text_styles) {{}}
34
- let(:text) {'hello world'}
9
+ let(:segment_collection) { double("segment collection", empty?: false) }
35
10
 
36
11
  subject { Shoes::Swt::TextBlock::Painter.new(dsl) }
37
12
 
38
- before :each do
39
- allow(::Swt::TextStyle).to receive(:new) { style.as_null_object }
13
+ it "doesn't draw if hidden" do
14
+ allow(dsl).to receive(:hidden?) { true }
15
+ expect(segment_collection).to_not receive(:paint_control)
40
16
 
41
- # Can't stub this in during initial let because of circular reference
42
- # segments -> dsl -> gui -> segments...
43
- allow(gui).to receive_messages(segments: [segment])
44
- end
45
-
46
- it "draws" do
47
- expect(segment).to receive(:draw)
48
17
  subject.paintControl(event)
49
18
  end
50
19
 
51
- it "sets justify" do
52
- expect(text_layout).to receive(:justify=).with(dsl_style[:justify])
53
- subject.paintControl(event)
54
- end
20
+ it "doesn't draw no segment collection" do
21
+ allow(gui).to receive(:segments) { nil }
22
+ expect(segment_collection).to_not receive(:paint_control)
55
23
 
56
- it "sets spacing" do
57
- expect(text_layout).to receive(:spacing=).with(dsl_style[:leading])
58
24
  subject.paintControl(event)
59
25
  end
60
26
 
61
- it "sets alignment" do
62
- expect(text_layout).to receive(:alignment=).with(anything)
63
- subject.paintControl(event)
64
- end
27
+ it "doesn't draw segment collection is empty" do
28
+ allow(segment_collection).to receive(:empty?) { true }
29
+ expect(segment_collection).to_not receive(:paint_control)
65
30
 
66
- it "sets text styles" do
67
- expect(text_layout).to receive(:set_style).with(anything, anything, anything).at_least(1).times
68
31
  subject.paintControl(event)
69
32
  end
70
33
 
71
- context "rise option" do
72
- it "sets default rise value to nil" do
73
- expect(style).to receive(:rise=).with(nil)
74
- subject.paintControl(event)
75
- end
76
-
77
- it "sets correct rise value" do
78
- dsl_style[:rise] = 10
79
- expect(style).to receive(:rise=).with(10)
80
-
81
- subject.paintControl(event)
82
- end
83
- end
84
-
85
- context "underline option" do
86
- it "sets default underline style to none" do
87
- dsl_style.delete(:underline)
88
-
89
- expect(style).to receive(:underline=).with(false)
90
- expect(style).to receive(:underlineStyle=).with(nil)
91
-
92
- subject.paintControl(event)
93
- end
94
-
95
- it "sets correct underline style" do
96
-
97
- expect(style).to receive(:underline=).with(true)
98
- expect(style).to receive(:underlineStyle=).with(Shoes::Swt::TextStyleFactory::UNDERLINE_STYLES["single"])
99
-
100
- subject.paintControl(event)
101
- end
102
-
103
- it "sets underline color" do
104
- dsl_style[:undercolor] = blue
105
-
106
- expect(style).to receive(:underlineColor=).with(swt_blue)
107
-
108
- subject.paintControl(event)
109
- end
110
-
111
- it "sets default underline color to nil" do
112
- expect(style).to receive(:underlineColor=).with(nil)
113
-
114
- subject.paintControl(event)
115
- end
116
- end
117
-
118
- context "strikethrough option" do
119
- it "sets default strikethrough to none" do
120
- expect(style).to receive(:strikeout=).with(false)
121
-
122
- subject.paintControl(event)
123
- end
124
-
125
- it "sets strikethrough" do
126
- dsl_style[:strikethrough] = "single"
127
-
128
- expect(style).to receive(:strikeout=).with(true)
129
-
130
- subject.paintControl(event)
131
- end
132
-
133
- it "sets strikethrough color" do
134
- dsl_style[:strikecolor] = blue
135
-
136
- expect(style).to receive(:strikeoutColor=).with(swt_blue)
137
-
138
- subject.paintControl(event)
139
- end
140
-
141
- it "sets default strikethrough color to nil" do
142
- expect(style).to receive(:strikeoutColor=).with(nil)
143
-
144
- subject.paintControl(event)
145
- end
146
- end
147
-
148
- context "font styles" do
149
- it "sets font style to bold" do
150
- dsl_style[:weight] = true
151
- expect(::Swt::Font).to receive(:new).with(anything, anything, anything, ::Swt::SWT::BOLD)
152
- subject.paintControl(event)
153
- end
154
-
155
- it "sets font style to italic" do
156
- dsl_style[:emphasis] = true
157
- expect(::Swt::Font).to receive(:new).with(anything, anything, anything, ::Swt::SWT::ITALIC)
158
- subject.paintControl(event)
159
- end
160
-
161
- it "sets font style to both bold and italic" do
162
- dsl_style[:weight] = true
163
- dsl_style[:emphasis] = true
164
- expect(::Swt::Font).to receive(:new).with(anything, anything, anything, ::Swt::SWT::BOLD | ::Swt::SWT::ITALIC)
165
-
166
- subject.paintControl(event)
167
- end
168
- end
169
-
170
- context "colors" do
171
- let(:black) { Shoes::Swt::Color.new(Shoes::COLORS[:black]).real }
172
- let(:salmon) { Shoes::Swt::Color.new(Shoes::COLORS[:salmon]).real }
173
-
174
- describe "stroke" do
175
- it "is black by default" do
176
- expect(::Swt::TextStyle).to receive(:new).with(anything, black, anything)
177
- subject.paintControl(event)
178
- end
179
-
180
- it "is set with dsl_style[:stroke]" do
181
- dsl_style[:stroke] = Shoes::COLORS[:salmon]
182
- expect(::Swt::TextStyle).to receive(:new).with(anything, salmon, anything)
183
- subject.paintControl(event)
184
- end
185
- end
186
-
187
- describe "fill" do
188
- it "is nil by default" do
189
- expect(::Swt::TextStyle).to receive(:new).with(anything, anything, nil)
190
- subject.paintControl(event)
191
- end
192
-
193
- it "is set with dsl_style[:fill]" do
194
- dsl_style[:fill] = Shoes::COLORS[:salmon]
195
- expect(::Swt::TextStyle).to receive(:new).with(anything, anything, salmon)
196
- subject.paintControl(event)
197
- end
198
- end
199
- end
200
-
201
- describe 'text_styles' do
202
- # this text_styles relies a lot on the internal structure of TextBlock/Painter
203
- # right now, which I'm not too fond of... :)
204
- let(:text_styles) {[[0...text.length, [Shoes::Span.new([text], size: 50)]]]}
205
- it 'sets the font size to 50' do
206
- expect(::Swt::Font).to receive(:new).
207
- with(anything, anything, 50, anything)
208
-
209
- subject.paintControl event
210
- end
34
+ it "paints" do
35
+ expect(segment_collection).to receive(:paint_control)
36
+ subject.paintControl(event)
211
37
  end
212
38
  end
@@ -5,7 +5,8 @@ describe Shoes::Swt::TextBlock::TextSegmentCollection do
5
5
 
6
6
  let(:first_segment) { create_segment("first", "first") }
7
7
  let(:second_segment) { create_segment("second", "rest") }
8
- let(:dsl) { double("dsl", font: "", size: 16, style:{}) }
8
+ let(:dsl) { double("dsl", font: "", size: 16, style:{},
9
+ text_styles: {(0..-1) => ["whatever"]}) }
9
10
 
10
11
  let(:gc) { double("gc") }
11
12
  let(:default_text_styles) {
@@ -62,7 +63,7 @@ describe Shoes::Swt::TextBlock::TextSegmentCollection do
62
63
 
63
64
  dsl_style = dsl_link.style
64
65
  default_style = default_text_styles.merge(dsl_style)
65
- expected_style = default_style.merge({underline: true, stroke: ::Shoes::COLORS[:blue], fill: nil})
66
+ expected_style = default_style.merge(underline: true, stroke: ::Shoes::COLORS[:blue], fill: nil)
66
67
  expect(first_segment).to have_received(:set_style).with(expected_style, 0..1)
67
68
  end
68
69
 
@@ -162,7 +163,7 @@ describe Shoes::Swt::TextBlock::TextSegmentCollection do
162
163
 
163
164
  expected_style = style_with(stroke: :blue, fg: :blue)
164
165
  expect(first_segment).to have_received(:set_style).with(expected_style, 0..2)
165
- expect(second_segment).to_not have_received(:set_style)
166
+ expect(second_segment).to_not have_received(:set_style).with(stroke: :blue)
166
167
  end
167
168
 
168
169
  it "applies segment styling in second segment" do
@@ -170,7 +171,7 @@ describe Shoes::Swt::TextBlock::TextSegmentCollection do
170
171
  subject.style_segment_ranges(styles)
171
172
 
172
173
  expected_style = style_with(stroke: :blue, fg: :blue)
173
- expect(first_segment).to_not have_received(:set_style)
174
+ expect(first_segment).to_not have_received(:set_style).with(stroke: :blue)
174
175
  expect(second_segment).to have_received(:set_style).with(expected_style, 0..2)
175
176
  end
176
177
 
@@ -236,7 +237,11 @@ describe Shoes::Swt::TextBlock::TextSegmentCollection do
236
237
  def create_segment(name, text)
237
238
  bounds = double("bounds", x: 0, y: 0, height: 0)
238
239
  layout = double(name, text: text,
239
- line_bounds: bounds, line_count: 1)
240
+ :justify= => nil, :spacing= => nil, :alignment= => nil,
241
+ line_bounds: bounds, line_count: 1)
242
+
243
+
244
+ allow_any_instance_of(Shoes::Swt::TextFontFactory).to receive(:create_font)
240
245
 
241
246
  segment = Shoes::Swt::TextBlock::TextSegment.new(dsl, text, 1)
242
247
  segment.position_at(0, 0)