glimmer-dsl-swt 4.18.4.4 → 4.18.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/LICENSE.txt +20 -20
  4. data/README.md +43 -5058
  5. data/RUBY_VERSION +1 -1
  6. data/VERSION +1 -1
  7. data/bin/girb +31 -31
  8. data/bin/girb_runner.rb +34 -34
  9. data/bin/glimmer +26 -26
  10. data/docs/reference/GLIMMER_COMMAND.md +591 -0
  11. data/docs/reference/GLIMMER_CONFIGURATION.md +183 -0
  12. data/docs/reference/GLIMMER_GIRB.md +30 -0
  13. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +3367 -0
  14. data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +202 -0
  15. data/docs/reference/GLIMMER_SAMPLES.md +755 -0
  16. data/docs/reference/GLIMMER_STYLE_GUIDE.md +14 -0
  17. data/glimmer-dsl-swt.gemspec +22 -7
  18. data/lib/ext/glimmer.rb +41 -41
  19. data/lib/ext/glimmer/config.rb +167 -167
  20. data/lib/ext/rouge/themes/glimmer.rb +29 -29
  21. data/lib/glimmer-dsl-swt.rb +44 -44
  22. data/lib/glimmer/Rakefile +26 -26
  23. data/lib/glimmer/data_binding/list_selection_binding.rb +72 -72
  24. data/lib/glimmer/data_binding/observable_widget.rb +38 -38
  25. data/lib/glimmer/data_binding/shine.rb +44 -44
  26. data/lib/glimmer/data_binding/table_items_binding.rb +89 -89
  27. data/lib/glimmer/data_binding/tree_items_binding.rb +108 -108
  28. data/lib/glimmer/data_binding/widget_binding.rb +73 -73
  29. data/lib/glimmer/dsl/swt/animation_expression.rb +43 -43
  30. data/lib/glimmer/dsl/swt/async_exec_expression.rb +35 -35
  31. data/lib/glimmer/dsl/swt/bind_expression.rb +58 -58
  32. data/lib/glimmer/dsl/swt/block_property_expression.rb +41 -41
  33. data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +61 -61
  34. data/lib/glimmer/dsl/swt/color_expression.rb +40 -40
  35. data/lib/glimmer/dsl/swt/column_properties_expression.rb +45 -45
  36. data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +67 -67
  37. data/lib/glimmer/dsl/swt/cursor_expression.rb +44 -44
  38. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +63 -63
  39. data/lib/glimmer/dsl/swt/data_binding_expression.rb +55 -55
  40. data/lib/glimmer/dsl/swt/dialog_expression.rb +48 -48
  41. data/lib/glimmer/dsl/swt/directory_dialog_expression.rb +48 -48
  42. data/lib/glimmer/dsl/swt/display_expression.rb +40 -40
  43. data/lib/glimmer/dsl/swt/dnd_expression.rb +46 -46
  44. data/lib/glimmer/dsl/swt/dsl.rb +63 -63
  45. data/lib/glimmer/dsl/swt/exec_expression.rb +55 -55
  46. data/lib/glimmer/dsl/swt/expand_item_expression.rb +60 -60
  47. data/lib/glimmer/dsl/swt/file_dialog_expression.rb +48 -48
  48. data/lib/glimmer/dsl/swt/font_expression.rb +49 -49
  49. data/lib/glimmer/dsl/swt/image_expression.rb +54 -50
  50. data/lib/glimmer/dsl/swt/layout_data_expression.rb +46 -46
  51. data/lib/glimmer/dsl/swt/layout_expression.rb +50 -50
  52. data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +65 -65
  53. data/lib/glimmer/dsl/swt/menu_bar_expression.rb +54 -54
  54. data/lib/glimmer/dsl/swt/menu_expression.rb +53 -53
  55. data/lib/glimmer/dsl/swt/message_box_expression.rb +54 -54
  56. data/lib/glimmer/dsl/swt/multiply_expression.rb +53 -53
  57. data/lib/glimmer/dsl/swt/observe_expression.rb +56 -53
  58. data/lib/glimmer/dsl/swt/pixel_expression.rb +38 -0
  59. data/lib/glimmer/dsl/swt/property_expression.rb +46 -46
  60. data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +62 -61
  61. data/lib/glimmer/dsl/swt/rgb_expression.rb +33 -33
  62. data/lib/glimmer/dsl/swt/rgba_expression.rb +33 -33
  63. data/lib/glimmer/dsl/swt/shape_expression.rb +54 -54
  64. data/lib/glimmer/dsl/swt/shell_expression.rb +46 -46
  65. data/lib/glimmer/dsl/swt/swt_expression.rb +46 -46
  66. data/lib/glimmer/dsl/swt/sync_exec_expression.rb +36 -36
  67. data/lib/glimmer/dsl/swt/tab_item_expression.rb +54 -54
  68. data/lib/glimmer/dsl/swt/table_items_data_binding_expression.rb +52 -52
  69. data/lib/glimmer/dsl/swt/transform_expression.rb +55 -55
  70. data/lib/glimmer/dsl/swt/tree_items_data_binding_expression.rb +52 -52
  71. data/lib/glimmer/dsl/swt/tree_properties_expression.rb +47 -47
  72. data/lib/glimmer/dsl/swt/widget_expression.rb +67 -66
  73. data/lib/glimmer/dsl/swt/widget_listener_expression.rb +53 -53
  74. data/lib/glimmer/rake_task.rb +220 -220
  75. data/lib/glimmer/rake_task/list.rb +97 -97
  76. data/lib/glimmer/rake_task/package.rb +139 -139
  77. data/lib/glimmer/rake_task/scaffold.rb +765 -765
  78. data/lib/glimmer/swt/color_proxy.rb +108 -107
  79. data/lib/glimmer/swt/cursor_proxy.rb +66 -66
  80. data/lib/glimmer/swt/custom/animation.rb +245 -243
  81. data/lib/glimmer/swt/custom/checkbox_group.rb +181 -181
  82. data/lib/glimmer/swt/custom/code_text.rb +1 -0
  83. data/lib/glimmer/swt/custom/drawable.rb +97 -49
  84. data/lib/glimmer/swt/custom/radio_group.rb +177 -176
  85. data/lib/glimmer/swt/custom/shape.rb +332 -297
  86. data/lib/glimmer/swt/date_time_proxy.rb +85 -85
  87. data/lib/glimmer/swt/directory_dialog_proxy.rb +65 -65
  88. data/lib/glimmer/swt/display_proxy.rb +167 -166
  89. data/lib/glimmer/swt/dnd_proxy.rb +51 -51
  90. data/lib/glimmer/swt/expand_item_proxy.rb +97 -97
  91. data/lib/glimmer/swt/file_dialog_proxy.rb +66 -66
  92. data/lib/glimmer/swt/font_proxy.rb +94 -94
  93. data/lib/glimmer/swt/image_proxy.rb +195 -184
  94. data/lib/glimmer/swt/layout_data_proxy.rb +105 -105
  95. data/lib/glimmer/swt/layout_proxy.rb +112 -112
  96. data/lib/glimmer/swt/menu_proxy.rb +126 -126
  97. data/lib/glimmer/swt/message_box_proxy.rb +89 -89
  98. data/lib/glimmer/swt/packages.rb +37 -37
  99. data/lib/glimmer/swt/properties.rb +74 -49
  100. data/lib/glimmer/swt/sash_form_proxy.rb +53 -53
  101. data/lib/glimmer/swt/scrolled_composite_proxy.rb +46 -37
  102. data/lib/glimmer/swt/style_constantizable.rb +157 -157
  103. data/lib/glimmer/swt/styled_text_proxy.rb +38 -38
  104. data/lib/glimmer/swt/swt_proxy.rb +59 -59
  105. data/lib/glimmer/swt/tab_item_proxy.rb +92 -91
  106. data/lib/glimmer/swt/table_column_proxy.rb +57 -57
  107. data/lib/glimmer/swt/transform_proxy.rb +109 -109
  108. data/lib/glimmer/swt/tree_proxy.rb +145 -145
  109. data/lib/glimmer/swt/widget_listener_proxy.rb +64 -64
  110. data/lib/glimmer/swt/widget_proxy.rb +977 -957
  111. data/lib/glimmer/ui/custom_shell.rb +82 -82
  112. data/lib/glimmer/ui/custom_widget.rb +332 -315
  113. data/lib/glimmer/util/proc_tracker.rb +39 -39
  114. data/samples/elaborate/contact_manager.rb +142 -142
  115. data/samples/elaborate/contact_manager/contact.rb +32 -32
  116. data/samples/elaborate/contact_manager/contact_manager_presenter.rb +47 -47
  117. data/samples/elaborate/contact_manager/contact_repository.rb +169 -169
  118. data/samples/elaborate/login.rb +123 -123
  119. data/samples/elaborate/mandelbrot_fractal.rb +354 -0
  120. data/samples/elaborate/tetris.rb +5 -18
  121. data/samples/elaborate/tetris/model/block.rb +48 -48
  122. data/samples/elaborate/tetris/model/past_game.rb +39 -39
  123. data/samples/elaborate/tetris/view/block.rb +1 -1
  124. data/samples/elaborate/tetris/view/playfield.rb +1 -1
  125. data/samples/elaborate/tic_tac_toe.rb +76 -76
  126. data/samples/elaborate/tic_tac_toe/board.rb +145 -145
  127. data/samples/elaborate/tic_tac_toe/cell.rb +48 -48
  128. data/samples/elaborate/user_profile.rb +76 -76
  129. data/samples/hello/hello_browser.rb +31 -31
  130. data/samples/hello/hello_button.rb +46 -46
  131. data/samples/hello/hello_canvas.rb +64 -64
  132. data/samples/hello/hello_canvas_animation.rb +1 -1
  133. data/samples/hello/hello_checkbox.rb +85 -85
  134. data/samples/hello/hello_checkbox_group.rb +71 -71
  135. data/samples/hello/hello_code_text.rb +104 -104
  136. data/samples/hello/hello_combo.rb +63 -63
  137. data/samples/hello/hello_computed.rb +96 -96
  138. data/samples/hello/hello_computed/contact.rb +42 -42
  139. data/samples/hello/hello_cursor.rb +57 -0
  140. data/samples/hello/hello_custom_shell.rb +155 -155
  141. data/samples/hello/hello_custom_widget.rb +86 -86
  142. data/samples/hello/hello_date_time.rb +63 -63
  143. data/samples/hello/hello_dialog.rb +78 -78
  144. data/samples/hello/hello_directory_dialog.rb +60 -60
  145. data/samples/hello/hello_drag_and_drop.rb +50 -50
  146. data/samples/hello/hello_expand_bar.rb +110 -110
  147. data/samples/hello/hello_file_dialog.rb +60 -60
  148. data/samples/hello/hello_group.rb +104 -104
  149. data/samples/hello/hello_link.rb +80 -80
  150. data/samples/hello/hello_list_multi_selection.rb +74 -74
  151. data/samples/hello/hello_list_single_selection.rb +59 -59
  152. data/samples/hello/hello_menu_bar.rb +241 -241
  153. data/samples/hello/hello_message_box.rb +37 -37
  154. data/samples/hello/hello_pop_up_context_menu.rb +84 -84
  155. data/samples/hello/hello_radio.rb +108 -108
  156. data/samples/hello/hello_radio_group.rb +87 -87
  157. data/samples/hello/hello_sash_form.rb +137 -137
  158. data/samples/hello/hello_spinner.rb +69 -69
  159. data/samples/hello/hello_styled_text.rb +138 -138
  160. data/samples/hello/hello_tab.rb +50 -50
  161. data/samples/hello/hello_table.rb +1 -1
  162. data/samples/hello/hello_table/baseball_park.png +0 -0
  163. data/samples/hello/hello_world.rb +29 -29
  164. metadata +19 -4
@@ -0,0 +1,354 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'complex'
23
+ require 'bigdecimal'
24
+ require 'concurrent-ruby'
25
+
26
+ # Mandelbrot multi-threaded implementation leveraging all processor cores.
27
+ class Mandelbrot
28
+ DEFAULT_STEP = 0.0030
29
+ Y_START = -1.0
30
+ Y_END = 1.0
31
+ X_START = -2.0
32
+ X_END = 0.5
33
+
34
+ class << self
35
+ def for(max_iterations:, zoom:, background: false)
36
+ key = [max_iterations, zoom]
37
+ creation_mutex.synchronize do
38
+ unless flyweight_mandelbrots.keys.include?(key)
39
+ flyweight_mandelbrots[key] = new(max_iterations: max_iterations, zoom: zoom, background: background)
40
+ end
41
+ end
42
+ flyweight_mandelbrots[key].background = background
43
+ flyweight_mandelbrots[key]
44
+ end
45
+
46
+ def flyweight_mandelbrots
47
+ @flyweight_mandelbrots ||= {}
48
+ end
49
+
50
+ def creation_mutex
51
+ @creation_mutex ||= Mutex.new
52
+ end
53
+ end
54
+
55
+ attr_accessor :max_iterations, :background
56
+ attr_reader :zoom, :points_calculated
57
+ alias points_calculated? points_calculated
58
+
59
+ # max_iterations is the maximum number of Mandelbrot calculation iterations
60
+ # zoom is how much zoom there is on the Mandelbrot points from the default view of zoom 1
61
+ # background indicates whether to do calculation in the background for caching purposes,
62
+ # thus utilizing less CPU cores to avoid disrupting user experience
63
+ def initialize(max_iterations:, zoom: 1.0, background: false)
64
+ @max_iterations = max_iterations
65
+ @zoom = zoom
66
+ @background = background
67
+ end
68
+
69
+ def step
70
+ DEFAULT_STEP / zoom
71
+ end
72
+
73
+ def y_array
74
+ @y_array ||= Y_START.step(Y_END, step).to_a
75
+ end
76
+
77
+ def x_array
78
+ @x_array ||= X_START.step(X_END, step).to_a
79
+ end
80
+
81
+ def height
82
+ y_array.size
83
+ end
84
+
85
+ def width
86
+ x_array.size
87
+ end
88
+
89
+ def points
90
+ @points ||= calculate_points
91
+ end
92
+
93
+ def thread_count
94
+ @background ? [Concurrent.processor_count - 1, 1].max : Concurrent.processor_count
95
+ end
96
+
97
+ def calculate_points
98
+ puts "Background calculation activated at zoom #{zoom}" if @background
99
+ if @points_calculated
100
+ puts "Points calculated already. Returning previously calculated points..."
101
+ return @points
102
+ end
103
+ thread_pool = Concurrent::FixedThreadPool.new(thread_count, fallback_policy: :discard)
104
+ @points = Concurrent::Array.new(height)
105
+ height.times do |y|
106
+ @points[y] ||= Concurrent::Array.new(width)
107
+ width.times do |x|
108
+ thread_pool.post do
109
+ @points[y][x] = calculate(x_array[x], y_array[y]).last
110
+ end
111
+ end
112
+ end
113
+ thread_pool.shutdown
114
+ thread_pool.wait_for_termination
115
+ @points_calculated = true
116
+ @points
117
+ end
118
+
119
+ # Calculates a Mandelbrot point, borrowing some open-source code from:
120
+ # https://github.com/gotbadger/ruby-mandelbrot
121
+ def calculate(x,y)
122
+ base_case = [Complex(x,y), 0]
123
+ Array.new(max_iterations, base_case).inject(base_case) do |prev ,base|
124
+ z, itr = prev
125
+ c, _ = base
126
+ val = z*z + c
127
+ itr += 1 unless val.abs < 2
128
+ [val, itr]
129
+ end
130
+ end
131
+ end
132
+
133
+ class MandelbrotFractal
134
+ include Glimmer::UI::CustomShell
135
+
136
+ COMMAND = OS.mac? ? :command : :ctrl
137
+
138
+ option :zoom, default: 1.0
139
+
140
+ before_body {
141
+ Display.app_name = 'Mandelbrot Fractal'
142
+ # pre-calculate mandelbrot image
143
+ @mandelbrot_image = build_mandelbrot_image
144
+ }
145
+
146
+ after_body {
147
+ # pre-calculate zoomed mandelbrot images even before the user zooms in
148
+ puts 'Starting background calculation thread...'
149
+ Thread.new {
150
+ future_zoom = 1.5
151
+ loop {
152
+ puts "Creating mandelbrot for background calculation at zoom: #{future_zoom}"
153
+ the_mandelbrot = Mandelbrot.for(max_iterations: color_palette.size - 1, zoom: future_zoom, background: true)
154
+ pixels = the_mandelbrot.calculate_points
155
+ build_mandelbrot_image(mandelbrot_zoom: future_zoom)
156
+ sync_exec {
157
+ swt_widget.text = mandelbrot_shell_title
158
+ @canvas.cursor = :cross
159
+ }
160
+ future_zoom += 0.5
161
+ }
162
+ }
163
+ }
164
+
165
+ body {
166
+ shell(:no_resize) {
167
+ text mandelbrot_shell_title
168
+ minimum_size mandelbrot.width, mandelbrot.height + 30
169
+ image @mandelbrot_image
170
+
171
+ @scrolled_composite = scrolled_composite {
172
+ @canvas = canvas {
173
+ image @mandelbrot_image
174
+ cursor :no
175
+
176
+ on_mouse_down {
177
+ @drag_detected = false
178
+ @canvas.cursor = :hand
179
+ }
180
+
181
+ on_drag_detected { |drag_detect_event|
182
+ @drag_detected = true
183
+ @drag_start_x = drag_detect_event.x
184
+ @drag_start_y = drag_detect_event.y
185
+ }
186
+
187
+ on_mouse_move { |mouse_event|
188
+ if @drag_detected
189
+ origin = @scrolled_composite.origin
190
+ new_x = origin.x - (mouse_event.x - @drag_start_x)
191
+ new_y = origin.y - (mouse_event.y - @drag_start_y)
192
+ @scrolled_composite.set_origin(new_x, new_y)
193
+ end
194
+ }
195
+
196
+ on_mouse_up { |mouse_event|
197
+ if !@drag_detected
198
+ origin = @scrolled_composite.origin
199
+ @location_x = [[origin.x + mouse_event.x - @scrolled_composite.bounds.width / 2.0, 0].max, @scrolled_composite.bounds.width].min
200
+ @location_y = [[origin.y + mouse_event.y - @scrolled_composite.bounds.height / 2.0, 0].max, @scrolled_composite.bounds.height].min
201
+ if mouse_event.button == 1
202
+ zoom_in
203
+ elsif mouse_event.button > 2
204
+ zoom_out
205
+ end
206
+ end
207
+ @canvas.cursor = can_zoom_in? ? :cross : :no
208
+ @drag_detected = false
209
+ }
210
+
211
+ }
212
+ }
213
+
214
+ menu_bar {
215
+ menu {
216
+ text '&View'
217
+
218
+ menu_item {
219
+ text 'Zoom &In'
220
+ accelerator COMMAND, '+'
221
+
222
+ on_widget_selected { zoom_in }
223
+ }
224
+
225
+ menu_item {
226
+ text 'Zoom &Out'
227
+ accelerator COMMAND, '-'
228
+
229
+ on_widget_selected { zoom_out }
230
+ }
231
+
232
+ menu_item {
233
+ text '&Reset Zoom'
234
+ accelerator COMMAND, '0'
235
+
236
+ on_widget_selected { perform_zoom(mandelbrot_zoom: 1.0) }
237
+ }
238
+ }
239
+ menu {
240
+ text '&Help'
241
+
242
+ menu_item {
243
+ text '&Instructions'
244
+ accelerator COMMAND, :shift, :i
245
+
246
+ on_widget_selected {
247
+ display_help_instructions
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+
255
+ def mandelbrot_shell_title
256
+ "Mandelbrot Fractal - Zoom #{zoom}x (Calculated Max: #{flyweight_mandelbrot_images.keys.max}x)"
257
+ end
258
+
259
+ def build_mandelbrot_image(mandelbrot_zoom: nil)
260
+ mandelbrot_zoom ||= zoom
261
+ unless flyweight_mandelbrot_images.keys.include?(mandelbrot_zoom)
262
+ the_mandelbrot = mandelbrot(mandelbrot_zoom: mandelbrot_zoom)
263
+ width = the_mandelbrot.width
264
+ height = the_mandelbrot.height
265
+ pixels = the_mandelbrot.points
266
+ new_mandelbrot_image = image(width, height, top_level: true) # invoke as a top-level parentless keyword to avoid nesting under any widget
267
+ new_mandelbrot_image_gc = new_mandelbrot_image.gc
268
+ current_foreground = nil
269
+ height.times { |y|
270
+ width.times { |x|
271
+ new_foreground = color_palette[pixels[y][x]]
272
+ new_mandelbrot_image_gc.foreground = current_foreground = new_foreground unless new_foreground == current_foreground
273
+ new_mandelbrot_image_gc.draw_point x, y
274
+ }
275
+ }
276
+ flyweight_mandelbrot_images[mandelbrot_zoom] = new_mandelbrot_image
277
+ end
278
+ flyweight_mandelbrot_images[mandelbrot_zoom]
279
+ end
280
+
281
+ def flyweight_mandelbrot_images
282
+ @flyweight_mandelbrot_images ||= {}
283
+ end
284
+
285
+ def mandelbrot(mandelbrot_zoom: nil)
286
+ mandelbrot_zoom ||= zoom
287
+ Mandelbrot.for(max_iterations: color_palette.size - 1, zoom: mandelbrot_zoom)
288
+ end
289
+
290
+ def color_palette
291
+ if @color_palette.nil?
292
+ @color_palette = [[0, 0, 0]] + 40.times.map { |i| [255 - i*5, 255 - i*5, 55 + i*5] }
293
+ @color_palette = @color_palette.map {|color_data| rgb(*color_data).swt_color}
294
+ end
295
+ @color_palette
296
+ end
297
+
298
+ def zoom_in
299
+ if can_zoom_in?
300
+ perform_zoom(zoom_delta: 0.5)
301
+ @canvas.cursor = can_zoom_in? ? :cross : :no
302
+ end
303
+ end
304
+
305
+ def can_zoom_in?
306
+ flyweight_mandelbrot_images.keys.include?(zoom + 0.5)
307
+ end
308
+
309
+ def zoom_out
310
+ perform_zoom(zoom_delta: -0.5)
311
+ end
312
+
313
+ def perform_zoom(zoom_delta: 0, mandelbrot_zoom: nil)
314
+ mandelbrot_zoom ||= self.zoom + zoom_delta
315
+ @canvas.cursor = :wait
316
+ last_zoom = self.zoom
317
+ self.zoom = [mandelbrot_zoom, 1.0].max
318
+ @canvas.clear_shapes(dispose_images: false)
319
+ @mandelbrot_image = build_mandelbrot_image
320
+ body_root.content {
321
+ image @mandelbrot_image
322
+ }
323
+ @canvas.content {
324
+ image @mandelbrot_image
325
+ }
326
+ @canvas.set_size @mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height
327
+ @scrolled_composite.swt_widget.set_min_size(Point.new(@mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height))
328
+ if @location_x && @location_y
329
+ factor = (zoom / last_zoom)
330
+ @scrolled_composite.set_origin(factor*@location_x, factor*@location_y)
331
+ @location_x = @location_y = nil
332
+ end
333
+ @canvas.cursor = :cross
334
+ swt_widget.text = mandelbrot_shell_title
335
+ end
336
+
337
+ def display_help_instructions
338
+ message_box(body_root) {
339
+ text 'Mandelbrot Fractal - Help'
340
+ message <<~MULTI_LINE_STRING
341
+ The Mandelbrot Fractal precalculates zoomed renderings in the background. Wait if you hit a zoom level that is not calculated yet.
342
+
343
+ Left-click to zoom in.
344
+ Right-click to zoom out.
345
+ Scroll or drag to pan.
346
+
347
+ Enjoy!
348
+ MULTI_LINE_STRING
349
+ }.open
350
+ end
351
+
352
+ end
353
+
354
+ MandelbrotFractal.launch
@@ -139,10 +139,6 @@ class Tetris
139
139
  score_lane(game: game, block_size: BLOCK_SIZE) {
140
140
  layout_data(:fill, :fill, true, true)
141
141
  }
142
-
143
- on_widget_disposed {
144
- deregister_observers
145
- }
146
142
  }
147
143
  }
148
144
 
@@ -159,19 +155,19 @@ class Tetris
159
155
  color = colored ? color(([:white] + Model::Tetromino::LETTER_COLORS.values).sample) : color(:white)
160
156
  x = column * icon_block_size
161
157
  y = row * icon_block_size
162
- rectangle(x, y, icon_block_size, icon_block_size, fill: true) {
158
+ rectangle(x, y, icon_block_size, icon_block_size) {
163
159
  background color
164
160
  }
165
- polygon(x, y, x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size, fill: true) {
161
+ polygon(x, y, x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size) {
166
162
  background rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
167
163
  }
168
- polygon(x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size, y + icon_block_size, fill: true) {
164
+ polygon(x + icon_block_size, y, x + icon_block_size - icon_bevel_pixel_size, y + icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size, y + icon_block_size) {
169
165
  background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
170
166
  }
171
- polygon(x + icon_block_size, y + icon_block_size, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, fill: true) {
167
+ polygon(x + icon_block_size, y + icon_block_size, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_block_size - icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size) {
172
168
  background rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
173
169
  }
174
- polygon(x, y, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size, fill: true) {
170
+ polygon(x, y, x, y + icon_block_size, x + icon_bevel_pixel_size, y + icon_block_size - icon_bevel_pixel_size, x + icon_bevel_pixel_size, y + icon_bevel_pixel_size) {
175
171
  background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
176
172
  }
177
173
  }
@@ -206,15 +202,6 @@ class Tetris
206
202
  message "Glimmer Tetris\n\nGlimmer DSL for SWT Sample\n\nCopyright (c) 2007-2021 Andy Maleh"
207
203
  }.open
208
204
  end
209
-
210
- def deregister_observers
211
- @show_high_scores_observer&.deregister
212
- @game_over_observer&.deregister
213
- @keyboard_down_listener&.deregister
214
- @keyboard_up_listener&.deregister
215
- @about_observer&.deregister
216
- @quit_observer&.deregister
217
- end
218
205
  end
219
206
 
220
207
  Tetris.launch
@@ -1,48 +1,48 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining
4
- # a copy of this software and associated documentation files (the
5
- # "Software"), to deal in the Software without restriction, including
6
- # without limitation the rights to use, copy, modify, merge, publish,
7
- # distribute, sublicense, and/or sell copies of the Software, and to
8
- # permit persons to whom the Software is furnished to do so, subject to
9
- # the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be
12
- # included in all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
- class Tetris
23
- module Model
24
- class Block
25
- COLOR_CLEAR = :white
26
-
27
- attr_accessor :color
28
-
29
- # Initializes with color. Default color (gray) signifies an empty block
30
- def initialize(color = COLOR_CLEAR)
31
- @color = color
32
- end
33
-
34
- # Clears block color. `quietly` option indicates if it should not notify observers by setting value quietly via variable not attribute writer.
35
- def clear
36
- self.color = COLOR_CLEAR unless self.color == COLOR_CLEAR
37
- end
38
-
39
- def clear?
40
- self.color == COLOR_CLEAR
41
- end
42
-
43
- def occupied?
44
- !clear?
45
- end
46
- end
47
- end
48
- end
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ class Tetris
23
+ module Model
24
+ class Block
25
+ COLOR_CLEAR = :white
26
+
27
+ attr_accessor :color
28
+
29
+ # Initializes with color. Default color (gray) signifies an empty block
30
+ def initialize(color = COLOR_CLEAR)
31
+ @color = color
32
+ end
33
+
34
+ # Clears block color. `quietly` option indicates if it should not notify observers by setting value quietly via variable not attribute writer.
35
+ def clear
36
+ self.color = COLOR_CLEAR unless self.color == COLOR_CLEAR
37
+ end
38
+
39
+ def clear?
40
+ self.color == COLOR_CLEAR
41
+ end
42
+
43
+ def occupied?
44
+ !clear?
45
+ end
46
+ end
47
+ end
48
+ end