glimmer-dsl-swt 4.18.4.2 → 4.18.4.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +84 -5072
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_COMMAND.md +591 -0
  6. data/docs/reference/GLIMMER_CONFIGURATION.md +183 -0
  7. data/docs/reference/GLIMMER_GIRB.md +30 -0
  8. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +3276 -0
  9. data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +202 -0
  10. data/docs/reference/GLIMMER_SAMPLES.md +676 -0
  11. data/docs/reference/GLIMMER_STYLE_GUIDE.md +14 -0
  12. data/glimmer-dsl-swt.gemspec +16 -8
  13. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +3 -3
  14. data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
  15. data/lib/glimmer/dsl/swt/observe_expression.rb +8 -5
  16. data/lib/glimmer/dsl/swt/pixel_expression.rb +38 -0
  17. data/lib/glimmer/dsl/swt/timer_exec_expression.rb +35 -0
  18. data/lib/glimmer/dsl/swt/widget_expression.rb +1 -0
  19. data/lib/glimmer/swt/custom/animation.rb +9 -8
  20. data/lib/glimmer/swt/custom/code_text.rb +24 -20
  21. data/lib/glimmer/swt/custom/drawable.rb +21 -5
  22. data/lib/glimmer/swt/custom/shape.rb +62 -57
  23. data/lib/glimmer/swt/display_proxy.rb +11 -10
  24. data/lib/glimmer/swt/properties.rb +35 -10
  25. data/lib/glimmer/swt/shell_proxy.rb +1 -1
  26. data/lib/glimmer/swt/widget_proxy.rb +16 -3
  27. data/lib/glimmer/ui/custom_widget.rb +17 -0
  28. data/samples/elaborate/mandelbrot_fractal.rb +103 -0
  29. data/samples/elaborate/meta_sample.rb +1 -1
  30. data/samples/elaborate/tetris.rb +20 -21
  31. data/samples/elaborate/tetris/view/playfield.rb +1 -1
  32. data/samples/elaborate/tetris/view/tetris_menu_bar.rb +13 -11
  33. data/samples/hello/hello_canvas_transform.rb +1 -1
  34. metadata +14 -6
  35. data/samples/elaborate/meta_sample/meta_sample_logo.png +0 -0
  36. data/samples/hello/hello_canvas_transform/hello_canvas_transform_image.png +0 -0
@@ -81,15 +81,15 @@ module Glimmer
81
81
  end
82
82
 
83
83
  def async_exec(&block)
84
- @swt_display.async_exec(&block)
84
+ @swt_display.asyncExec(&block)
85
85
  end
86
86
 
87
87
  def sync_exec(&block)
88
- @swt_display.sync_exec(&block)
88
+ @swt_display.syncExec(&block)
89
89
  end
90
90
 
91
- def timer_exec(&block)
92
- @swt_display.timer_exec(&block)
91
+ def timer_exec(delay_in_millis, &block)
92
+ @swt_display.timerExec(delay_in_millis, &block)
93
93
  end
94
94
 
95
95
  def on_widget_disposed(&block)
@@ -137,12 +137,13 @@ module Glimmer
137
137
  add_swt_event_filter(constant_name, &block)
138
138
  elsif observation_request.start_with?('on_')
139
139
  event_name = observation_request.sub(/^on_/, '')
140
- if OBSERVED_MENU_ITEMS.include?(event_name)
141
- if OS.mac?
142
- system_menu = swt_display.getSystemMenu
143
- menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
144
- menu_item.addListener(SWTProxy[:Selection], &block)
145
- end
140
+ if OBSERVED_MENU_ITEMS.include?(event_name) && OS.mac?
141
+ system_menu = swt_display.getSystemMenu
142
+ menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
143
+ display_mac_event_registration = menu_item.addListener(SWTProxy[:Selection], &block)
144
+ # TODO enable this code and test on the Mac to ensure automatic cleanup of mac event registrations in custom widgets
145
+ # Glimmer::UI::CustomWidget.current_custom_widgets.last&.observer_registrations&.push(display_mac_event_registration)
146
+ display_mac_event_registration
146
147
  end
147
148
  end
148
149
  end
@@ -22,28 +22,53 @@
22
22
  module Glimmer
23
23
  module SWT
24
24
  module Properties
25
+ class << self
26
+ def ruby_attribute_setter(attribute_name)
27
+ @ruby_attribute_setters ||= {}
28
+ @ruby_attribute_setters[attribute_name] ||= "#{normalized_attribute(attribute_name)}="
29
+ end
30
+
31
+ def attribute_setter(attribute_name)
32
+ @attribute_setters ||= {}
33
+ @attribute_setters[attribute_name] ||= "set#{normalized_attribute(attribute_name).camelcase(:upper)}"
34
+ end
35
+
36
+ def attribute_getter(attribute_name)
37
+ @attribute_getters ||= {}
38
+ @attribute_getters[attribute_name] ||= "get#{normalized_attribute(attribute_name).camelcase(:upper)}"
39
+ end
40
+
41
+ def normalized_attribute(attribute_name)
42
+ @normalized_attributes ||= {}
43
+ if @normalized_attributes[attribute_name].nil?
44
+ attribute_name = attribute_name.to_s if attribute_name.is_a?(Symbol)
45
+ attribute_name = attribute_name.underscore unless attribute_name.downcase?
46
+ attribute_name = attribute_name.sub(/^get_/, '') if attribute_name.start_with?('get_')
47
+ attribute_name = attribute_name.sub(/^set_/, '') if attribute_name.start_with?('set_')
48
+ attribute_name = attribute_name.sub(/=$/, '') if attribute_name.end_with?('=')
49
+ @normalized_attributes[attribute_name] = attribute_name
50
+ end
51
+ @normalized_attributes[attribute_name]
52
+ end
53
+ alias ruby_attribute_getter normalized_attribute
54
+ end
55
+
25
56
  def ruby_attribute_setter(attribute_name)
26
- "#{normalized_attribute(attribute_name)}="
57
+ Glimmer::SWT::Properties.ruby_attribute_setter(attribute_name)
27
58
  end
28
59
 
29
60
  def attribute_setter(attribute_name)
30
- "set#{normalized_attribute(attribute_name).camelcase(:upper)}"
61
+ Glimmer::SWT::Properties.attribute_setter(attribute_name)
31
62
  end
32
63
 
33
64
  def attribute_getter(attribute_name)
34
- "get#{normalized_attribute(attribute_name).camelcase(:upper)}"
65
+ Glimmer::SWT::Properties.attribute_getter(attribute_name)
35
66
  end
36
67
 
37
68
  def normalized_attribute(attribute_name)
38
- attribute_name = attribute_name.to_s if attribute_name.is_a?(Symbol)
39
- attribute_name = attribute_name.underscore unless attribute_name.downcase?
40
- attribute_name = attribute_name.sub(/^get_/, '') if attribute_name.start_with?('get_')
41
- attribute_name = attribute_name.sub(/^set_/, '') if attribute_name.start_with?('set_')
42
- attribute_name = attribute_name.sub(/=$/, '') if attribute_name.end_with?('=')
43
- attribute_name
69
+ Glimmer::SWT::Properties.normalized_attribute(attribute_name)
44
70
  end
45
71
  alias ruby_attribute_getter normalized_attribute
46
-
47
72
  end
48
73
  end
49
74
  end
@@ -164,7 +164,7 @@ module Glimmer
164
164
  minimum_size = @swt_widget.getMinimumSize
165
165
  @swt_widget.setMinimumSize(bounds.width, bounds.height)
166
166
  listener = on_control_resized { @swt_widget.setBounds(bounds) }
167
- @swt_widget.pack
167
+ @swt_widget.layout(true, true)
168
168
  @swt_widget.removeControlListener(listener.swt_listener)
169
169
  @swt_widget.setMinimumSize(minimum_size)
170
170
  elsif OS.linux?
@@ -50,6 +50,7 @@ module Glimmer
50
50
  DEFAULT_STYLES = {
51
51
  'arrow' => [:arrow],
52
52
  'button' => [:push],
53
+ 'canvas' => [:double_buffered],
53
54
  'checkbox' => [:check],
54
55
  'check' => [:check],
55
56
  'drag_source' => [:drop_copy],
@@ -136,7 +137,8 @@ module Glimmer
136
137
  end
137
138
  end
138
139
 
139
- attr_reader :parent_proxy, :swt_widget, :drag_source_proxy, :drop_target_proxy, :drag_source_style, :drag_source_transfer, :drop_target_transfer
140
+ attr_reader :parent_proxy, :swt_widget, :drag_source_proxy, :drop_target_proxy, :drag_source_style, :drag_source_transfer, :drop_target_transfer, :finished_add_content
141
+ alias finished_add_content? finished_add_content
140
142
 
141
143
  # Initializes a new SWT Widget
142
144
  #
@@ -169,6 +171,7 @@ module Glimmer
169
171
  if respond_to?(:on_widget_disposed)
170
172
  on_widget_disposed {
171
173
  clear_shapes
174
+ deregister_shape_painting
172
175
  }
173
176
  end
174
177
  end
@@ -178,11 +181,17 @@ module Glimmer
178
181
  # No Op by default
179
182
  end
180
183
 
181
- # Subclasses may override to perform post add_content work
184
+ # Subclasses may override to perform post add_content work.
185
+ # Make sure its logic detects if it ran before since it could run multiple times
186
+ # when adding content multiple times post creation.
182
187
  def post_add_content
183
188
  # No Op by default
184
189
  end
185
-
190
+
191
+ def finish_add_content!
192
+ @finished_add_content = true
193
+ end
194
+
186
195
  def extract_args(underscored_widget_name, args)
187
196
  @arg_extractor_mapping ||= {
188
197
  'menu_item' => lambda do |args|
@@ -544,6 +553,10 @@ module Glimmer
544
553
  DisplayProxy.instance.sync_exec(&block)
545
554
  end
546
555
 
556
+ def timer_exec(delay_in_millis, &block)
557
+ DisplayProxy.instance.timer_exec(delay_in_millis, &block)
558
+ end
559
+
547
560
  def has_style?(style)
548
561
  comparison = interpret_style(style)
549
562
  (@swt_widget.style & comparison) == comparison
@@ -158,11 +158,17 @@ module Glimmer
158
158
  def after_body(&block)
159
159
  @after_body_block = block
160
160
  end
161
+
162
+ # Current custom widgets being rendered. Useful to yoke all observers evaluated during rendering of their custom widgets for automatical disposal on_widget_disposed
163
+ def current_custom_widgets
164
+ @current_custom_widgets ||= []
165
+ end
161
166
  end
162
167
 
163
168
  attr_reader :body_root, :swt_widget, :parent, :parent_proxy, :swt_style, :options
164
169
 
165
170
  def initialize(parent, *swt_constants, options, &content)
171
+ Glimmer::UI::CustomWidget.current_custom_widgets << self
166
172
  @parent_proxy = @parent = parent
167
173
  @parent_proxy = @parent&.get_data('proxy') if @parent.respond_to?(:get_data) && @parent.get_data('proxy')
168
174
  @swt_style = SWT::SWTProxy[*swt_constants]
@@ -177,6 +183,9 @@ module Glimmer
177
183
  @swt_widget = @body_root.swt_widget
178
184
  @swt_widget.set_data('custom_widget', self)
179
185
  execute_hook('after_body')
186
+ @dispose_listener_registration = @body_root.on_widget_disposed do
187
+ observer_registrations.each(&:deregister)
188
+ end
180
189
  end
181
190
 
182
191
  # Subclasses may override to perform post initialization work on an added child
@@ -184,6 +193,10 @@ module Glimmer
184
193
  # No Op by default
185
194
  end
186
195
 
196
+ def observer_registrations
197
+ @observer_registrations ||= []
198
+ end
199
+
187
200
  def can_handle_observation_request?(observation_request)
188
201
  observation_request = observation_request.to_s
189
202
  result = false
@@ -273,6 +286,10 @@ module Glimmer
273
286
  SWT::DisplayProxy.instance.sync_exec(&block)
274
287
  end
275
288
 
289
+ def timer_exec(delay_in_millis, &block)
290
+ SWT::DisplayProxy.instance.timer_exec(delay_in_millis, &block)
291
+ end
292
+
276
293
  # Returns content block if used as an attribute reader (no args)
277
294
  # Otherwise, if a block is passed, it adds it as content to this custom widget
278
295
  def content(&block)
@@ -0,0 +1,103 @@
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 implementation
27
+ # Courtesy of open-source code at:
28
+ # https://github.com/gotbadger/ruby-mandelbrot
29
+ class Mandelbrot
30
+
31
+ attr_accessor :max_iterations
32
+
33
+ def initialize(max_iterations)
34
+ @max_iterations = max_iterations
35
+ end
36
+
37
+ def calculate_all(x_array, y_array)
38
+ thread_pool = Concurrent::FixedThreadPool.new(Concurrent.processor_count)
39
+ width = x_array.size
40
+ height = y_array.size
41
+ pixel_rows_array = Concurrent::Array.new(height)
42
+ height.times do |y|
43
+ pixel_rows_array[y] ||= Concurrent::Array.new(width)
44
+ width.times do |x|
45
+ thread_pool.post do
46
+ pixel_rows_array[y][x] = calculate(x_array[x], y_array[y]).last
47
+ end
48
+ end
49
+ end
50
+ thread_pool.shutdown
51
+ thread_pool.wait_for_termination
52
+ pixel_rows_array
53
+ end
54
+
55
+ def calculate(x,y)
56
+ base_case = [Complex(x,y), 0]
57
+ Array.new(max_iterations, base_case).inject(base_case) do |prev ,base|
58
+ z, itr = prev
59
+ c, _ = base
60
+ val = z*z + c
61
+ itr += 1 unless val.abs < 2
62
+ [val, itr]
63
+ end
64
+ end
65
+ end
66
+
67
+ class MandelbrotFractal
68
+ include Glimmer::UI::CustomShell
69
+
70
+ before_body {
71
+ @colors = [[0, 0, 0]] + 40.times.map { |i| [255 - i*5, 255 - i*5, 55 + i*5] }
72
+ @colors = @colors.map {|color_data| rgb(*color_data).swt_color}
73
+ mandelbrot = Mandelbrot.new(@colors.size - 1)
74
+ @y_array = (1.0).step(-1,-0.0030).to_a
75
+ @x_array = (-2.0).step(0.5,0.0030).to_a
76
+ @height = @y_array.size
77
+ @width = @x_array.size
78
+ @pixel_rows_array = mandelbrot.calculate_all(@x_array, @y_array)
79
+ @image = Image.new(display.swt_display, @width, @height)
80
+ image_gc = org.eclipse.swt.graphics.GC.new(@image)
81
+ @height.times { |y|
82
+ @width.times { |x|
83
+ new_foreground = @colors[@pixel_rows_array[y][x]]
84
+ image_gc.foreground = @current_foreground = new_foreground unless new_foreground == @current_foreground
85
+ image_gc.draw_point x, y
86
+ }
87
+ }
88
+ }
89
+
90
+ body {
91
+ shell {
92
+ text 'Mandelbrot Fractal'
93
+ minimum_size @width, @height + 12
94
+ image @image
95
+
96
+ canvas {
97
+ image(@image, 0, 0)
98
+ }
99
+ }
100
+ }
101
+ end
102
+
103
+ MandelbrotFractal.launch
@@ -203,7 +203,7 @@ class MetaSampleApplication
203
203
  shell(:fill_screen) {
204
204
  minimum_size 1280, 768
205
205
  text 'Glimmer Meta-Sample (The Sample of Samples)'
206
- image File.expand_path('meta_sample/meta_sample_logo.png', __dir__)
206
+ image File.expand_path('../../icons/scaffold_app.png', __dir__)
207
207
 
208
208
  sash_form {
209
209
  composite {
@@ -51,11 +51,12 @@ class Tetris
51
51
  end
52
52
 
53
53
  Display.app_name = 'Glimmer Tetris'
54
+
54
55
  display {
55
- @keyboard_listener = on_swt_keydown { |key_event|
56
+ @keyboard_down_listener = on_swt_keydown { |key_event|
56
57
  case key_event.keyCode
57
58
  when swt(:arrow_down), 's'.bytes.first
58
- game.down!
59
+ game.down! if OS.mac?
59
60
  when swt(:arrow_up)
60
61
  case game.up_arrow_action
61
62
  when :instant_down
@@ -69,7 +70,7 @@ class Tetris
69
70
  game.left!
70
71
  when swt(:arrow_right), 'd'.bytes.first
71
72
  game.right!
72
- when swt(:shift), swt(:alt), swt(:ctrl)
73
+ when swt(:shift), swt(:alt)
73
74
  if key_event.keyLocation == swt(:right) # right shift key
74
75
  game.rotate!(:right)
75
76
  elsif key_event.keyLocation == swt(:left) # left shift key
@@ -77,6 +78,16 @@ class Tetris
77
78
  end
78
79
  end
79
80
  }
81
+
82
+ # invoke game.down! on keyup with Windows/Linux since they seem to group-render similar events, preventing intermediate renders (causing invisiblity while holding keys)
83
+ if !OS.mac?
84
+ @keyboard_up_listener = on_swt_keyup { |key_event|
85
+ case key_event.keyCode
86
+ when swt(:arrow_down), 's'.bytes.first
87
+ game.down!
88
+ end
89
+ }
90
+ end
80
91
 
81
92
  # if running in app mode, set the Mac app about dialog (ignored in platforms)
82
93
  @about_observer = on_about {
@@ -128,10 +139,6 @@ class Tetris
128
139
  score_lane(game: game, block_size: BLOCK_SIZE) {
129
140
  layout_data(:fill, :fill, true, true)
130
141
  }
131
-
132
- on_widget_disposed {
133
- deregister_observers
134
- }
135
142
  }
136
143
  }
137
144
 
@@ -148,26 +155,26 @@ class Tetris
148
155
  color = colored ? color(([:white] + Model::Tetromino::LETTER_COLORS.values).sample) : color(:white)
149
156
  x = column * icon_block_size
150
157
  y = row * icon_block_size
151
- rectangle(x, y, icon_block_size, icon_block_size, fill: true) {
158
+ rectangle(x, y, icon_block_size, icon_block_size) {
152
159
  background color
153
160
  }
154
- 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) {
155
162
  background rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
156
163
  }
157
- 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) {
158
165
  background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
159
166
  }
160
- 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) {
161
168
  background rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
162
169
  }
163
- 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) {
164
171
  background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
165
172
  }
166
173
  }
167
174
  }
168
175
  }
169
176
  end
170
-
177
+
171
178
  def start_moving_tetrominos_down
172
179
  Thread.new do
173
180
  @mutex.synchronize do
@@ -195,14 +202,6 @@ class Tetris
195
202
  message "Glimmer Tetris\n\nGlimmer DSL for SWT Sample\n\nCopyright (c) 2007-2021 Andy Maleh"
196
203
  }.open
197
204
  end
198
-
199
- def deregister_observers
200
- @show_high_scores_observer&.deregister
201
- @game_over_observer&.deregister
202
- @keyboard_listener&.deregister
203
- @about_observer&.deregister
204
- @quit_observer&.deregister
205
- end
206
205
  end
207
206
 
208
207
  Tetris.launch
@@ -29,7 +29,7 @@ class Tetris
29
29
  options :game_playfield, :playfield_width, :playfield_height, :block_size
30
30
 
31
31
  body {
32
- composite {
32
+ composite((:double_buffered unless OS.mac?)) {
33
33
  grid_layout {
34
34
  num_columns playfield_width
35
35
  make_columns_equal_width true
@@ -23,6 +23,8 @@ class Tetris
23
23
  module View
24
24
  class TetrisMenuBar
25
25
  include Glimmer::UI::CustomWidget
26
+
27
+ COMMAND_KEY = OS.mac? ? :command : :ctrl
26
28
 
27
29
  options :game
28
30
 
@@ -34,7 +36,7 @@ class Tetris
34
36
  menu_item {
35
37
  text '&Start'
36
38
  enabled bind(game, :game_over)
37
- accelerator :command, :s
39
+ accelerator COMMAND_KEY, :s
38
40
 
39
41
  on_widget_selected {
40
42
  game.start!
@@ -42,14 +44,14 @@ class Tetris
42
44
  }
43
45
  menu_item(:check) {
44
46
  text '&Pause'
45
- accelerator :command, :p
47
+ accelerator COMMAND_KEY, :p
46
48
  enabled bind(game, :game_over, on_read: :!) {|value| value && !game.show_high_scores}
47
49
  enabled bind(game, :show_high_scores, on_read: :!) {|value| value && !game.game_over}
48
50
  selection bind(game, :paused)
49
51
  }
50
52
  menu_item {
51
53
  text '&Restart'
52
- accelerator :command, :r
54
+ accelerator COMMAND_KEY, :r
53
55
 
54
56
  on_widget_selected {
55
57
  game.restart!
@@ -58,7 +60,7 @@ class Tetris
58
60
  menu_item(:separator)
59
61
  menu_item {
60
62
  text '&Exit'
61
- accelerator :command, :x
63
+ accelerator COMMAND_KEY, :x
62
64
 
63
65
  on_widget_selected {
64
66
  parent_proxy.close
@@ -73,12 +75,12 @@ class Tetris
73
75
  text '&High Scores'
74
76
  menu_item(:check) {
75
77
  text '&Show'
76
- accelerator :command, :shift, :h
78
+ accelerator COMMAND_KEY, :shift, :h
77
79
  selection bind(game, :show_high_scores)
78
80
  }
79
81
  menu_item {
80
82
  text '&Clear'
81
- accelerator :command, :shift, :c
83
+ accelerator COMMAND_KEY, :shift, :c
82
84
 
83
85
  on_widget_selected {
84
86
  game.clear_high_scores!
@@ -91,24 +93,24 @@ class Tetris
91
93
  text '&Options'
92
94
  menu_item(:check) {
93
95
  text '&Beeping'
94
- accelerator :command, :b
96
+ accelerator COMMAND_KEY, :b
95
97
  selection bind(game, :beeping)
96
98
  }
97
99
  menu {
98
100
  text 'Up Arrow'
99
101
  menu_item(:radio) {
100
102
  text '&Instant Down'
101
- accelerator :command, :shift, :i
103
+ accelerator COMMAND_KEY, :shift, :i
102
104
  selection bind(game, :instant_down_on_up, computed_by: :up_arrow_action)
103
105
  }
104
106
  menu_item(:radio) {
105
107
  text 'Rotate &Right'
106
- accelerator :command, :shift, :r
108
+ accelerator COMMAND_KEY, :shift, :r
107
109
  selection bind(game, :rotate_right_on_up, computed_by: :up_arrow_action)
108
110
  }
109
111
  menu_item(:radio) {
110
112
  text 'Rotate &Left'
111
- accelerator :command, :shift, :l
113
+ accelerator COMMAND_KEY, :shift, :l
112
114
  selection bind(game, :rotate_left_on_up, computed_by: :up_arrow_action)
113
115
  }
114
116
  }
@@ -119,7 +121,7 @@ class Tetris
119
121
 
120
122
  menu_item {
121
123
  text '&About'
122
- accelerator :command, :shift, :a
124
+ accelerator COMMAND_KEY, :shift, :a
123
125
 
124
126
  on_widget_selected {
125
127
  parent_custom_shell&.show_about_dialog