glimmer-dsl-swt 4.18.4.9 → 4.18.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +73 -0
- data/README.md +14 -5
- data/VERSION +1 -1
- data/bin/glimmer +3 -3
- data/docs/reference/GLIMMER_CONFIGURATION.md +7 -3
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +464 -149
- data/docs/reference/GLIMMER_SAMPLES.md +91 -4
- data/glimmer-dsl-swt.gemspec +24 -13
- data/lib/ext/glimmer/config.rb +3 -7
- data/lib/glimmer/data_binding/list_selection_binding.rb +13 -7
- data/lib/glimmer/data_binding/table_items_binding.rb +22 -17
- data/lib/glimmer/data_binding/tree_items_binding.rb +19 -15
- data/lib/glimmer/data_binding/widget_binding.rb +13 -15
- data/lib/glimmer/dsl/swt/{file_dialog_expression.rb → auto_exec_expression.rb} +6 -18
- data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +9 -6
- data/lib/glimmer/dsl/swt/color_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +16 -14
- data/lib/glimmer/dsl/swt/custom_widget_expression.rb +4 -1
- data/lib/glimmer/dsl/swt/data_binding_expression.rb +2 -2
- data/lib/glimmer/dsl/swt/dialog_expression.rb +18 -9
- data/lib/glimmer/dsl/swt/dsl.rb +1 -0
- data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/font_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/image_expression.rb +16 -2
- data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +11 -8
- data/lib/glimmer/dsl/swt/pixel_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +8 -5
- data/lib/glimmer/dsl/swt/shape_expression.rb +2 -2
- data/lib/glimmer/dsl/swt/shell_expression.rb +5 -2
- data/lib/glimmer/dsl/swt/widget_expression.rb +8 -4
- data/lib/glimmer/launcher.rb +3 -0
- data/lib/glimmer/rake_task/scaffold.rb +3 -0
- data/lib/glimmer/swt/color_proxy.rb +1 -1
- data/lib/glimmer/swt/custom/code_text.rb +33 -11
- data/lib/glimmer/swt/custom/drawable.rb +55 -0
- data/lib/glimmer/swt/custom/shape.rb +187 -43
- data/lib/glimmer/swt/custom/shape/arc.rb +60 -0
- data/lib/glimmer/{dsl/swt/directory_dialog_expression.rb → swt/custom/shape/focus.rb} +15 -20
- data/lib/glimmer/swt/custom/shape/image.rb +99 -0
- data/lib/glimmer/swt/custom/shape/line.rb +65 -0
- data/lib/glimmer/swt/custom/shape/oval.rb +61 -0
- data/lib/glimmer/swt/custom/shape/point.rb +54 -0
- data/lib/glimmer/swt/custom/shape/polygon.rb +73 -0
- data/lib/glimmer/swt/custom/shape/polyline.rb +74 -0
- data/lib/glimmer/swt/custom/shape/rectangle.rb +101 -0
- data/lib/glimmer/swt/custom/shape/text.rb +85 -0
- data/lib/glimmer/swt/date_time_proxy.rb +9 -3
- data/lib/glimmer/swt/dialog_proxy.rb +92 -0
- data/lib/glimmer/swt/display_proxy.rb +62 -2
- data/lib/glimmer/swt/expand_item_proxy.rb +18 -12
- data/lib/glimmer/swt/font_proxy.rb +13 -7
- data/lib/glimmer/swt/image_proxy.rb +15 -4
- data/lib/glimmer/swt/layout_data_proxy.rb +21 -15
- data/lib/glimmer/swt/layout_proxy.rb +19 -15
- data/lib/glimmer/swt/menu_proxy.rb +2 -2
- data/lib/glimmer/swt/message_box_proxy.rb +21 -7
- data/lib/glimmer/swt/properties.rb +3 -0
- data/lib/glimmer/swt/proxy_properties.rb +145 -0
- data/lib/glimmer/swt/scrolled_composite_proxy.rb +6 -2
- data/lib/glimmer/swt/shell_proxy.rb +96 -80
- data/lib/glimmer/swt/swt_proxy.rb +17 -0
- data/lib/glimmer/swt/tab_item_proxy.rb +5 -3
- data/lib/glimmer/swt/table_proxy.rb +32 -11
- data/lib/glimmer/swt/transform_proxy.rb +39 -35
- data/lib/glimmer/swt/tree_proxy.rb +11 -16
- data/lib/glimmer/swt/widget_listener_proxy.rb +6 -2
- data/lib/glimmer/swt/widget_proxy.rb +192 -141
- data/lib/glimmer/ui.rb +5 -0
- data/lib/glimmer/ui/custom_shell.rb +13 -7
- data/lib/glimmer/ui/custom_widget.rb +4 -5
- data/samples/elaborate/contact_manager.rb +7 -7
- data/samples/elaborate/login.rb +25 -21
- data/samples/elaborate/mandelbrot_fractal.rb +87 -31
- data/samples/elaborate/meta_sample.rb +1 -1
- data/samples/elaborate/tetris.rb +1 -0
- data/samples/elaborate/tic_tac_toe.rb +16 -14
- data/samples/elaborate/tic_tac_toe/board.rb +5 -5
- data/samples/elaborate/tic_tac_toe/cell.rb +5 -5
- data/samples/hello/hello_button.rb +7 -7
- data/samples/hello/hello_canvas.rb +143 -41
- data/samples/hello/hello_checkbox.rb +16 -14
- data/samples/hello/hello_checkbox_group.rb +11 -9
- data/samples/hello/hello_color_dialog.rb +66 -0
- data/samples/hello/hello_combo.rb +14 -12
- data/samples/hello/hello_computed.rb +7 -7
- data/samples/hello/hello_cursor.rb +2 -1
- data/samples/hello/hello_custom_shell.rb +17 -21
- data/samples/hello/hello_custom_widget.rb +4 -6
- data/samples/hello/hello_date_time.rb +14 -12
- data/samples/hello/hello_directory_dialog.rb +7 -7
- data/samples/hello/hello_expand_bar.rb +8 -8
- data/samples/hello/hello_file_dialog.rb +7 -7
- data/samples/hello/hello_font_dialog.rb +82 -0
- data/samples/hello/hello_group.rb +18 -16
- data/samples/hello/hello_list_multi_selection.rb +13 -11
- data/samples/hello/hello_list_single_selection.rb +13 -11
- data/samples/hello/hello_progress_bar.rb +125 -0
- data/samples/hello/hello_radio.rb +18 -16
- data/samples/hello/hello_radio_group.rb +14 -12
- data/samples/hello/hello_spinner.rb +7 -7
- data/samples/hello/hello_tab.rb +5 -5
- data/samples/hello/hello_table.rb +10 -5
- data/samples/hello/hello_tree.rb +485 -0
- metadata +22 -22
- data/lib/glimmer/swt/directory_dialog_proxy.rb +0 -65
- data/lib/glimmer/swt/file_dialog_proxy.rb +0 -66
data/lib/glimmer/ui.rb
ADDED
@@ -19,6 +19,7 @@
|
|
19
19
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
+
require 'glimmer/ui'
|
22
23
|
require 'glimmer/error'
|
23
24
|
|
24
25
|
module Glimmer
|
@@ -28,19 +29,22 @@ module Glimmer
|
|
28
29
|
include Glimmer::UI::CustomWidget
|
29
30
|
|
30
31
|
class << self
|
31
|
-
attr_reader :launched_custom_shell
|
32
|
-
|
33
32
|
def launch(*args, &content)
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
auto_exec do
|
34
|
+
@launched_custom_shell = send(keyword, *args, &content)
|
35
|
+
@launched_custom_shell.swt_widget.set_data('launched', true)
|
36
|
+
@launched_custom_shell.open
|
37
|
+
end
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
41
|
def initialize(parent, *swt_constants, options, &content)
|
41
42
|
super
|
42
|
-
|
43
|
-
|
43
|
+
auto_exec do
|
44
|
+
@swt_widget.set_data('custom_shell', self)
|
45
|
+
@swt_widget.set_data('custom_window', self)
|
46
|
+
end
|
47
|
+
raise Error, 'Invalid custom shell (window) body root! Must be a shell (window) or another custom shell (window).' unless body_root.swt_widget.is_a?(org.eclipse.swt.widgets.Shell)
|
44
48
|
end
|
45
49
|
|
46
50
|
# Classes may override
|
@@ -78,5 +82,7 @@ module Glimmer
|
|
78
82
|
body_root.start_event_loop
|
79
83
|
end
|
80
84
|
end
|
85
|
+
CustomWindow = CustomShell
|
86
|
+
Application = CustomShell
|
81
87
|
end
|
82
88
|
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer'
|
23
|
+
require 'glimmer/ui'
|
23
24
|
require 'glimmer/error'
|
24
25
|
require 'glimmer/swt/swt_proxy'
|
25
26
|
require 'glimmer/swt/display_proxy'
|
@@ -181,7 +182,9 @@ module Glimmer
|
|
181
182
|
@body_root = instance_exec(&body_block)
|
182
183
|
raise Glimmer::Error, 'Invalid custom widget for having an empty body! Please fill body block!' if @body_root.nil?
|
183
184
|
@swt_widget = @body_root.swt_widget
|
184
|
-
|
185
|
+
auto_exec do
|
186
|
+
@swt_widget.set_data('custom_widget', self)
|
187
|
+
end
|
185
188
|
execute_hook('after_body')
|
186
189
|
@dispose_listener_registration = @body_root.on_widget_disposed do
|
187
190
|
observer_registrations.each(&:deregister)
|
@@ -271,10 +274,6 @@ module Glimmer
|
|
271
274
|
(swt_style & SWT::SWTProxy[style]) == SWT::SWTProxy[style]
|
272
275
|
end
|
273
276
|
|
274
|
-
def pack(*args)
|
275
|
-
body_root.pack(*args)
|
276
|
-
end
|
277
|
-
|
278
277
|
# TODO see if it is worth it to eliminate duplication of async_exec/sync_exec
|
279
278
|
# delegation to DisplayProxy, via a module
|
280
279
|
|
@@ -22,14 +22,14 @@
|
|
22
22
|
require_relative "contact_manager/contact_manager_presenter"
|
23
23
|
|
24
24
|
class ContactManager
|
25
|
-
include Glimmer
|
25
|
+
include Glimmer::UI::CustomShell
|
26
26
|
|
27
|
-
|
27
|
+
before_body {
|
28
28
|
@contact_manager_presenter = ContactManagerPresenter.new
|
29
29
|
@contact_manager_presenter.list
|
30
|
-
|
30
|
+
}
|
31
31
|
|
32
|
-
|
32
|
+
body {
|
33
33
|
shell {
|
34
34
|
text "Contact Manager"
|
35
35
|
composite {
|
@@ -135,8 +135,8 @@ class ContactManager
|
|
135
135
|
}
|
136
136
|
}
|
137
137
|
}
|
138
|
-
}
|
139
|
-
|
138
|
+
}
|
139
|
+
}
|
140
140
|
end
|
141
141
|
|
142
|
-
ContactManager.
|
142
|
+
ContactManager.launch
|
data/samples/elaborate/login.rb
CHANGED
@@ -45,17 +45,19 @@ class LoginPresenter
|
|
45
45
|
def logged_in
|
46
46
|
self.status == "Logged In"
|
47
47
|
end
|
48
|
+
alias logged_in? logged_in
|
48
49
|
|
49
50
|
def logged_out
|
50
51
|
!self.logged_in
|
51
52
|
end
|
53
|
+
alias logged_out? logged_out
|
52
54
|
|
53
|
-
def login
|
55
|
+
def login!
|
54
56
|
return unless valid?
|
55
57
|
self.status = "Logged In"
|
56
58
|
end
|
57
59
|
|
58
|
-
def logout
|
60
|
+
def logout!
|
59
61
|
self.user_name = ""
|
60
62
|
self.password = ""
|
61
63
|
self.status = "Logged Out"
|
@@ -64,19 +66,22 @@ class LoginPresenter
|
|
64
66
|
end
|
65
67
|
|
66
68
|
class Login
|
67
|
-
include Glimmer
|
69
|
+
include Glimmer::UI::CustomShell
|
68
70
|
|
69
|
-
|
70
|
-
presenter = LoginPresenter.new
|
71
|
-
|
71
|
+
before_body {
|
72
|
+
@presenter = LoginPresenter.new
|
73
|
+
}
|
74
|
+
|
75
|
+
body {
|
76
|
+
shell {
|
72
77
|
text "Login"
|
73
78
|
composite {
|
74
79
|
grid_layout 2, false #two columns with differing widths
|
75
80
|
|
76
81
|
label { text "Username:" } # goes in column 1
|
77
82
|
@user_name_text = text { # goes in column 2
|
78
|
-
text bind(presenter, :user_name)
|
79
|
-
enabled bind(presenter, :logged_out)
|
83
|
+
text bind(@presenter, :user_name)
|
84
|
+
enabled bind(@presenter, :logged_out)
|
80
85
|
on_key_pressed { |event|
|
81
86
|
@password_text.set_focus if event.keyCode == swt(:cr)
|
82
87
|
}
|
@@ -84,40 +89,39 @@ class Login
|
|
84
89
|
|
85
90
|
label { text "Password:" }
|
86
91
|
@password_text = text(:password, :border) {
|
87
|
-
text bind(presenter, :password)
|
88
|
-
enabled bind(presenter, :logged_out)
|
92
|
+
text bind(@presenter, :password)
|
93
|
+
enabled bind(@presenter, :logged_out)
|
89
94
|
on_key_pressed { |event|
|
90
|
-
presenter.login if event.keyCode == swt(:cr)
|
95
|
+
@presenter.login! if event.keyCode == swt(:cr)
|
91
96
|
}
|
92
97
|
}
|
93
98
|
|
94
99
|
label { text "Status:" }
|
95
|
-
label { text bind(presenter, :status) }
|
100
|
+
label { text bind(@presenter, :status) }
|
96
101
|
|
97
102
|
button {
|
98
103
|
text "Login"
|
99
|
-
enabled bind(presenter, :logged_out)
|
100
|
-
on_widget_selected { presenter.login }
|
104
|
+
enabled bind(@presenter, :logged_out)
|
105
|
+
on_widget_selected { @presenter.login! }
|
101
106
|
on_key_pressed { |event|
|
102
|
-
presenter.login if event.keyCode == swt(:cr)
|
107
|
+
@presenter.login! if event.keyCode == swt(:cr)
|
103
108
|
}
|
104
109
|
}
|
105
110
|
|
106
111
|
button {
|
107
112
|
text "Logout"
|
108
|
-
enabled bind(presenter, :logged_in)
|
109
|
-
on_widget_selected { presenter.logout }
|
113
|
+
enabled bind(@presenter, :logged_in)
|
114
|
+
on_widget_selected { @presenter.logout! }
|
110
115
|
on_key_pressed { |event|
|
111
116
|
if event.keyCode == swt(:cr)
|
112
|
-
presenter.logout
|
117
|
+
@presenter.logout!
|
113
118
|
@user_name_text.set_focus
|
114
119
|
end
|
115
120
|
}
|
116
121
|
}
|
117
122
|
}
|
118
123
|
}
|
119
|
-
|
120
|
-
end
|
124
|
+
}
|
121
125
|
end
|
122
126
|
|
123
|
-
Login.
|
127
|
+
Login.launch
|
@@ -20,7 +20,6 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'complex'
|
23
|
-
require 'bigdecimal'
|
24
23
|
require 'concurrent-ruby'
|
25
24
|
|
26
25
|
# Mandelbrot multi-threaded implementation leveraging all processor cores.
|
@@ -30,8 +29,12 @@ class Mandelbrot
|
|
30
29
|
Y_END = 1.0
|
31
30
|
X_START = -2.0
|
32
31
|
X_END = 0.5
|
32
|
+
PROGRESS_MAX = 40
|
33
33
|
|
34
34
|
class << self
|
35
|
+
attr_accessor :progress, :work_in_progress
|
36
|
+
attr_writer :processor_count
|
37
|
+
|
35
38
|
def for(max_iterations:, zoom:, background: false)
|
36
39
|
key = [max_iterations, zoom]
|
37
40
|
creation_mutex.synchronize do
|
@@ -50,6 +53,10 @@ class Mandelbrot
|
|
50
53
|
def creation_mutex
|
51
54
|
@creation_mutex ||= Mutex.new
|
52
55
|
end
|
56
|
+
|
57
|
+
def processor_count
|
58
|
+
@processor_count ||= Concurrent.physical_processor_count
|
59
|
+
end
|
53
60
|
end
|
54
61
|
|
55
62
|
attr_accessor :max_iterations, :background
|
@@ -63,7 +70,6 @@ class Mandelbrot
|
|
63
70
|
def initialize(max_iterations:, zoom: 1.0, background: false)
|
64
71
|
@max_iterations = max_iterations
|
65
72
|
@zoom = zoom
|
66
|
-
@background = background
|
67
73
|
end
|
68
74
|
|
69
75
|
def step
|
@@ -90,28 +96,31 @@ class Mandelbrot
|
|
90
96
|
@points ||= calculate_points
|
91
97
|
end
|
92
98
|
|
93
|
-
def thread_count
|
94
|
-
@background ? [Concurrent.processor_count - 1, 1].max : Concurrent.processor_count
|
95
|
-
end
|
96
|
-
|
97
99
|
def calculate_points
|
98
100
|
puts "Background calculation activated at zoom #{zoom}" if @background
|
99
101
|
if @points_calculated
|
100
102
|
puts "Points calculated already. Returning previously calculated points..."
|
101
103
|
return @points
|
102
104
|
end
|
103
|
-
thread_pool = Concurrent::FixedThreadPool.new(
|
105
|
+
thread_pool = Concurrent::FixedThreadPool.new(Mandelbrot.processor_count, fallback_policy: :discard)
|
104
106
|
@points = Concurrent::Array.new(height)
|
107
|
+
Mandelbrot.work_in_progress = "Calculating Mandelbrot Points for Zoom #{zoom}x"
|
108
|
+
Mandelbrot.progress = 0
|
109
|
+
point_index = 0
|
110
|
+
point_count = width*height
|
105
111
|
height.times do |y|
|
106
112
|
@points[y] ||= Concurrent::Array.new(width)
|
107
113
|
width.times do |x|
|
108
114
|
thread_pool.post do
|
109
115
|
@points[y][x] = calculate(x_array[x], y_array[y]).last
|
116
|
+
point_index += 1
|
117
|
+
Mandelbrot.progress += 1 if (point_index.to_f / point_count.to_f)*PROGRESS_MAX >= Mandelbrot.progress
|
110
118
|
end
|
111
119
|
end
|
112
120
|
end
|
113
121
|
thread_pool.shutdown
|
114
122
|
thread_pool.wait_for_termination
|
123
|
+
Mandelbrot.progress = PROGRESS_MAX
|
115
124
|
@points_calculated = true
|
116
125
|
@points
|
117
126
|
end
|
@@ -132,9 +141,11 @@ end
|
|
132
141
|
|
133
142
|
class MandelbrotFractal
|
134
143
|
include Glimmer::UI::CustomShell
|
135
|
-
|
136
|
-
COMMAND = OS.mac? ? :command : :ctrl
|
137
144
|
|
145
|
+
COMMAND = OS.mac? ? :command : :ctrl
|
146
|
+
|
147
|
+
attr_accessor :mandelbrot_shell_title
|
148
|
+
|
138
149
|
option :zoom, default: 1.0
|
139
150
|
|
140
151
|
before_body {
|
@@ -144,6 +155,12 @@ class MandelbrotFractal
|
|
144
155
|
}
|
145
156
|
|
146
157
|
after_body {
|
158
|
+
observe(Mandelbrot, :work_in_progress) {
|
159
|
+
update_mandelbrot_shell_title!
|
160
|
+
}
|
161
|
+
observe(Mandelbrot, :zoom) {
|
162
|
+
update_mandelbrot_shell_title!
|
163
|
+
}
|
147
164
|
# pre-calculate zoomed mandelbrot images even before the user zooms in
|
148
165
|
puts 'Starting background calculation thread...'
|
149
166
|
Thread.new {
|
@@ -153,10 +170,7 @@ class MandelbrotFractal
|
|
153
170
|
the_mandelbrot = Mandelbrot.for(max_iterations: color_palette.size - 1, zoom: future_zoom, background: true)
|
154
171
|
pixels = the_mandelbrot.calculate_points
|
155
172
|
build_mandelbrot_image(mandelbrot_zoom: future_zoom)
|
156
|
-
|
157
|
-
swt_widget.text = mandelbrot_shell_title
|
158
|
-
@canvas.cursor = :cross
|
159
|
-
}
|
173
|
+
@canvas.cursor = :cross unless @canvas.disposed?
|
160
174
|
future_zoom += 0.5
|
161
175
|
}
|
162
176
|
}
|
@@ -164,11 +178,21 @@ class MandelbrotFractal
|
|
164
178
|
|
165
179
|
body {
|
166
180
|
shell(:no_resize) {
|
167
|
-
|
168
|
-
|
181
|
+
grid_layout
|
182
|
+
text bind(self, :mandelbrot_shell_title)
|
183
|
+
minimum_size mandelbrot.width + 29, mandelbrot.height + 77
|
169
184
|
image @mandelbrot_image
|
170
185
|
|
186
|
+
progress_bar {
|
187
|
+
layout_data :fill, :center, true, false
|
188
|
+
|
189
|
+
minimum 0
|
190
|
+
maximum Mandelbrot::PROGRESS_MAX
|
191
|
+
selection bind(Mandelbrot, :progress)
|
192
|
+
}
|
193
|
+
|
171
194
|
@scrolled_composite = scrolled_composite {
|
195
|
+
layout_data :fill, :fill, true, true
|
172
196
|
@canvas = canvas {
|
173
197
|
image @mandelbrot_image
|
174
198
|
cursor :no
|
@@ -196,8 +220,8 @@ class MandelbrotFractal
|
|
196
220
|
on_mouse_up { |mouse_event|
|
197
221
|
if !@drag_detected
|
198
222
|
origin = @scrolled_composite.origin
|
199
|
-
@location_x =
|
200
|
-
@location_y =
|
223
|
+
@location_x = mouse_event.x
|
224
|
+
@location_y = mouse_event.y
|
201
225
|
if mouse_event.button == 1
|
202
226
|
zoom_in
|
203
227
|
elsif mouse_event.button > 2
|
@@ -236,6 +260,31 @@ class MandelbrotFractal
|
|
236
260
|
on_widget_selected { perform_zoom(mandelbrot_zoom: 1.0) }
|
237
261
|
}
|
238
262
|
}
|
263
|
+
menu {
|
264
|
+
text '&Cores'
|
265
|
+
|
266
|
+
Concurrent.physical_processor_count.times {|n|
|
267
|
+
processor_number = n + 1
|
268
|
+
menu_item(:radio) {
|
269
|
+
text "&#{processor_number}"
|
270
|
+
|
271
|
+
case processor_number
|
272
|
+
when 0..9
|
273
|
+
accelerator COMMAND, processor_number.to_s
|
274
|
+
when 10..19
|
275
|
+
accelerator COMMAND, :shift, (processor_number - 10).to_s
|
276
|
+
when 20..29
|
277
|
+
accelerator COMMAND, :alt, (processor_number - 20).to_s
|
278
|
+
end
|
279
|
+
|
280
|
+
selection true if processor_number == Concurrent.physical_processor_count
|
281
|
+
|
282
|
+
on_widget_selected {
|
283
|
+
Mandelbrot.processor_count = processor_number
|
284
|
+
}
|
285
|
+
}
|
286
|
+
}
|
287
|
+
}
|
239
288
|
menu {
|
240
289
|
text '&Help'
|
241
290
|
|
@@ -251,9 +300,11 @@ class MandelbrotFractal
|
|
251
300
|
}
|
252
301
|
}
|
253
302
|
}
|
254
|
-
|
255
|
-
def
|
256
|
-
"Mandelbrot Fractal - Zoom #{zoom}x (Calculated Max: #{flyweight_mandelbrot_images.keys.max}x)"
|
303
|
+
|
304
|
+
def update_mandelbrot_shell_title!
|
305
|
+
new_title = "Mandelbrot Fractal - Zoom #{zoom}x (Calculated Max: #{flyweight_mandelbrot_images.keys.max}x)"
|
306
|
+
new_title += " - #{Mandelbrot.work_in_progress}" if Mandelbrot.work_in_progress
|
307
|
+
self.mandelbrot_shell_title = new_title
|
257
308
|
end
|
258
309
|
|
259
310
|
def build_mandelbrot_image(mandelbrot_zoom: nil)
|
@@ -263,17 +314,20 @@ class MandelbrotFractal
|
|
263
314
|
width = the_mandelbrot.width
|
264
315
|
height = the_mandelbrot.height
|
265
316
|
pixels = the_mandelbrot.points
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
317
|
+
Mandelbrot.work_in_progress = "Consuming Points To Build Image for Zoom #{mandelbrot_zoom}x"
|
318
|
+
Mandelbrot.progress = Mandelbrot::PROGRESS_MAX + 1
|
319
|
+
point_index = 0
|
320
|
+
point_count = width*height
|
321
|
+
# invoke as a top-level parentless keyword to avoid nesting under any widget
|
322
|
+
new_mandelbrot_image = image(width, height, top_level: true) { |x, y|
|
323
|
+
point_index += 1
|
324
|
+
Mandelbrot.progress -= 1 if (Mandelbrot::PROGRESS_MAX - (point_index.to_f / point_count.to_f)*Mandelbrot::PROGRESS_MAX) < Mandelbrot.progress
|
325
|
+
pixel_color_index = pixels[y][x]
|
326
|
+
color_palette[pixel_color_index]
|
275
327
|
}
|
328
|
+
Mandelbrot.progress = 0
|
276
329
|
flyweight_mandelbrot_images[mandelbrot_zoom] = new_mandelbrot_image
|
330
|
+
update_mandelbrot_shell_title!
|
277
331
|
end
|
278
332
|
flyweight_mandelbrot_images[mandelbrot_zoom]
|
279
333
|
end
|
@@ -326,12 +380,13 @@ class MandelbrotFractal
|
|
326
380
|
@canvas.set_size @mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height
|
327
381
|
@scrolled_composite.swt_widget.set_min_size(Point.new(@mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height))
|
328
382
|
if @location_x && @location_y
|
383
|
+
# center on mouse click location
|
329
384
|
factor = (zoom / last_zoom)
|
330
|
-
@scrolled_composite.set_origin(factor*@location_x, factor*@location_y)
|
385
|
+
@scrolled_composite.set_origin(factor*@location_x - @scrolled_composite.client_area.width/2.0, factor*@location_y - @scrolled_composite.client_area.height/2.0)
|
331
386
|
@location_x = @location_y = nil
|
332
387
|
end
|
388
|
+
update_mandelbrot_shell_title!
|
333
389
|
@canvas.cursor = :cross
|
334
|
-
swt_widget.text = mandelbrot_shell_title
|
335
390
|
end
|
336
391
|
|
337
392
|
def display_help_instructions
|
@@ -343,6 +398,7 @@ class MandelbrotFractal
|
|
343
398
|
Left-click to zoom in.
|
344
399
|
Right-click to zoom out.
|
345
400
|
Scroll or drag to pan.
|
401
|
+
Adjust cores to get a more responsive interaction.
|
346
402
|
|
347
403
|
Enjoy!
|
348
404
|
MULTI_LINE_STRING
|