shoes-swt 4.0.0.pre2

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 (238) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +84 -0
  3. data/Gemfile +24 -0
  4. data/Guardfile +11 -0
  5. data/LICENSE +31 -0
  6. data/README.md +201 -0
  7. data/lib/shoes/swt.rb +118 -0
  8. data/lib/shoes/swt/animation.rb +46 -0
  9. data/lib/shoes/swt/app.rb +314 -0
  10. data/lib/shoes/swt/arc.rb +71 -0
  11. data/lib/shoes/swt/background.rb +41 -0
  12. data/lib/shoes/swt/border.rb +41 -0
  13. data/lib/shoes/swt/button.rb +18 -0
  14. data/lib/shoes/swt/check.rb +14 -0
  15. data/lib/shoes/swt/check_button.rb +19 -0
  16. data/lib/shoes/swt/color.rb +49 -0
  17. data/lib/shoes/swt/color_factory.rb +32 -0
  18. data/lib/shoes/swt/common/child.rb +16 -0
  19. data/lib/shoes/swt/common/clickable.rb +68 -0
  20. data/lib/shoes/swt/common/container.rb +28 -0
  21. data/lib/shoes/swt/common/fill.rb +38 -0
  22. data/lib/shoes/swt/common/painter.rb +92 -0
  23. data/lib/shoes/swt/common/painter_updates_position.rb +12 -0
  24. data/lib/shoes/swt/common/remove.rb +30 -0
  25. data/lib/shoes/swt/common/resource.rb +29 -0
  26. data/lib/shoes/swt/common/selection_listener.rb +14 -0
  27. data/lib/shoes/swt/common/stroke.rb +42 -0
  28. data/lib/shoes/swt/common/update_position.rb +15 -0
  29. data/lib/shoes/swt/common/visibility.rb +13 -0
  30. data/lib/shoes/swt/dialog.rb +90 -0
  31. data/lib/shoes/swt/disposed_protection.rb +23 -0
  32. data/lib/shoes/swt/download.rb +24 -0
  33. data/lib/shoes/swt/font.rb +32 -0
  34. data/lib/shoes/swt/gradient.rb +92 -0
  35. data/lib/shoes/swt/image.rb +128 -0
  36. data/lib/shoes/swt/image_pattern.rb +31 -0
  37. data/lib/shoes/swt/input_box.rb +73 -0
  38. data/lib/shoes/swt/key_listener.rb +145 -0
  39. data/lib/shoes/swt/line.rb +60 -0
  40. data/lib/shoes/swt/link.rb +31 -0
  41. data/lib/shoes/swt/link_segment.rb +111 -0
  42. data/lib/shoes/swt/list_box.rb +48 -0
  43. data/lib/shoes/swt/mouse_move_listener.rb +67 -0
  44. data/lib/shoes/swt/oval.rb +52 -0
  45. data/lib/shoes/swt/progress.rb +35 -0
  46. data/lib/shoes/swt/radio.rb +29 -0
  47. data/lib/shoes/swt/radio_group.rb +54 -0
  48. data/lib/shoes/swt/rect.rb +30 -0
  49. data/lib/shoes/swt/rect_painter.rb +23 -0
  50. data/lib/shoes/swt/redrawing_aspect.rb +123 -0
  51. data/lib/shoes/swt/shape.rb +133 -0
  52. data/lib/shoes/swt/shoes_layout.rb +43 -0
  53. data/lib/shoes/swt/slot.rb +39 -0
  54. data/lib/shoes/swt/sound.rb +119 -0
  55. data/lib/shoes/swt/star.rb +50 -0
  56. data/lib/shoes/swt/support/jl1.0.1.jar +0 -0
  57. data/lib/shoes/swt/support/jogg-0.0.7.jar +0 -0
  58. data/lib/shoes/swt/support/jorbis-0.0.15.jar +0 -0
  59. data/lib/shoes/swt/support/log4j-1.2.16.jar +0 -0
  60. data/lib/shoes/swt/support/mp3spi1.9.5.jar +0 -0
  61. data/lib/shoes/swt/support/tritonus_share.jar +0 -0
  62. data/lib/shoes/swt/support/vorbisspi1.0.3.jar +0 -0
  63. data/lib/shoes/swt/swt_button.rb +56 -0
  64. data/lib/shoes/swt/text_block.rb +124 -0
  65. data/lib/shoes/swt/text_block/centered_text_segment.rb +22 -0
  66. data/lib/shoes/swt/text_block/cursor_painter.rb +53 -0
  67. data/lib/shoes/swt/text_block/fitter.rb +212 -0
  68. data/lib/shoes/swt/text_block/painter.rb +47 -0
  69. data/lib/shoes/swt/text_block/text_font_factory.rb +50 -0
  70. data/lib/shoes/swt/text_block/text_segment.rb +108 -0
  71. data/lib/shoes/swt/text_block/text_segment_collection.rb +160 -0
  72. data/lib/shoes/swt/text_block/text_style_factory.rb +88 -0
  73. data/lib/shoes/swt/timer.rb +19 -0
  74. data/lib/shoes/swt/tooling/leak_hunter.rb +35 -0
  75. data/lib/shoes/swt/version.rb +5 -0
  76. data/manifests/common.rb +34 -0
  77. data/manifests/shoes-swt.rb +29 -0
  78. data/shoes-swt.gemspec +24 -0
  79. data/spec/code_coverage.rb +14 -0
  80. data/spec/shoes/animation_spec.rb +65 -0
  81. data/spec/shoes/app_spec.rb +484 -0
  82. data/spec/shoes/arc_spec.rb +51 -0
  83. data/spec/shoes/background_spec.rb +53 -0
  84. data/spec/shoes/border_spec.rb +47 -0
  85. data/spec/shoes/builtin_methods_spec.rb +110 -0
  86. data/spec/shoes/button_spec.rb +44 -0
  87. data/spec/shoes/check_spec.rb +35 -0
  88. data/spec/shoes/cli_spec.rb +15 -0
  89. data/spec/shoes/color_spec.rb +408 -0
  90. data/spec/shoes/common/inspect_spec.rb +26 -0
  91. data/spec/shoes/common/remove_spec.rb +38 -0
  92. data/spec/shoes/common/style_normalizer_spec.rb +28 -0
  93. data/spec/shoes/common/style_spec.rb +147 -0
  94. data/spec/shoes/configuration_spec.rb +36 -0
  95. data/spec/shoes/constants_spec.rb +38 -0
  96. data/spec/shoes/dialog_spec.rb +163 -0
  97. data/spec/shoes/dimension_spec.rb +407 -0
  98. data/spec/shoes/dimensions_spec.rb +837 -0
  99. data/spec/shoes/download_spec.rb +142 -0
  100. data/spec/shoes/flow_spec.rb +133 -0
  101. data/spec/shoes/font_spec.rb +37 -0
  102. data/spec/shoes/framework_learning_spec.rb +30 -0
  103. data/spec/shoes/gradient_spec.rb +32 -0
  104. data/spec/shoes/helpers/fake_element.rb +17 -0
  105. data/spec/shoes/helpers/inspect_helpers.rb +5 -0
  106. data/spec/shoes/helpers/sample17_helper.rb +66 -0
  107. data/spec/shoes/image_spec.rb +49 -0
  108. data/spec/shoes/images/shoe.jpg +0 -0
  109. data/spec/shoes/input_box_spec.rb +80 -0
  110. data/spec/shoes/integration_spec.rb +20 -0
  111. data/spec/shoes/internal_app_spec.rb +141 -0
  112. data/spec/shoes/keypress_spec.rb +11 -0
  113. data/spec/shoes/keyrelease_spec.rb +12 -0
  114. data/spec/shoes/line_spec.rb +49 -0
  115. data/spec/shoes/link_spec.rb +105 -0
  116. data/spec/shoes/list_box_spec.rb +74 -0
  117. data/spec/shoes/logger/ruby_spec.rb +8 -0
  118. data/spec/shoes/logger_spec.rb +45 -0
  119. data/spec/shoes/oval_spec.rb +24 -0
  120. data/spec/shoes/point_spec.rb +71 -0
  121. data/spec/shoes/progress_spec.rb +54 -0
  122. data/spec/shoes/radio_spec.rb +32 -0
  123. data/spec/shoes/rect_spec.rb +39 -0
  124. data/spec/shoes/renamed_delegate_spec.rb +70 -0
  125. data/spec/shoes/shape_spec.rb +95 -0
  126. data/spec/shoes/shared_examples/button.rb +6 -0
  127. data/spec/shoes/shared_examples/changeable.rb +26 -0
  128. data/spec/shoes/shared_examples/clickable.rb +5 -0
  129. data/spec/shoes/shared_examples/common_methods.rb +35 -0
  130. data/spec/shoes/shared_examples/dimensions.rb +32 -0
  131. data/spec/shoes/shared_examples/dsl.rb +44 -0
  132. data/spec/shoes/shared_examples/dsl/animate.rb +29 -0
  133. data/spec/shoes/shared_examples/dsl/arc.rb +45 -0
  134. data/spec/shoes/shared_examples/dsl/background.rb +26 -0
  135. data/spec/shoes/shared_examples/dsl/border.rb +10 -0
  136. data/spec/shoes/shared_examples/dsl/button.rb +5 -0
  137. data/spec/shoes/shared_examples/dsl/cap.rb +6 -0
  138. data/spec/shoes/shared_examples/dsl/check.rb +11 -0
  139. data/spec/shoes/shared_examples/dsl/edit_box.rb +8 -0
  140. data/spec/shoes/shared_examples/dsl/edit_line.rb +8 -0
  141. data/spec/shoes/shared_examples/dsl/editable_element.rb +29 -0
  142. data/spec/shoes/shared_examples/dsl/fill.rb +27 -0
  143. data/spec/shoes/shared_examples/dsl/flow.rb +15 -0
  144. data/spec/shoes/shared_examples/dsl/gradient.rb +62 -0
  145. data/spec/shoes/shared_examples/dsl/image.rb +21 -0
  146. data/spec/shoes/shared_examples/dsl/line.rb +9 -0
  147. data/spec/shoes/shared_examples/dsl/nofill.rb +6 -0
  148. data/spec/shoes/shared_examples/dsl/nostroke.rb +6 -0
  149. data/spec/shoes/shared_examples/dsl/oval.rb +88 -0
  150. data/spec/shoes/shared_examples/dsl/pattern.rb +34 -0
  151. data/spec/shoes/shared_examples/dsl/progress.rb +7 -0
  152. data/spec/shoes/shared_examples/dsl/rect.rb +92 -0
  153. data/spec/shoes/shared_examples/dsl/rgb.rb +26 -0
  154. data/spec/shoes/shared_examples/dsl/shape.rb +21 -0
  155. data/spec/shoes/shared_examples/dsl/star.rb +48 -0
  156. data/spec/shoes/shared_examples/dsl/stroke.rb +30 -0
  157. data/spec/shoes/shared_examples/dsl/strokewidth.rb +19 -0
  158. data/spec/shoes/shared_examples/dsl/style.rb +32 -0
  159. data/spec/shoes/shared_examples/dsl/text_elements.rb +81 -0
  160. data/spec/shoes/shared_examples/dsl/video.rb +5 -0
  161. data/spec/shoes/shared_examples/dsl_app_context.rb +8 -0
  162. data/spec/shoes/shared_examples/hover_leave.rb +11 -0
  163. data/spec/shoes/shared_examples/parent.rb +6 -0
  164. data/spec/shoes/shared_examples/scroll.rb +41 -0
  165. data/spec/shoes/shared_examples/shared_element_method.rb +60 -0
  166. data/spec/shoes/shared_examples/slot.rb +331 -0
  167. data/spec/shoes/shared_examples/state.rb +19 -0
  168. data/spec/shoes/shared_examples/style.rb +82 -0
  169. data/spec/shoes/slot_spec.rb +130 -0
  170. data/spec/shoes/sound_spec.rb +15 -0
  171. data/spec/shoes/span_spec.rb +112 -0
  172. data/spec/shoes/spec_helper.rb +24 -0
  173. data/spec/shoes/stack_spec.rb +79 -0
  174. data/spec/shoes/star_spec.rb +31 -0
  175. data/spec/shoes/text_block_dimensions_spec.rb +75 -0
  176. data/spec/shoes/text_block_spec.rb +270 -0
  177. data/spec/shoes/url_spec.rb +68 -0
  178. data/spec/shoes/widget_spec.rb +70 -0
  179. data/spec/shoes_spec.rb +44 -0
  180. data/spec/spec_helper.rb +18 -0
  181. data/spec/swt_shoes/animation_spec.rb +86 -0
  182. data/spec/swt_shoes/app_spec.rb +84 -0
  183. data/spec/swt_shoes/arc_spec.rb +103 -0
  184. data/spec/swt_shoes/background_spec.rb +67 -0
  185. data/spec/swt_shoes/border_spec.rb +52 -0
  186. data/spec/swt_shoes/button_spec.rb +101 -0
  187. data/spec/swt_shoes/check_spec.rb +28 -0
  188. data/spec/swt_shoes/color_factory_spec.rb +49 -0
  189. data/spec/swt_shoes/color_spec.rb +67 -0
  190. data/spec/swt_shoes/common/painter_spec.rb +49 -0
  191. data/spec/swt_shoes/common/remove_spec.rb +53 -0
  192. data/spec/swt_shoes/configuration_spec.rb +12 -0
  193. data/spec/swt_shoes/dialog_spec.rb +106 -0
  194. data/spec/swt_shoes/disposed_protection_spec.rb +49 -0
  195. data/spec/swt_shoes/flow_spec.rb +36 -0
  196. data/spec/swt_shoes/font_spec.rb +33 -0
  197. data/spec/swt_shoes/gradient_spec.rb +31 -0
  198. data/spec/swt_shoes/image_pattern_spec.rb +35 -0
  199. data/spec/swt_shoes/image_spec.rb +100 -0
  200. data/spec/swt_shoes/input_box_spec.rb +116 -0
  201. data/spec/swt_shoes/integration_spec.rb +27 -0
  202. data/spec/swt_shoes/key_listener_spec.rb +325 -0
  203. data/spec/swt_shoes/line_spec.rb +49 -0
  204. data/spec/swt_shoes/link_segment_spec.rb +120 -0
  205. data/spec/swt_shoes/link_spec.rb +54 -0
  206. data/spec/swt_shoes/list_box_spec.rb +56 -0
  207. data/spec/swt_shoes/minimal.png +0 -0
  208. data/spec/swt_shoes/mouse_move_listener_spec.rb +123 -0
  209. data/spec/swt_shoes/oval_spec.rb +51 -0
  210. data/spec/swt_shoes/progress_spec.rb +44 -0
  211. data/spec/swt_shoes/radio_group_spec.rb +73 -0
  212. data/spec/swt_shoes/radio_spec.rb +56 -0
  213. data/spec/swt_shoes/rect_painter_spec.rb +45 -0
  214. data/spec/swt_shoes/rect_spec.rb +19 -0
  215. data/spec/swt_shoes/shape_spec.rb +84 -0
  216. data/spec/swt_shoes/shared_examples/button.rb +21 -0
  217. data/spec/swt_shoes/shared_examples/clickable.rb +85 -0
  218. data/spec/swt_shoes/shared_examples/movable.rb +36 -0
  219. data/spec/swt_shoes/shared_examples/paintable.rb +7 -0
  220. data/spec/swt_shoes/shared_examples/painter.rb +83 -0
  221. data/spec/swt_shoes/shared_examples/pattern.rb +32 -0
  222. data/spec/swt_shoes/shared_examples/removable.rb +41 -0
  223. data/spec/swt_shoes/shared_examples/swt_app_context.rb +23 -0
  224. data/spec/swt_shoes/shared_examples/visibility.rb +15 -0
  225. data/spec/swt_shoes/shell_control_listener_spec.rb +23 -0
  226. data/spec/swt_shoes/slot_spec.rb +24 -0
  227. data/spec/swt_shoes/sound.rb +10 -0
  228. data/spec/swt_shoes/spec_helper.rb +31 -0
  229. data/spec/swt_shoes/star_spec.rb +47 -0
  230. data/spec/swt_shoes/text_block/centered_text_segment_spec.rb +16 -0
  231. data/spec/swt_shoes/text_block/cursor_painter_spec.rb +120 -0
  232. data/spec/swt_shoes/text_block/fitter_spec.rb +213 -0
  233. data/spec/swt_shoes/text_block/painter_spec.rb +212 -0
  234. data/spec/swt_shoes/text_block/text_font_factory_spec.rb +40 -0
  235. data/spec/swt_shoes/text_block/text_segment_collection_spec.rb +256 -0
  236. data/spec/swt_shoes/text_block/text_segment_spec.rb +135 -0
  237. data/spec/swt_shoes/text_block_spec.rb +199 -0
  238. metadata +496 -0
@@ -0,0 +1,256 @@
1
+ require 'swt_shoes/spec_helper'
2
+
3
+ describe Shoes::Swt::TextBlock::TextSegmentCollection do
4
+ include_context "swt app"
5
+
6
+ let(:first_segment) { create_segment("first", "first") }
7
+ let(:second_segment) { create_segment("second", "rest") }
8
+ let(:dsl) { double("dsl", font: "", size: 16, style:{}) }
9
+
10
+ let(:gc) { double("gc") }
11
+ let(:default_text_styles) {
12
+ {
13
+ :fg => :fg,
14
+ :bg => :bg,
15
+ :strikecolor => :strikecolor,
16
+ :undercolor => :undercolor,
17
+ :font_detail => {
18
+ :name => "font name",
19
+ :size => 12,
20
+ :styles => [::Swt::SWT::NORMAL]
21
+ }
22
+ }
23
+ }
24
+
25
+ describe "with one segment" do
26
+ subject { Shoes::Swt::TextBlock::TextSegmentCollection.new(dsl,
27
+ [first_segment],
28
+ default_text_styles) }
29
+
30
+ before do
31
+ allow(dsl).to receive(:text) { first_segment.text }
32
+ end
33
+
34
+ it "should have length" do
35
+ expect(subject.length).to eq(1)
36
+ end
37
+
38
+ it "delegates drawing" do
39
+ subject.draw(gc)
40
+ expect(first_segment).to have_received(:draw)
41
+ end
42
+
43
+ it "applies segment styling" do
44
+ styles = [[0..1, [double("segment", style:{stroke: :blue})]]]
45
+ subject.style_segment_ranges(styles)
46
+
47
+ expected_style = style_with(stroke: :blue, fg: :blue)
48
+ expect(first_segment).to have_received(:set_style).with(expected_style, 0..1)
49
+ end
50
+
51
+ it "only gets default styling if segment is missing opts" do
52
+ styles = [[0..1, [double("segment")]]]
53
+ subject.style_segment_ranges(styles)
54
+ expect(first_segment).to have_received(:set_style).with(default_text_styles, 0..1)
55
+ end
56
+
57
+ describe "links" do
58
+ it "styles links" do
59
+ dsl_link = create_link("linky")
60
+ styles = [[0..1, [dsl_link]]]
61
+ subject.style_segment_ranges(styles)
62
+
63
+ dsl_style = dsl_link.style
64
+ default_style = default_text_styles.merge(dsl_style)
65
+ expected_style = default_style.merge({underline: true, stroke: ::Shoes::COLORS[:blue], fill: nil})
66
+ expect(first_segment).to have_received(:set_style).with(expected_style, 0..1)
67
+ end
68
+
69
+ it "creates a link segment" do
70
+ link = create_link("f")
71
+ styles = [[0..1, [link]]]
72
+ subject.create_links(styles)
73
+
74
+ expect(link.gui.link_segments.size).to eq(1)
75
+ end
76
+ end
77
+
78
+ describe "segment ranges" do
79
+ it "picks within the first range" do
80
+ result = subject.segment_ranges(0..2)
81
+ expect(result).to eql([[first_segment, 0..2]])
82
+ end
83
+
84
+ it "picks the full first range if too large value requested" do
85
+ result = subject.segment_ranges(0..first_segment.text.length + 10)
86
+ expect(result).to eql([[first_segment, 0..first_segment.text.length]])
87
+ end
88
+ end
89
+
90
+ describe "relative text positions" do
91
+ it "should choose the segment" do
92
+ expect(subject.relative_text_position(0)).to eq(0)
93
+ end
94
+
95
+ it "should choose segment nearing end" do
96
+ cursor = first_segment.text.length - 1
97
+ expect(subject.relative_text_position(cursor)).to eq(cursor)
98
+ end
99
+
100
+ it "should choose segment at end" do
101
+ cursor = first_segment.text.length
102
+ expect_relative_position_at_end_of(cursor, first_segment)
103
+ end
104
+
105
+ it "should choose the segment when just past end" do
106
+ cursor = first_segment.text.length + 1
107
+ expect_relative_position_at_end_of(cursor, first_segment)
108
+ end
109
+
110
+ it "should choose right past end" do
111
+ cursor = first_segment.text.length + 3
112
+ expect_relative_position_at_end_of(cursor, first_segment)
113
+ end
114
+
115
+ it "should chooose the segment for -1" do
116
+ expect_relative_position_at_end_of(-1, first_segment)
117
+ end
118
+
119
+ it "should allow crazy positions past the end" do
120
+ expect_relative_position_at_end_of(1000, first_segment)
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "with two segments" do
126
+ subject { Shoes::Swt::TextBlock::TextSegmentCollection.new(dsl,
127
+ [first_segment, second_segment],
128
+ default_text_styles) }
129
+
130
+ before do
131
+ allow(dsl).to receive(:text) { first_segment.text + second_segment.text }
132
+ end
133
+
134
+ it "should have length" do
135
+ expect(subject.length).to eq(2)
136
+ end
137
+
138
+ it "picks range in first segment" do
139
+ result = subject.segment_ranges(0..2)
140
+ expect(result).to eql([[first_segment, 0..2]])
141
+ end
142
+
143
+ it "picks range in second segment" do
144
+ result = subject.segment_ranges(5..7)
145
+ expect(result).to eql([[second_segment, 0..2]])
146
+ end
147
+
148
+ it "spans both segments" do
149
+ result = subject.segment_ranges(2..7)
150
+ expect(result).to eql([[first_segment, 2..5],
151
+ [second_segment, 0..2]])
152
+ end
153
+
154
+ it "applies segment styling in first segment" do
155
+ styles = [[0..2, [double("segment", style:{stroke: :blue})]]]
156
+ subject.style_segment_ranges(styles)
157
+
158
+ expected_style = style_with(stroke: :blue, fg: :blue)
159
+ expect(first_segment).to have_received(:set_style).with(expected_style, 0..2)
160
+ expect(second_segment).to_not have_received(:set_style)
161
+ end
162
+
163
+ it "applies segment styling in second segment" do
164
+ styles = [[5..7, [double("segment", style:{stroke: :blue})]]]
165
+ subject.style_segment_ranges(styles)
166
+
167
+ expected_style = style_with(stroke: :blue, fg: :blue)
168
+ expect(first_segment).to_not have_received(:set_style)
169
+ expect(second_segment).to have_received(:set_style).with(expected_style, 0..2)
170
+ end
171
+
172
+ it "applies segment styling in both segments" do
173
+ styles = [[2..7, [double("segment", style:{stroke: :blue})]]]
174
+ subject.style_segment_ranges(styles)
175
+
176
+ expected_style = style_with(stroke: :blue, fg: :blue)
177
+ expect(first_segment).to have_received(:set_style).with(expected_style, 2..5)
178
+ expect(second_segment).to have_received(:set_style).with(expected_style, 0..2)
179
+ end
180
+
181
+ describe "links" do
182
+ let(:link) { create_link("rstres") }
183
+
184
+ it "creates link segments in both segments" do
185
+ styles = [[2..7, [link]]]
186
+ subject.create_links(styles)
187
+
188
+ expect(link.gui.link_segments.size).to eq(2)
189
+ end
190
+
191
+ it "clears links before re-creating them" do
192
+ styles = [[2..7, [link]]]
193
+
194
+ subject.create_links(styles)
195
+ subject.create_links(styles)
196
+
197
+ expect(link.gui.link_segments.size).to eq(2)
198
+ end
199
+ end
200
+
201
+ describe "relative text positions" do
202
+ it "should choose the first segment" do
203
+ expect(subject.relative_text_position(0)).to eq(0)
204
+ end
205
+
206
+ it "should choose first segment nearing end" do
207
+ cursor = first_segment.text.length - 1
208
+ expect(subject.relative_text_position(cursor)).to eq(cursor)
209
+ end
210
+
211
+ it "should choose second segment at end" do
212
+ cursor = first_segment.text.length
213
+ expect(subject.relative_text_position(cursor)).to eq(0)
214
+ end
215
+
216
+ it "should choose the second segment" do
217
+ cursor = first_segment.text.length + 1
218
+ expect(subject.relative_text_position(cursor)).to eq(1)
219
+ end
220
+
221
+ it "should chooose the second segment for -1" do
222
+ expect_relative_position_at_end_of(-1, second_segment)
223
+ end
224
+
225
+ it "should allow crazy positions past the end" do
226
+ expect_relative_position_at_end_of(1000, second_segment)
227
+ end
228
+ end
229
+ end
230
+
231
+ def create_segment(name, text)
232
+ bounds = double("bounds", x: 0, y: 0, height: 0)
233
+ layout = double(name, text: text,
234
+ line_bounds: bounds, line_count: 1)
235
+
236
+ segment = Shoes::Swt::TextBlock::TextSegment.new(dsl, text, 1)
237
+ segment.position_at(0, 0)
238
+ allow(segment).to receive(:draw)
239
+ allow(segment).to receive(:set_style)
240
+ allow(segment).to receive(:get_location).and_return(double("position", x: 0, y: 0))
241
+ allow(segment).to receive(:layout).and_return(layout)
242
+ segment
243
+ end
244
+
245
+ def create_link(text)
246
+ Shoes::Link.new(shoes_app, parent, [text])
247
+ end
248
+
249
+ def style_with(style={})
250
+ default_text_styles.merge(style)
251
+ end
252
+
253
+ def expect_relative_position_at_end_of(cursor, segment)
254
+ expect(subject.relative_text_position(cursor)).to eq(segment.text.length)
255
+ end
256
+ end
@@ -0,0 +1,135 @@
1
+ require 'swt_shoes/spec_helper'
2
+
3
+ describe Shoes::Swt::TextBlock::TextSegment do
4
+ let(:layout) { double("layout", text: "the text",
5
+ :alignment= => nil, :justify= => nil, :spacing= => nil,
6
+ :text= => nil, :width= => nil,
7
+ disposed?: false, dispose: nil,
8
+ set_style: nil, bounds: bounds) }
9
+ let(:bounds) { Java::OrgEclipseSwtGraphics::Rectangle.new(0, 0, 0, 0) }
10
+ let(:element_left) { 0 }
11
+ let(:element_top) { 0 }
12
+ let(:segment_width) { 10 }
13
+ let(:segment_height) { 10 }
14
+ let(:left_offset) { 5 }
15
+ let(:top_offset) { 5 }
16
+
17
+ let(:font_factory) { double("font factory", create_font: font, dispose: nil) }
18
+ let(:style_factory) { double("style factory", create_style: style, dispose: nil) }
19
+ let(:font) { double("font") }
20
+ let(:style) { double("style") }
21
+
22
+ let(:style_hash) {
23
+ {
24
+ bg: double("bg"),
25
+ fg: double("fg"),
26
+ font_detail: {
27
+ name: "Comic Sans",
28
+ size: 18,
29
+ styles: nil
30
+ }
31
+ }
32
+ }
33
+
34
+ let(:dsl) { double("dsl", font: "", size: 16, style:{}) }
35
+
36
+ before(:each) do
37
+ allow(::Swt::TextLayout).to receive(:new) { layout }
38
+ allow(Shoes::Swt::TextFontFactory).to receive(:new) { font_factory }
39
+ allow(Shoes::Swt::TextStyleFactory).to receive(:new) { style_factory }
40
+ end
41
+
42
+ subject do
43
+ segment = Shoes::Swt::TextBlock::TextSegment.new(dsl, "text", segment_width)
44
+ segment.position_at(element_left, element_top)
45
+ end
46
+
47
+ context "disposal" do
48
+ it "disposes of underlying layout" do
49
+ allow(layout).to receive(:disposed?) { false }
50
+ expect(layout).to receive(:dispose)
51
+ subject.dispose
52
+ end
53
+
54
+ it "doesn't overdispose" do
55
+ allow(layout).to receive(:disposed?) { true }
56
+ expect(layout).to_not receive(:dispose)
57
+ subject.dispose
58
+ end
59
+ end
60
+
61
+ context "setting style" do
62
+ it "on full range" do
63
+ subject.set_style(style_hash)
64
+ expect(layout).to have_received(:set_style).
65
+ with(style, 0, layout.text.length - 1).
66
+ at_least(1).times
67
+ end
68
+
69
+ it "with a range" do
70
+ subject.set_style(style_hash, 1..2)
71
+ expect(layout).to have_received(:set_style).with(style, 1, 2)
72
+ end
73
+
74
+ it "ignores empty ranges" do
75
+ subject.set_style(style_hash, 0...0)
76
+ expect(layout).to_not have_received(:set_style).with(style, 0, 0)
77
+ end
78
+ end
79
+
80
+ describe "shrinking on initialization" do
81
+ it "should not shrink when enough containing width" do
82
+ expect(subject.layout).to_not have_received(:width=)
83
+ end
84
+
85
+ it "shrinks when too long for container" do
86
+ bounds.width = segment_width + 10
87
+ expect(subject.layout).to have_received(:width=).with(segment_width)
88
+ end
89
+ end
90
+
91
+ context "bounds checking" do
92
+ before(:each) do
93
+ set_bounds(0, 0, segment_width, segment_height)
94
+ end
95
+
96
+ it "checks boundaries" do
97
+ expect(subject.in_bounds?(1,1)).to be_truthy
98
+ end
99
+
100
+ describe "offsets left" do
101
+ let(:element_left) { left_offset }
102
+
103
+ it "checks boundaries" do
104
+ expect(subject.in_bounds?(segment_width + left_offset - 1, 0)).to be_truthy
105
+ end
106
+ end
107
+
108
+ describe "offsets top" do
109
+ let(:element_top) { top_offset }
110
+
111
+ it "checks boundaries" do
112
+ expect(subject.in_bounds?(0, segment_height + top_offset - 1)).to be_truthy
113
+ end
114
+ end
115
+
116
+ def set_bounds(x, y, width, height)
117
+ bounds.x = x
118
+ bounds.y = y
119
+ bounds.width = width
120
+ bounds.height = height
121
+ end
122
+ end
123
+
124
+ describe "dispose" do
125
+ it "should dispose its Swt fonts" do
126
+ subject.dispose
127
+ expect(font_factory).to have_received(:dispose)
128
+ end
129
+
130
+ it "should dispose its Swt colors" do
131
+ subject.dispose
132
+ expect(style_factory).to have_received(:dispose)
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,199 @@
1
+ require 'swt_shoes/spec_helper'
2
+
3
+ describe Shoes::Swt::TextBlock do
4
+ include_context "swt app"
5
+
6
+ let(:height) { 100 }
7
+ let(:width) { 200 }
8
+ let(:margin) { 10 }
9
+ let(:dsl) { double("dsl", app: shoes_app, text: "text",
10
+ margin_left: 0, margin_right: 0,
11
+ margin_top: 0, margin_bottom: 0,
12
+ pass_coordinates?: nil).as_null_object }
13
+
14
+ subject { Shoes::Swt::TextBlock.new(dsl, swt_app) }
15
+
16
+ it_behaves_like "paintable"
17
+ it_behaves_like "updating visibility"
18
+ it_behaves_like "clickable backend"
19
+
20
+ # reported nil, caused trouble in simple-downloader.rb
21
+ it 'initially responds with empty segments' do
22
+ expect(subject.segments).to be_empty
23
+ end
24
+
25
+ describe "bounds checking" do
26
+ it "delegates to segment" do
27
+ segment = double()
28
+ subject.segments = [segment]
29
+ expect(segment).to receive(:in_bounds?)
30
+
31
+ subject.in_bounds?(1,1)
32
+ end
33
+ end
34
+
35
+ describe "contents alignment" do
36
+ let(:layout_width) { 100 }
37
+ let(:layout_height) { 200 }
38
+ let(:line_height) { 10 }
39
+
40
+ let(:bounds) { double("bounds", height: layout_height, width: layout_width) }
41
+ let(:unused_bounds) { double("unused bounds", height: 0, width: 0) }
42
+
43
+ let(:fitter) { double("fitter") }
44
+ let(:segment) { create_segment }
45
+ let(:second_segment) { create_segment }
46
+
47
+ let(:current_position) { Shoes::Slot::CurrentPosition.new(0, 0) }
48
+
49
+ before(:each) do
50
+ allow(::Shoes::Swt::TextBlock::Fitter).to receive(:new) { fitter }
51
+ allow(fitter).to receive(:fit_it_in).and_return([segment], [second_segment])
52
+ end
53
+
54
+ describe "with single segment" do
55
+ before(:each) do
56
+ allow(dsl).to receive(:absolute_left) { 50 }
57
+ allow(dsl).to receive(:absolute_top) { 0 }
58
+ allow(dsl).to receive(:absolute_bottom) { layout_height }
59
+ end
60
+
61
+ it "positions single line of text" do
62
+ expect(dsl).to receive(:absolute_right=).with(layout_width + 50)
63
+ expect(dsl).to receive(:absolute_bottom=).with(layout_height)
64
+
65
+ when_aligns_and_positions
66
+
67
+ expect(current_position.y).to eq(layout_height - line_height)
68
+ end
69
+
70
+ it "positions single line with margin" do
71
+ allow(dsl).to receive_messages(margin_left: margin, margin_right: margin,
72
+ margin_top: margin, margin_bottom: margin)
73
+
74
+ expect(dsl).to receive(:absolute_right=).with(layout_width + 50 + margin)
75
+ expect(dsl).to receive(:absolute_bottom=).with(layout_height + 2 * margin)
76
+
77
+ when_aligns_and_positions
78
+
79
+ expect(current_position.y).to eq(layout_height - line_height)
80
+ end
81
+
82
+ it "pushes to next line if ends in newline" do
83
+ allow(dsl).to receive(:text) { "text\n" }
84
+
85
+ expect(dsl).to receive(:absolute_right=).with(50)
86
+ expect(dsl).to receive(:absolute_bottom=).with(layout_height)
87
+
88
+ when_aligns_and_positions
89
+
90
+ expect(current_position.y).to eq(layout_height)
91
+ end
92
+
93
+ it "disposes of prior segments" do
94
+ subject.contents_alignment(current_position)
95
+ expect(segment).to receive(:dispose)
96
+
97
+ subject.contents_alignment(current_position)
98
+ end
99
+
100
+ it "should not dispose any segments" do
101
+ expect(segment).not_to receive(:dispose)
102
+ expect(second_segment).not_to receive(:dispose)
103
+
104
+ subject.contents_alignment(current_position)
105
+ end
106
+
107
+ context "on the second call" do
108
+ before(:each) do
109
+ subject.contents_alignment(current_position)
110
+ end
111
+
112
+ it "should only dispose old segment" do
113
+ expect(segment).to receive(:dispose)
114
+ expect(second_segment).not_to receive(:dispose)
115
+
116
+ subject.contents_alignment(current_position)
117
+ end
118
+
119
+ it "should dispose all segments on remove" do
120
+ allow(swt_app).to receive(:remove_listener)
121
+
122
+ expect(segment).to receive(:dispose).at_least(1).times
123
+ expect(second_segment).to receive(:dispose).at_least(1).times
124
+
125
+ subject.contents_alignment(current_position)
126
+ subject.remove
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "with two segments" do
132
+ before(:each) do
133
+ allow(dsl).to receive(:parent) { double("dsl parent", absolute_left: 0) }
134
+ allow(dsl).to receive(:absolute_bottom) { layout_height }
135
+
136
+ current_position.next_line_start = 0
137
+
138
+ allow(fitter).to receive(:fit_it_in) {
139
+ [create_segment("unused segment"),
140
+ create_segment("segment")]
141
+ }
142
+ end
143
+
144
+ it "positions in two segments" do
145
+ expect(dsl).to receive(:absolute_right=).with(layout_width)
146
+ expect(dsl).to receive(:absolute_bottom=).with(layout_height)
147
+
148
+ when_aligns_and_positions
149
+
150
+ expect(current_position.y).to eq(layout_height - line_height)
151
+ end
152
+
153
+ it "positions in two segments with margins" do
154
+ allow(dsl).to receive_messages(margin_left: margin, margin_right: margin,
155
+ margin_top: margin, margin_bottom: margin)
156
+
157
+ expect(dsl).to receive(:absolute_right=).with(layout_width + margin)
158
+ expect(dsl).to receive(:absolute_bottom=).with(layout_height + 2 * margin)
159
+
160
+ when_aligns_and_positions
161
+
162
+ expect(current_position.y).to eq(layout_height - line_height)
163
+ end
164
+ end
165
+ end
166
+
167
+ context "links" do
168
+ let(:link) { Shoes::Link.new(shoes_app, subject, ["link"]) }
169
+
170
+ before(:each) do
171
+ allow(dsl).to receive(:links) { [link] }
172
+ allow(swt_app).to receive(:remove_listener)
173
+ end
174
+
175
+ it "clears links" do
176
+ expect(link).to receive(:remove)
177
+ subject.remove
178
+ end
179
+
180
+ it "clears links on replace" do
181
+ expect(link).to receive(:remove)
182
+ subject.replace("text")
183
+ end
184
+ end
185
+
186
+ def create_segment(name="segment", width=layout_width,
187
+ height=layout_height, line_height=line_height)
188
+ bounds = double("bounds", width: width, height: height)
189
+ double(name, disposed?: false,
190
+ width: width, height: height,
191
+ last_line_width: width, last_line_height: line_height,
192
+ bounds: bounds)
193
+ end
194
+
195
+ def when_aligns_and_positions
196
+ subject.contents_alignment(current_position)
197
+ subject.adjust_current_position(current_position)
198
+ end
199
+ end