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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/LICENSE.txt +20 -20
- data/README.md +43 -5058
- data/RUBY_VERSION +1 -1
- data/VERSION +1 -1
- data/bin/girb +31 -31
- data/bin/girb_runner.rb +34 -34
- data/bin/glimmer +26 -26
- data/docs/reference/GLIMMER_COMMAND.md +591 -0
- data/docs/reference/GLIMMER_CONFIGURATION.md +183 -0
- data/docs/reference/GLIMMER_GIRB.md +30 -0
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +3367 -0
- data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +202 -0
- data/docs/reference/GLIMMER_SAMPLES.md +755 -0
- data/docs/reference/GLIMMER_STYLE_GUIDE.md +14 -0
- data/glimmer-dsl-swt.gemspec +22 -7
- data/lib/ext/glimmer.rb +41 -41
- data/lib/ext/glimmer/config.rb +167 -167
- data/lib/ext/rouge/themes/glimmer.rb +29 -29
- data/lib/glimmer-dsl-swt.rb +44 -44
- data/lib/glimmer/Rakefile +26 -26
- data/lib/glimmer/data_binding/list_selection_binding.rb +72 -72
- data/lib/glimmer/data_binding/observable_widget.rb +38 -38
- data/lib/glimmer/data_binding/shine.rb +44 -44
- data/lib/glimmer/data_binding/table_items_binding.rb +89 -89
- data/lib/glimmer/data_binding/tree_items_binding.rb +108 -108
- data/lib/glimmer/data_binding/widget_binding.rb +73 -73
- data/lib/glimmer/dsl/swt/animation_expression.rb +43 -43
- data/lib/glimmer/dsl/swt/async_exec_expression.rb +35 -35
- data/lib/glimmer/dsl/swt/bind_expression.rb +58 -58
- data/lib/glimmer/dsl/swt/block_property_expression.rb +41 -41
- data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +61 -61
- data/lib/glimmer/dsl/swt/color_expression.rb +40 -40
- data/lib/glimmer/dsl/swt/column_properties_expression.rb +45 -45
- data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +67 -67
- data/lib/glimmer/dsl/swt/cursor_expression.rb +44 -44
- data/lib/glimmer/dsl/swt/custom_widget_expression.rb +63 -63
- data/lib/glimmer/dsl/swt/data_binding_expression.rb +55 -55
- data/lib/glimmer/dsl/swt/dialog_expression.rb +48 -48
- data/lib/glimmer/dsl/swt/directory_dialog_expression.rb +48 -48
- data/lib/glimmer/dsl/swt/display_expression.rb +40 -40
- data/lib/glimmer/dsl/swt/dnd_expression.rb +46 -46
- data/lib/glimmer/dsl/swt/dsl.rb +63 -63
- data/lib/glimmer/dsl/swt/exec_expression.rb +55 -55
- data/lib/glimmer/dsl/swt/expand_item_expression.rb +60 -60
- data/lib/glimmer/dsl/swt/file_dialog_expression.rb +48 -48
- data/lib/glimmer/dsl/swt/font_expression.rb +49 -49
- data/lib/glimmer/dsl/swt/image_expression.rb +54 -50
- data/lib/glimmer/dsl/swt/layout_data_expression.rb +46 -46
- data/lib/glimmer/dsl/swt/layout_expression.rb +50 -50
- data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +65 -65
- data/lib/glimmer/dsl/swt/menu_bar_expression.rb +54 -54
- data/lib/glimmer/dsl/swt/menu_expression.rb +53 -53
- data/lib/glimmer/dsl/swt/message_box_expression.rb +54 -54
- data/lib/glimmer/dsl/swt/multiply_expression.rb +53 -53
- data/lib/glimmer/dsl/swt/observe_expression.rb +56 -53
- data/lib/glimmer/dsl/swt/pixel_expression.rb +38 -0
- data/lib/glimmer/dsl/swt/property_expression.rb +46 -46
- data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +62 -61
- data/lib/glimmer/dsl/swt/rgb_expression.rb +33 -33
- data/lib/glimmer/dsl/swt/rgba_expression.rb +33 -33
- data/lib/glimmer/dsl/swt/shape_expression.rb +54 -54
- data/lib/glimmer/dsl/swt/shell_expression.rb +46 -46
- data/lib/glimmer/dsl/swt/swt_expression.rb +46 -46
- data/lib/glimmer/dsl/swt/sync_exec_expression.rb +36 -36
- data/lib/glimmer/dsl/swt/tab_item_expression.rb +54 -54
- data/lib/glimmer/dsl/swt/table_items_data_binding_expression.rb +52 -52
- data/lib/glimmer/dsl/swt/transform_expression.rb +55 -55
- data/lib/glimmer/dsl/swt/tree_items_data_binding_expression.rb +52 -52
- data/lib/glimmer/dsl/swt/tree_properties_expression.rb +47 -47
- data/lib/glimmer/dsl/swt/widget_expression.rb +67 -66
- data/lib/glimmer/dsl/swt/widget_listener_expression.rb +53 -53
- data/lib/glimmer/rake_task.rb +220 -220
- data/lib/glimmer/rake_task/list.rb +97 -97
- data/lib/glimmer/rake_task/package.rb +139 -139
- data/lib/glimmer/rake_task/scaffold.rb +765 -765
- data/lib/glimmer/swt/color_proxy.rb +108 -107
- data/lib/glimmer/swt/cursor_proxy.rb +66 -66
- data/lib/glimmer/swt/custom/animation.rb +245 -243
- data/lib/glimmer/swt/custom/checkbox_group.rb +181 -181
- data/lib/glimmer/swt/custom/code_text.rb +1 -0
- data/lib/glimmer/swt/custom/drawable.rb +97 -49
- data/lib/glimmer/swt/custom/radio_group.rb +177 -176
- data/lib/glimmer/swt/custom/shape.rb +332 -297
- data/lib/glimmer/swt/date_time_proxy.rb +85 -85
- data/lib/glimmer/swt/directory_dialog_proxy.rb +65 -65
- data/lib/glimmer/swt/display_proxy.rb +167 -166
- data/lib/glimmer/swt/dnd_proxy.rb +51 -51
- data/lib/glimmer/swt/expand_item_proxy.rb +97 -97
- data/lib/glimmer/swt/file_dialog_proxy.rb +66 -66
- data/lib/glimmer/swt/font_proxy.rb +94 -94
- data/lib/glimmer/swt/image_proxy.rb +195 -184
- data/lib/glimmer/swt/layout_data_proxy.rb +105 -105
- data/lib/glimmer/swt/layout_proxy.rb +112 -112
- data/lib/glimmer/swt/menu_proxy.rb +126 -126
- data/lib/glimmer/swt/message_box_proxy.rb +89 -89
- data/lib/glimmer/swt/packages.rb +37 -37
- data/lib/glimmer/swt/properties.rb +74 -49
- data/lib/glimmer/swt/sash_form_proxy.rb +53 -53
- data/lib/glimmer/swt/scrolled_composite_proxy.rb +46 -37
- data/lib/glimmer/swt/style_constantizable.rb +157 -157
- data/lib/glimmer/swt/styled_text_proxy.rb +38 -38
- data/lib/glimmer/swt/swt_proxy.rb +59 -59
- data/lib/glimmer/swt/tab_item_proxy.rb +92 -91
- data/lib/glimmer/swt/table_column_proxy.rb +57 -57
- data/lib/glimmer/swt/transform_proxy.rb +109 -109
- data/lib/glimmer/swt/tree_proxy.rb +145 -145
- data/lib/glimmer/swt/widget_listener_proxy.rb +64 -64
- data/lib/glimmer/swt/widget_proxy.rb +977 -957
- data/lib/glimmer/ui/custom_shell.rb +82 -82
- data/lib/glimmer/ui/custom_widget.rb +332 -315
- data/lib/glimmer/util/proc_tracker.rb +39 -39
- data/samples/elaborate/contact_manager.rb +142 -142
- data/samples/elaborate/contact_manager/contact.rb +32 -32
- data/samples/elaborate/contact_manager/contact_manager_presenter.rb +47 -47
- data/samples/elaborate/contact_manager/contact_repository.rb +169 -169
- data/samples/elaborate/login.rb +123 -123
- data/samples/elaborate/mandelbrot_fractal.rb +354 -0
- data/samples/elaborate/tetris.rb +5 -18
- data/samples/elaborate/tetris/model/block.rb +48 -48
- data/samples/elaborate/tetris/model/past_game.rb +39 -39
- data/samples/elaborate/tetris/view/block.rb +1 -1
- data/samples/elaborate/tetris/view/playfield.rb +1 -1
- data/samples/elaborate/tic_tac_toe.rb +76 -76
- data/samples/elaborate/tic_tac_toe/board.rb +145 -145
- data/samples/elaborate/tic_tac_toe/cell.rb +48 -48
- data/samples/elaborate/user_profile.rb +76 -76
- data/samples/hello/hello_browser.rb +31 -31
- data/samples/hello/hello_button.rb +46 -46
- data/samples/hello/hello_canvas.rb +64 -64
- data/samples/hello/hello_canvas_animation.rb +1 -1
- data/samples/hello/hello_checkbox.rb +85 -85
- data/samples/hello/hello_checkbox_group.rb +71 -71
- data/samples/hello/hello_code_text.rb +104 -104
- data/samples/hello/hello_combo.rb +63 -63
- data/samples/hello/hello_computed.rb +96 -96
- data/samples/hello/hello_computed/contact.rb +42 -42
- data/samples/hello/hello_cursor.rb +57 -0
- data/samples/hello/hello_custom_shell.rb +155 -155
- data/samples/hello/hello_custom_widget.rb +86 -86
- data/samples/hello/hello_date_time.rb +63 -63
- data/samples/hello/hello_dialog.rb +78 -78
- data/samples/hello/hello_directory_dialog.rb +60 -60
- data/samples/hello/hello_drag_and_drop.rb +50 -50
- data/samples/hello/hello_expand_bar.rb +110 -110
- data/samples/hello/hello_file_dialog.rb +60 -60
- data/samples/hello/hello_group.rb +104 -104
- data/samples/hello/hello_link.rb +80 -80
- data/samples/hello/hello_list_multi_selection.rb +74 -74
- data/samples/hello/hello_list_single_selection.rb +59 -59
- data/samples/hello/hello_menu_bar.rb +241 -241
- data/samples/hello/hello_message_box.rb +37 -37
- data/samples/hello/hello_pop_up_context_menu.rb +84 -84
- data/samples/hello/hello_radio.rb +108 -108
- data/samples/hello/hello_radio_group.rb +87 -87
- data/samples/hello/hello_sash_form.rb +137 -137
- data/samples/hello/hello_spinner.rb +69 -69
- data/samples/hello/hello_styled_text.rb +138 -138
- data/samples/hello/hello_tab.rb +50 -50
- data/samples/hello/hello_table.rb +1 -1
- data/samples/hello/hello_table/baseball_park.png +0 -0
- data/samples/hello/hello_world.rb +29 -29
- 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
|
data/samples/elaborate/tetris.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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
|