glimmer-dsl-swt 4.18.4.4 → 4.18.4.9

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 (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