glimmer-dsl-swt 4.18.4.10 → 4.18.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +71 -0
  3. data/README.md +14 -5
  4. data/VERSION +1 -1
  5. data/bin/glimmer +3 -3
  6. data/docs/reference/GLIMMER_CONFIGURATION.md +7 -3
  7. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +451 -112
  8. data/docs/reference/GLIMMER_SAMPLES.md +76 -3
  9. data/glimmer-dsl-swt.gemspec +23 -13
  10. data/lib/ext/glimmer/config.rb +3 -7
  11. data/lib/glimmer/data_binding/list_selection_binding.rb +13 -7
  12. data/lib/glimmer/data_binding/table_items_binding.rb +22 -17
  13. data/lib/glimmer/data_binding/tree_items_binding.rb +19 -15
  14. data/lib/glimmer/data_binding/widget_binding.rb +12 -27
  15. data/lib/glimmer/dsl/swt/{file_dialog_expression.rb → auto_exec_expression.rb} +6 -18
  16. data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +9 -6
  17. data/lib/glimmer/dsl/swt/color_expression.rb +1 -1
  18. data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +16 -14
  19. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +4 -1
  20. data/lib/glimmer/dsl/swt/data_binding_expression.rb +1 -2
  21. data/lib/glimmer/dsl/swt/dialog_expression.rb +18 -9
  22. data/lib/glimmer/dsl/swt/dsl.rb +1 -0
  23. data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
  24. data/lib/glimmer/dsl/swt/font_expression.rb +1 -1
  25. data/lib/glimmer/dsl/swt/image_expression.rb +16 -2
  26. data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +11 -8
  27. data/lib/glimmer/dsl/swt/pixel_expression.rb +1 -1
  28. data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +8 -5
  29. data/lib/glimmer/dsl/swt/shape_expression.rb +2 -2
  30. data/lib/glimmer/dsl/swt/shell_expression.rb +1 -1
  31. data/lib/glimmer/dsl/swt/widget_expression.rb +8 -4
  32. data/lib/glimmer/launcher.rb +3 -0
  33. data/lib/glimmer/rake_task/scaffold.rb +3 -0
  34. data/lib/glimmer/swt/color_proxy.rb +1 -1
  35. data/lib/glimmer/swt/custom/code_text.rb +33 -11
  36. data/lib/glimmer/swt/custom/drawable.rb +57 -1
  37. data/lib/glimmer/swt/custom/shape.rb +332 -48
  38. data/lib/glimmer/swt/custom/shape/arc.rb +60 -0
  39. data/lib/glimmer/{dsl/swt/directory_dialog_expression.rb → swt/custom/shape/focus.rb} +15 -20
  40. data/lib/glimmer/swt/custom/shape/image.rb +112 -0
  41. data/lib/glimmer/swt/custom/shape/line.rb +111 -0
  42. data/lib/glimmer/swt/custom/shape/oval.rb +61 -0
  43. data/lib/glimmer/swt/custom/shape/point.rb +49 -0
  44. data/lib/glimmer/swt/custom/shape/polygon.rb +114 -0
  45. data/lib/glimmer/swt/custom/shape/polyline.rb +115 -0
  46. data/lib/glimmer/swt/custom/shape/rectangle.rb +105 -0
  47. data/lib/glimmer/swt/custom/shape/text.rb +85 -0
  48. data/lib/glimmer/swt/date_time_proxy.rb +9 -3
  49. data/lib/glimmer/swt/dialog_proxy.rb +92 -0
  50. data/lib/glimmer/swt/display_proxy.rb +62 -2
  51. data/lib/glimmer/swt/expand_item_proxy.rb +18 -12
  52. data/lib/glimmer/swt/font_proxy.rb +13 -7
  53. data/lib/glimmer/swt/image_proxy.rb +15 -4
  54. data/lib/glimmer/swt/layout_data_proxy.rb +21 -15
  55. data/lib/glimmer/swt/layout_proxy.rb +19 -15
  56. data/lib/glimmer/swt/menu_proxy.rb +2 -2
  57. data/lib/glimmer/swt/message_box_proxy.rb +21 -7
  58. data/lib/glimmer/swt/properties.rb +3 -0
  59. data/lib/glimmer/swt/proxy_properties.rb +145 -0
  60. data/lib/glimmer/swt/scrolled_composite_proxy.rb +6 -2
  61. data/lib/glimmer/swt/shell_proxy.rb +94 -80
  62. data/lib/glimmer/swt/swt_proxy.rb +16 -0
  63. data/lib/glimmer/swt/tab_item_proxy.rb +5 -3
  64. data/lib/glimmer/swt/table_proxy.rb +32 -11
  65. data/lib/glimmer/swt/transform_proxy.rb +39 -35
  66. data/lib/glimmer/swt/tree_proxy.rb +11 -16
  67. data/lib/glimmer/swt/widget_listener_proxy.rb +6 -2
  68. data/lib/glimmer/swt/widget_proxy.rb +193 -138
  69. data/lib/glimmer/ui.rb +5 -0
  70. data/lib/glimmer/ui/custom_shell.rb +11 -5
  71. data/lib/glimmer/ui/custom_widget.rb +4 -5
  72. data/samples/elaborate/contact_manager.rb +9 -7
  73. data/samples/elaborate/login.rb +27 -21
  74. data/samples/elaborate/mandelbrot_fractal.rb +20 -25
  75. data/samples/elaborate/meta_sample.rb +2 -1
  76. data/samples/elaborate/tetris.rb +3 -1
  77. data/samples/elaborate/tic_tac_toe.rb +18 -14
  78. data/samples/elaborate/tic_tac_toe/board.rb +5 -5
  79. data/samples/elaborate/tic_tac_toe/cell.rb +5 -5
  80. data/samples/elaborate/user_profile.rb +10 -8
  81. data/samples/hello/hello_browser.rb +2 -0
  82. data/samples/hello/hello_button.rb +9 -7
  83. data/samples/hello/hello_canvas.rb +144 -40
  84. data/samples/hello/hello_canvas_animation.rb +2 -0
  85. data/samples/hello/hello_canvas_transform.rb +2 -0
  86. data/samples/hello/hello_checkbox.rb +18 -14
  87. data/samples/hello/hello_checkbox_group.rb +13 -9
  88. data/samples/hello/hello_code_text.rb +2 -0
  89. data/samples/hello/hello_color_dialog.rb +68 -0
  90. data/samples/hello/hello_combo.rb +16 -12
  91. data/samples/hello/hello_computed.rb +9 -7
  92. data/samples/hello/hello_cursor.rb +4 -1
  93. data/samples/hello/hello_custom_shell.rb +18 -21
  94. data/samples/hello/hello_custom_widget.rb +6 -6
  95. data/samples/hello/hello_date_time.rb +16 -12
  96. data/samples/hello/hello_dialog.rb +2 -0
  97. data/samples/hello/hello_directory_dialog.rb +9 -7
  98. data/samples/hello/hello_drag_and_drop.rb +5 -3
  99. data/samples/hello/hello_expand_bar.rb +10 -8
  100. data/samples/hello/hello_file_dialog.rb +9 -7
  101. data/samples/hello/hello_font_dialog.rb +84 -0
  102. data/samples/hello/hello_group.rb +20 -16
  103. data/samples/hello/hello_link.rb +2 -0
  104. data/samples/hello/hello_list_multi_selection.rb +15 -11
  105. data/samples/hello/hello_list_single_selection.rb +15 -11
  106. data/samples/hello/hello_menu_bar.rb +2 -0
  107. data/samples/hello/hello_message_box.rb +2 -0
  108. data/samples/hello/hello_pop_up_context_menu.rb +2 -0
  109. data/samples/hello/hello_progress_bar.rb +5 -5
  110. data/samples/hello/hello_radio.rb +20 -16
  111. data/samples/hello/hello_radio_group.rb +16 -12
  112. data/samples/hello/hello_sash_form.rb +2 -0
  113. data/samples/hello/hello_spinner.rb +9 -7
  114. data/samples/hello/hello_styled_text.rb +19 -17
  115. data/samples/hello/hello_tab.rb +7 -5
  116. data/samples/hello/hello_table.rb +12 -5
  117. data/samples/hello/hello_tree.rb +485 -0
  118. data/samples/hello/hello_world.rb +2 -0
  119. metadata +21 -22
  120. data/lib/glimmer/swt/directory_dialog_proxy.rb +0 -65
  121. data/lib/glimmer/swt/file_dialog_proxy.rb +0 -66
data/lib/glimmer/ui.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Glimmer
2
+ module UI
3
+ end
4
+ GUI = UI # alias
5
+ end
@@ -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
@@ -29,16 +30,20 @@ module Glimmer
29
30
 
30
31
  class << self
31
32
  def launch(*args, &content)
32
- @launched_custom_shell = send(keyword, *args, &content) if @launched_custom_shell.nil? || @launched_custom_shell.disposed?
33
- @launched_custom_shell.swt_widget.set_data('launched', true)
34
- @launched_custom_shell.open
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
35
38
  end
36
39
  end
37
40
 
38
41
  def initialize(parent, *swt_constants, options, &content)
39
42
  super
40
- @swt_widget.set_data('custom_shell', self)
41
- @swt_widget.set_data('custom_window', self)
43
+ auto_exec do
44
+ @swt_widget.set_data('custom_shell', self)
45
+ @swt_widget.set_data('custom_window', self)
46
+ end
42
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)
43
48
  end
44
49
 
@@ -78,5 +83,6 @@ module Glimmer
78
83
  end
79
84
  end
80
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
- @swt_widget.set_data('custom_widget', self)
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
 
@@ -19,17 +19,19 @@
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-dsl-swt'
23
+
22
24
  require_relative "contact_manager/contact_manager_presenter"
23
25
 
24
26
  class ContactManager
25
- include Glimmer
27
+ include Glimmer::UI::CustomShell
26
28
 
27
- def initialize
29
+ before_body {
28
30
  @contact_manager_presenter = ContactManagerPresenter.new
29
31
  @contact_manager_presenter.list
30
- end
32
+ }
31
33
 
32
- def launch
34
+ body {
33
35
  shell {
34
36
  text "Contact Manager"
35
37
  composite {
@@ -135,8 +137,8 @@ class ContactManager
135
137
  }
136
138
  }
137
139
  }
138
- }.open
139
- end
140
+ }
141
+ }
140
142
  end
141
143
 
142
- ContactManager.new.launch
144
+ ContactManager.launch
@@ -19,6 +19,8 @@
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-dsl-swt'
23
+
22
24
  class LoginPresenter
23
25
 
24
26
  attr_accessor :user_name
@@ -45,17 +47,19 @@ class LoginPresenter
45
47
  def logged_in
46
48
  self.status == "Logged In"
47
49
  end
50
+ alias logged_in? logged_in
48
51
 
49
52
  def logged_out
50
53
  !self.logged_in
51
54
  end
55
+ alias logged_out? logged_out
52
56
 
53
- def login
57
+ def login!
54
58
  return unless valid?
55
59
  self.status = "Logged In"
56
60
  end
57
61
 
58
- def logout
62
+ def logout!
59
63
  self.user_name = ""
60
64
  self.password = ""
61
65
  self.status = "Logged Out"
@@ -64,19 +68,22 @@ class LoginPresenter
64
68
  end
65
69
 
66
70
  class Login
67
- include Glimmer
71
+ include Glimmer::UI::CustomShell
72
+
73
+ before_body {
74
+ @presenter = LoginPresenter.new
75
+ }
68
76
 
69
- def launch
70
- presenter = LoginPresenter.new
71
- @shell = shell {
77
+ body {
78
+ shell {
72
79
  text "Login"
73
80
  composite {
74
81
  grid_layout 2, false #two columns with differing widths
75
82
 
76
83
  label { text "Username:" } # goes in column 1
77
84
  @user_name_text = text { # goes in column 2
78
- text bind(presenter, :user_name)
79
- enabled bind(presenter, :logged_out)
85
+ text bind(@presenter, :user_name)
86
+ enabled bind(@presenter, :logged_out)
80
87
  on_key_pressed { |event|
81
88
  @password_text.set_focus if event.keyCode == swt(:cr)
82
89
  }
@@ -84,40 +91,39 @@ class Login
84
91
 
85
92
  label { text "Password:" }
86
93
  @password_text = text(:password, :border) {
87
- text bind(presenter, :password)
88
- enabled bind(presenter, :logged_out)
94
+ text bind(@presenter, :password)
95
+ enabled bind(@presenter, :logged_out)
89
96
  on_key_pressed { |event|
90
- presenter.login if event.keyCode == swt(:cr)
97
+ @presenter.login! if event.keyCode == swt(:cr)
91
98
  }
92
99
  }
93
100
 
94
101
  label { text "Status:" }
95
- label { text bind(presenter, :status) }
102
+ label { text bind(@presenter, :status) }
96
103
 
97
104
  button {
98
105
  text "Login"
99
- enabled bind(presenter, :logged_out)
100
- on_widget_selected { presenter.login }
106
+ enabled bind(@presenter, :logged_out)
107
+ on_widget_selected { @presenter.login! }
101
108
  on_key_pressed { |event|
102
- presenter.login if event.keyCode == swt(:cr)
109
+ @presenter.login! if event.keyCode == swt(:cr)
103
110
  }
104
111
  }
105
112
 
106
113
  button {
107
114
  text "Logout"
108
- enabled bind(presenter, :logged_in)
109
- on_widget_selected { presenter.logout }
115
+ enabled bind(@presenter, :logged_in)
116
+ on_widget_selected { @presenter.logout! }
110
117
  on_key_pressed { |event|
111
118
  if event.keyCode == swt(:cr)
112
- presenter.logout
119
+ @presenter.logout!
113
120
  @user_name_text.set_focus
114
121
  end
115
122
  }
116
123
  }
117
124
  }
118
125
  }
119
- @shell.open
120
- end
126
+ }
121
127
  end
122
128
 
123
- Login.new.launch
129
+ Login.launch
@@ -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-dsl-swt'
22
23
  require 'complex'
23
24
  require 'concurrent-ruby'
24
25
 
@@ -55,7 +56,7 @@ class Mandelbrot
55
56
  end
56
57
 
57
58
  def processor_count
58
- @processor_count ||= Concurrent.processor_count
59
+ @processor_count ||= Concurrent.physical_processor_count
59
60
  end
60
61
  end
61
62
 
@@ -170,9 +171,7 @@ class MandelbrotFractal
170
171
  the_mandelbrot = Mandelbrot.for(max_iterations: color_palette.size - 1, zoom: future_zoom, background: true)
171
172
  pixels = the_mandelbrot.calculate_points
172
173
  build_mandelbrot_image(mandelbrot_zoom: future_zoom)
173
- sync_exec {
174
- @canvas.cursor = :cross
175
- }
174
+ @canvas.cursor = :cross unless @canvas.disposed?
176
175
  future_zoom += 0.5
177
176
  }
178
177
  }
@@ -181,7 +180,7 @@ class MandelbrotFractal
181
180
  body {
182
181
  shell(:no_resize) {
183
182
  grid_layout
184
- text bind(self, :mandelbrot_shell_title, sync_exec: true)
183
+ text bind(self, :mandelbrot_shell_title)
185
184
  minimum_size mandelbrot.width + 29, mandelbrot.height + 77
186
185
  image @mandelbrot_image
187
186
 
@@ -190,7 +189,7 @@ class MandelbrotFractal
190
189
 
191
190
  minimum 0
192
191
  maximum Mandelbrot::PROGRESS_MAX
193
- selection bind(Mandelbrot, :progress, sync_exec: true)
192
+ selection bind(Mandelbrot, :progress)
194
193
  }
195
194
 
196
195
  @scrolled_composite = scrolled_composite {
@@ -222,8 +221,8 @@ class MandelbrotFractal
222
221
  on_mouse_up { |mouse_event|
223
222
  if !@drag_detected
224
223
  origin = @scrolled_composite.origin
225
- @location_x = [[origin.x + mouse_event.x - @scrolled_composite.bounds.width / 2.0, 0].max, @scrolled_composite.bounds.width].min
226
- @location_y = [[origin.y + mouse_event.y - @scrolled_composite.bounds.height / 2.0, 0].max, @scrolled_composite.bounds.height].min
224
+ @location_x = mouse_event.x
225
+ @location_y = mouse_event.y
227
226
  if mouse_event.button == 1
228
227
  zoom_in
229
228
  elsif mouse_event.button > 2
@@ -265,7 +264,7 @@ class MandelbrotFractal
265
264
  menu {
266
265
  text '&Cores'
267
266
 
268
- Concurrent.processor_count.times {|n|
267
+ Concurrent.physical_processor_count.times {|n|
269
268
  processor_number = n + 1
270
269
  menu_item(:radio) {
271
270
  text "&#{processor_number}"
@@ -279,10 +278,10 @@ class MandelbrotFractal
279
278
  accelerator COMMAND, :alt, (processor_number - 20).to_s
280
279
  end
281
280
 
282
- selection true if processor_number == Concurrent.processor_count
281
+ selection true if processor_number == Concurrent.physical_processor_count
283
282
 
284
283
  on_widget_selected {
285
- Mandelbrot.processor_count = n
284
+ Mandelbrot.processor_count = processor_number
286
285
  }
287
286
  }
288
287
  }
@@ -316,21 +315,16 @@ class MandelbrotFractal
316
315
  width = the_mandelbrot.width
317
316
  height = the_mandelbrot.height
318
317
  pixels = the_mandelbrot.points
319
- new_mandelbrot_image = image(width, height, top_level: true) # invoke as a top-level parentless keyword to avoid nesting under any widget
320
- new_mandelbrot_image_gc = new_mandelbrot_image.gc
321
- current_foreground = nil
322
318
  Mandelbrot.work_in_progress = "Consuming Points To Build Image for Zoom #{mandelbrot_zoom}x"
323
- Mandelbrot.progress = Mandelbrot::PROGRESS_MAX
319
+ Mandelbrot.progress = Mandelbrot::PROGRESS_MAX + 1
324
320
  point_index = 0
325
321
  point_count = width*height
326
- height.times { |y|
327
- width.times { |x|
328
- new_foreground = color_palette[pixels[y][x]]
329
- new_mandelbrot_image_gc.foreground = current_foreground = new_foreground unless new_foreground == current_foreground
330
- new_mandelbrot_image_gc.draw_point x, y
331
- point_index += 1
332
- Mandelbrot.progress -= 1 if (Mandelbrot::PROGRESS_MAX - (point_index.to_f / point_count.to_f)*Mandelbrot::PROGRESS_MAX) < Mandelbrot.progress
333
- }
322
+ # invoke as a top-level parentless keyword to avoid nesting under any widget
323
+ new_mandelbrot_image = image(width, height, top_level: true) { |x, y|
324
+ point_index += 1
325
+ Mandelbrot.progress -= 1 if (Mandelbrot::PROGRESS_MAX - (point_index.to_f / point_count.to_f)*Mandelbrot::PROGRESS_MAX) < Mandelbrot.progress
326
+ pixel_color_index = pixels[y][x]
327
+ color_palette[pixel_color_index]
334
328
  }
335
329
  Mandelbrot.progress = 0
336
330
  flyweight_mandelbrot_images[mandelbrot_zoom] = new_mandelbrot_image
@@ -387,8 +381,9 @@ class MandelbrotFractal
387
381
  @canvas.set_size @mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height
388
382
  @scrolled_composite.swt_widget.set_min_size(Point.new(@mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height))
389
383
  if @location_x && @location_y
384
+ # center on mouse click location
390
385
  factor = (zoom / last_zoom)
391
- @scrolled_composite.set_origin(factor*@location_x, factor*@location_y)
386
+ @scrolled_composite.set_origin(factor*@location_x - @scrolled_composite.client_area.width/2.0, factor*@location_y - @scrolled_composite.client_area.height/2.0)
392
387
  @location_x = @location_y = nil
393
388
  end
394
389
  update_mandelbrot_shell_title!
@@ -404,7 +399,7 @@ class MandelbrotFractal
404
399
  Left-click to zoom in.
405
400
  Right-click to zoom out.
406
401
  Scroll or drag to pan.
407
- Lower cores to get more responsive interaction.
402
+ Adjust cores to get a more responsive interaction.
408
403
 
409
404
  Enjoy!
410
405
  MULTI_LINE_STRING
@@ -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-dsl-swt'
22
23
  require 'fileutils'
23
24
 
24
25
  class Sample
@@ -219,7 +220,7 @@ class MetaSampleApplication
219
220
  SampleDirectory.sample_directories.each { |sample_directory|
220
221
  expand_item {
221
222
  layout_data(:fill, :fill, true, true)
222
- text " #{sample_directory.name} Samples"
223
+ text " #{sample_directory.name} Samples (#{sample_directory.samples.count})"
223
224
 
224
225
  radio_group { |radio_group_proxy|
225
226
  row_layout(:vertical) {
@@ -19,7 +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
- # Tetris App View Custom Shell (represents `tetris` keyword)
22
+ require 'glimmer-dsl-swt'
23
23
 
24
24
  require_relative 'tetris/model/game'
25
25
 
@@ -28,6 +28,7 @@ require_relative 'tetris/view/score_lane'
28
28
  require_relative 'tetris/view/high_score_dialog'
29
29
  require_relative 'tetris/view/tetris_menu_bar'
30
30
 
31
+ # Tetris App View Custom Shell (represents `tetris` keyword)
31
32
  class Tetris
32
33
  include Glimmer::UI::CustomShell
33
34
 
@@ -182,6 +183,7 @@ class Tetris
182
183
  time = Time.now
183
184
  sleep @game.delay
184
185
  break if @game.game_over? || body_root.disposed?
186
+ # ensure entire game tetromino down movement happens as one GUI update event with sync_exec (to avoid flicker/stutter)
185
187
  sync_exec {
186
188
  @game.down! unless @game.paused?
187
189
  }
@@ -19,14 +19,26 @@
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-dsl-swt'
23
+
22
24
  require_relative "tic_tac_toe/board"
23
25
 
24
26
  class TicTacToe
25
- include Glimmer
27
+ include Glimmer::UI::CustomShell
26
28
 
27
- def initialize
29
+ before_body {
28
30
  @tic_tac_toe_board = Board.new
29
- @shell = shell {
31
+ }
32
+
33
+ after_body {
34
+ observe(@tic_tac_toe_board, :game_status) { |game_status|
35
+ display_win_message if game_status == Board::WIN
36
+ display_draw_message if game_status == Board::DRAW
37
+ }
38
+ }
39
+
40
+ body {
41
+ shell {
30
42
  text "Tic-Tac-Toe"
31
43
  minimum_size 176, 200
32
44
  composite {
@@ -46,11 +58,7 @@ class TicTacToe
46
58
  }
47
59
  }
48
60
  }
49
- observe(@tic_tac_toe_board, :game_status) { |game_status|
50
- display_win_message if game_status == Board::WIN
51
- display_draw_message if game_status == Board::DRAW
52
- }
53
- end
61
+ }
54
62
 
55
63
  def display_win_message
56
64
  display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
@@ -65,12 +73,8 @@ class TicTacToe
65
73
  text 'Game Over'
66
74
  message message_text
67
75
  }.open
68
- @tic_tac_toe_board.reset
69
- end
70
-
71
- def open
72
- @shell.open
76
+ @tic_tac_toe_board.reset!
73
77
  end
74
78
  end
75
79
 
76
- TicTacToe.new.open
80
+ TicTacToe.launch