glimmer-dsl-swt 4.21.2.4 → 4.22.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +208 -167
  3. data/README.md +18 -11
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_COMMAND.md +2 -2
  6. data/docs/reference/GLIMMER_CONFIGURATION.md +14 -3
  7. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +277 -112
  8. data/docs/reference/GLIMMER_SAMPLES.md +26 -0
  9. data/glimmer-dsl-swt.gemspec +0 -0
  10. data/lib/ext/glimmer/config.rb +41 -24
  11. data/lib/glimmer/data_binding/observable_widget.rb +6 -6
  12. data/lib/glimmer/data_binding/widget_binding.rb +4 -3
  13. data/lib/glimmer/dsl/swt/observe_expression.rb +2 -1
  14. data/lib/glimmer/dsl/swt/sync_call_expression.rb +38 -0
  15. data/lib/glimmer/dsl/swt/transform_expression.rb +1 -1
  16. data/lib/glimmer/launcher.rb +15 -14
  17. data/lib/glimmer/rake_task/package.rb +5 -3
  18. data/lib/glimmer/rake_task/scaffold.rb +2 -14
  19. data/lib/glimmer/swt/color_proxy.rb +5 -5
  20. data/lib/glimmer/swt/custom/drawable.rb +8 -2
  21. data/lib/glimmer/swt/custom/shape/line.rb +0 -1
  22. data/lib/glimmer/swt/custom/shape/path.rb +2 -2
  23. data/lib/glimmer/swt/custom/shape/path_segment.rb +2 -2
  24. data/lib/glimmer/swt/custom/shape/point.rb +8 -1
  25. data/lib/glimmer/swt/custom/shape.rb +170 -69
  26. data/lib/glimmer/swt/display_proxy.rb +15 -10
  27. data/lib/glimmer/swt/image_proxy.rb +5 -5
  28. data/lib/glimmer/swt/message_box_proxy.rb +5 -5
  29. data/lib/glimmer/swt/shape_listener_proxy.rb +55 -0
  30. data/lib/glimmer/swt/shell_proxy.rb +1 -1
  31. data/lib/glimmer/swt/transform_proxy.rb +3 -3
  32. data/lib/glimmer/swt/tray_proxy.rb +4 -4
  33. data/lib/glimmer/swt/widget_proxy.rb +14 -10
  34. data/lib/glimmer/ui/custom_shape.rb +34 -10
  35. data/lib/glimmer/ui/custom_widget.rb +7 -10
  36. data/lib/glimmer-dsl-swt.rb +6 -2
  37. data/samples/elaborate/battleship/view/cell.rb +10 -2
  38. data/samples/elaborate/klondike_solitaire/model/column_pile.rb +0 -1
  39. data/samples/elaborate/klondike_solitaire/view/column_pile.rb +3 -16
  40. data/samples/elaborate/klondike_solitaire/view/dealing_pile.rb +1 -1
  41. data/samples/elaborate/klondike_solitaire/view/dealt_pile.rb +12 -5
  42. data/samples/elaborate/klondike_solitaire/view/empty_playing_card.rb +2 -1
  43. data/samples/elaborate/klondike_solitaire/view/foundation_pile.rb +2 -2
  44. data/samples/elaborate/klondike_solitaire/view/hidden_playing_card.rb +2 -2
  45. data/samples/elaborate/klondike_solitaire/view/klondike_solitaire_menu_bar.rb +60 -0
  46. data/samples/elaborate/klondike_solitaire/view/playing_card.rb +3 -2
  47. data/samples/elaborate/klondike_solitaire.rb +13 -55
  48. data/samples/elaborate/mandelbrot_fractal.rb +3 -1
  49. data/samples/elaborate/quarto/model/game.rb +124 -0
  50. data/samples/elaborate/quarto/model/piece/cube.rb +31 -0
  51. data/samples/elaborate/quarto/model/piece/cylinder.rb +31 -0
  52. data/samples/elaborate/quarto/model/piece.rb +70 -0
  53. data/samples/elaborate/quarto/view/available_pieces_area.rb +72 -0
  54. data/samples/elaborate/quarto/view/board.rb +65 -0
  55. data/samples/elaborate/quarto/view/cell.rb +85 -0
  56. data/samples/elaborate/quarto/view/cube.rb +73 -0
  57. data/samples/elaborate/quarto/view/cylinder.rb +72 -0
  58. data/samples/elaborate/quarto/view/message_box_panel.rb +114 -0
  59. data/samples/elaborate/quarto/view/piece.rb +56 -0
  60. data/samples/elaborate/quarto/view/selected_piece_area.rb +69 -0
  61. data/samples/elaborate/quarto.rb +190 -0
  62. data/samples/hello/hello_custom_widget.rb +23 -5
  63. data/samples/hello/hello_scrolled_composite.rb +95 -0
  64. data/samples/hello/hello_world.rb +1 -0
  65. data/vendor/swt/linux/swt.jar +0 -0
  66. data/vendor/swt/linux_aarch64/swt.jar +0 -0
  67. data/vendor/swt/mac/swt.jar +0 -0
  68. data/vendor/swt/mac_aarch64/swt.jar +0 -0
  69. data/vendor/swt/windows/swt.jar +0 -0
  70. metadata +21 -25
  71. data/bin/glimmer_runner.rb +0 -4
@@ -175,8 +175,10 @@ module Glimmer
175
175
  @keyword = underscored_widget_name.to_s
176
176
  if respond_to?(:on_widget_disposed)
177
177
  on_widget_disposed {
178
- clear_shapes
179
- deregister_shape_painting
178
+ unless shell_proxy.last_shell_closing?
179
+ clear_shapes
180
+ deregister_shape_painting
181
+ end
180
182
  }
181
183
  end
182
184
  end
@@ -199,7 +201,11 @@ module Glimmer
199
201
  end
200
202
 
201
203
  def shell_proxy
202
- @swt_widget.shell.get_data('proxy')
204
+ if @swt_widget.respond_to?(:shell)
205
+ @swt_widget.shell.get_data('proxy')
206
+ else
207
+ @parent_proxy&.shell_proxy
208
+ end
203
209
  end
204
210
 
205
211
  def extract_args(underscored_widget_name, args)
@@ -572,11 +578,9 @@ module Glimmer
572
578
  flyweight_swt_widget_classes[underscored_widget_name] = swt_widget_class
573
579
  rescue SyntaxError, NameError => e
574
580
  Glimmer::Config.logger.debug {e.full_message}
575
- # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
576
581
  nil
577
582
  rescue => e
578
583
  Glimmer::Config.logger.debug {e.full_message}
579
- # Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
580
584
  nil
581
585
  end
582
586
  end
@@ -772,20 +776,20 @@ module Glimmer
772
776
  end
773
777
  end
774
778
 
775
- def method_missing(method, *args, &block)
779
+ def method_missing(method_name, *args, &block)
776
780
  # TODO push most of this logic down to Properties (and perhaps create Listeners module as well)
777
- if can_handle_observation_request?(method)
778
- handle_observation_request(method, &block)
781
+ if block && can_handle_observation_request?(method_name)
782
+ handle_observation_request(method_name, &block)
779
783
  else
780
784
  super
781
785
  end
782
786
  end
783
787
 
784
- def respond_to?(method, *args, &block)
788
+ def respond_to?(method_name, *args, &block)
785
789
  result = super
786
790
  return true if result
787
791
  auto_exec do
788
- can_handle_observation_request?(method)
792
+ can_handle_observation_request?(method_name)
789
793
  end
790
794
  end
791
795
 
@@ -158,17 +158,12 @@ module Glimmer
158
158
  def after_body(&block)
159
159
  @after_body_block = block
160
160
  end
161
-
162
- # Current custom shapes being rendered. Useful to yoke all observers evaluated during rendering of their custom shapes for automatical disposal on_shape_disposed
163
- def current_custom_shapes
164
- @current_custom_shapes ||= []
165
- end
166
161
  end
167
162
 
168
163
  attr_reader :body_root, :args, :parent, :parent_proxy, :options
169
164
 
170
165
  def initialize(parent, *args, options, &content)
171
- Glimmer::UI::CustomShape.current_custom_shapes << self
166
+ SWT::DisplayProxy.current_custom_widgets_and_shapes << self
172
167
  @parent_proxy = @parent = parent
173
168
  @parent_proxy = @parent&.get_data('proxy') if @parent.respond_to?(:get_data) && @parent.get_data('proxy')
174
169
  @args = args
@@ -183,13 +178,26 @@ module Glimmer
183
178
  auto_exec do # TODO is this necessary given shape is a lightweight construct (not SWT widget) ?
184
179
  @body_root.set_data('custom_shape', self)
185
180
  end
181
+ auto_exec do
182
+ @dispose_listener_registration = @body_root.on_shape_disposed do
183
+ unless @body_root.shell_proxy.last_shell_closing?
184
+ observer_registrations.compact.each(&:deregister)
185
+ observer_registrations.clear
186
+ end
187
+ end
188
+ end
186
189
  execute_hook('after_body')
190
+ post_add_content if content.nil?
187
191
  end
188
192
 
189
193
  # Subclasses may override to perform post initialization work on an added child
190
194
  def post_initialize_child(child)
191
195
  # No Op by default
192
196
  end
197
+
198
+ def post_add_content
199
+ SWT::DisplayProxy.current_custom_widgets_and_shapes.delete(self)
200
+ end
193
201
 
194
202
  def observer_registrations
195
203
  @observer_registrations ||= []
@@ -276,17 +284,33 @@ module Glimmer
276
284
  end
277
285
  alias getData get_data # for compatibility with SWT APIs
278
286
  alias data get_data # for compatibility with SWT APIs
287
+
288
+ def dispose(dispose_images: true, dispose_patterns: true, redraw: true)
289
+ body_root.dispose(dispose_images: dispose_images, dispose_patterns: dispose_patterns, redraw: redraw)
290
+ # @dispose_listener_registration.deregister # TODO enable once returning a true listener object or observer proc registration
291
+ end
292
+
293
+ def disposed
294
+ body_root.disposed
295
+ end
296
+ alias disposed? disposed
297
+ alias is_disposed disposed
279
298
 
280
- def method_missing(method, *args, &block)
299
+ def method_missing(method_name, *args, &block)
281
300
  # TODO Consider supporting a glimmer error silencing option for methods defined here
282
301
  # but fail the glimmer DSL for the right reason to avoid seeing noise in the log output
283
- body_root.send(method, *args, &block)
302
+ if block && can_handle_observation_request?(method_name)
303
+ handle_observation_request(method_name, &block)
304
+ else
305
+ body_root.send(method_name, *args, &block)
306
+ end
284
307
  end
285
308
 
286
309
  alias local_respond_to? respond_to?
287
- def respond_to?(method, *args, &block)
310
+ def respond_to?(method_name, *args, &block)
288
311
  super or
289
- body_root.respond_to?(method, *args, &block)
312
+ can_handle_observation_request?(method_name) or
313
+ body_root.respond_to?(method_name, *args, &block)
290
314
  end
291
315
 
292
316
  private
@@ -159,17 +159,12 @@ module Glimmer
159
159
  def after_body(&block)
160
160
  @after_body_block = block
161
161
  end
162
-
163
- # Current custom widgets being rendered. Useful to yoke all observers evaluated during rendering of their custom widgets for automatical disposal on_widget_disposed
164
- def current_custom_widgets
165
- @current_custom_widgets ||= []
166
- end
167
162
  end
168
163
 
169
164
  attr_reader :body_root, :swt_widget, :parent, :parent_proxy, :swt_style, :options
170
165
 
171
166
  def initialize(parent, *swt_constants, options, &content)
172
- Glimmer::UI::CustomWidget.current_custom_widgets << self
167
+ SWT::DisplayProxy.current_custom_widgets_and_shapes << self
173
168
  @parent_proxy = @parent = parent
174
169
  @parent_proxy = @parent&.get_data('proxy') if @parent.respond_to?(:get_data) && @parent.get_data('proxy')
175
170
  @swt_style = SWT::SWTProxy[*swt_constants]
@@ -188,8 +183,10 @@ module Glimmer
188
183
  auto_exec { execute_hook('after_body') }
189
184
  auto_exec do
190
185
  @dispose_listener_registration = @body_root.on_widget_disposed do
191
- observer_registrations.compact.each(&:deregister)
192
- observer_registrations.clear
186
+ unless @body_root.shell_proxy.last_shell_closing?
187
+ observer_registrations.compact.each(&:deregister)
188
+ observer_registrations.clear
189
+ end
193
190
  end
194
191
  end
195
192
  post_add_content if content.nil?
@@ -201,7 +198,7 @@ module Glimmer
201
198
  end
202
199
 
203
200
  def post_add_content
204
- Glimmer::UI::CustomWidget.current_custom_widgets.delete(self)
201
+ SWT::DisplayProxy.current_custom_widgets_and_shapes.delete(self)
205
202
  end
206
203
 
207
204
  def observer_registrations
@@ -310,7 +307,7 @@ module Glimmer
310
307
  def method_missing(method, *args, &block)
311
308
  # TODO Consider supporting a glimmer error silencing option for methods defined here
312
309
  # but fail the glimmer DSL for the right reason to avoid seeing noise in the log output
313
- if can_handle_observation_request?(method)
310
+ if block && can_handle_observation_request?(method)
314
311
  handle_observation_request(method, &block)
315
312
  else
316
313
  body_root.send(method, *args, &block)
@@ -30,9 +30,13 @@ if !['', 'false'].include?(ENV['GLIMMER_BUNDLER_SETUP'].to_s.strip.downcase)
30
30
  end
31
31
  require 'java'
32
32
  require 'puts_debuggerer' if ("#{ENV['pd']}#{ENV['PD']}").to_s.downcase.include?('true')
33
- require 'concurrent-ruby' # ensures glimmer relies on Concurrent data-structure classes (e.g. Concurrent::Array)
33
+
34
+ # concurrent-ruby gem ensures glimmer relies on Concurrent data-structure classes
35
+ require 'concurrent/array'
36
+ require 'concurrent/hash'
37
+ require 'concurrent/set'
34
38
  require 'glimmer'
35
- require 'logging'
39
+
36
40
  require 'nested_inherited_jruby_include_package'
37
41
  require 'super_module'
38
42
  require 'date'
@@ -54,10 +54,18 @@ class Battleship
54
54
 
55
55
  rectangle(0, 0, [:max, -1], [:max, -1])
56
56
  oval(:default, :default, 10, 10) {
57
- foreground <= [model, :hit, on_read: ->(h) {h == nil ? COLOR_EMPTY : (h ? COLOR_HIT : COLOR_NO_HIT)}]
57
+ if model.nil?
58
+ foreground COLOR_EMPTY
59
+ else
60
+ foreground <= [model, :hit, on_read: ->(h) {h == nil ? COLOR_EMPTY : (h ? COLOR_HIT : COLOR_NO_HIT)}]
61
+ end
58
62
  }
59
63
  oval(:default, :default, 5, 5) {
60
- background <= [model, :hit, on_read: ->(h) {h == nil ? COLOR_EMPTY : (h ? COLOR_HIT : COLOR_NO_HIT)}]
64
+ if model.nil?
65
+ background COLOR_EMPTY
66
+ else
67
+ background <= [model, :hit, on_read: ->(h) {h == nil ? COLOR_EMPTY : (h ? COLOR_HIT : COLOR_NO_HIT)}]
68
+ end
61
69
  }
62
70
 
63
71
  on_mouse_move do |event|
@@ -13,7 +13,6 @@ class KlondikeSolitaire
13
13
  def reset!
14
14
  playing_cards.clear
15
15
  populate!(count.times.map { @game.deck.pop })
16
- notify_observers(:playing_cards)
17
16
  end
18
17
 
19
18
  # this method does not validate
@@ -7,16 +7,6 @@ class KlondikeSolitaire
7
7
  class ColumnPile
8
8
  include Glimmer::UI::CustomShape
9
9
 
10
- IMAGE_EMPTY = image(50, 80) {
11
- rectangle(0, 0, 50, 80) {
12
- background :dark_green
13
-
14
- rectangle(0, 0, 49, 79, 15, 15) {
15
- foreground :gray
16
- }
17
- }
18
- }
19
-
20
10
  options :pile_x, :pile_y, :model
21
11
 
22
12
  after_body {
@@ -36,13 +26,10 @@ class KlondikeSolitaire
36
26
  card_parent_pile = card_shape.parent_pile
37
27
  card_source_model = card_parent_pile.model
38
28
  cards = card_source_model.remove!(card)
39
- if cards.is_a?(Array) # if it is a column pile
40
- cards[1..-1].each do |card|
41
- model.add!(card)
42
- end
43
- end
29
+ cards[1..-1].each { |card| model.add!(card) } if cards.is_a?(Array) # if it is a column pile
44
30
  drop_event.dragged_shape.dispose
45
31
  rescue => e
32
+ Glimmer::Config.logger.debug { "Error encountered on drop of a card to a column pile: #{e.full_message}" }
46
33
  drop_event.doit = false
47
34
  end
48
35
  end
@@ -50,7 +37,7 @@ class KlondikeSolitaire
50
37
  }
51
38
 
52
39
  def build_column_pile(playing_cards)
53
- body_root.shapes.to_a.each(&:dispose)
40
+ body_root.shapes.to_a.dup.each { |shape| shape.dispose(redraw: false) }
54
41
  current_parent = body_root
55
42
  playing_cards.each_with_index do |card, i|
56
43
  current_parent.content {
@@ -12,7 +12,7 @@ class KlondikeSolitaire
12
12
 
13
13
  after_body {
14
14
  observe(model, 'playing_cards.empty?') do |empty_value|
15
- body_root.shapes.to_a.each(&:dispose)
15
+ body_root.shapes.to_a.each { |shape| shape.dispose(redraw: false) }
16
16
  if empty_value
17
17
  body_root.content {
18
18
  empty_playing_card
@@ -13,16 +13,23 @@ class KlondikeSolitaire
13
13
  after_body do
14
14
  observe(model, 'playing_cards.empty?') do |empty_value|
15
15
  if empty_value
16
- body_root.shapes.to_a.dup.each(&:dispose)
16
+ body_root.shapes.to_a.dup.each { |shape| shape.dispose(redraw: false) }
17
17
  body_root.content {
18
18
  empty_playing_card
19
19
  }
20
20
  else
21
- body_root.content {
22
- playing_card(model: model.playing_cards.last, parent_pile: self) {
23
- drag_source true
21
+ body_root.shapes.each { |shape| shape.drag_source = false }
22
+ before_last_shape = body_root.shapes[-2] && body_root.shapes[-2].get_data('custom_shape').respond_to?(:model) && body_root.shapes[-2].get_data('custom_shape').model
23
+ if model.playing_cards.last == before_last_shape # happens when dragging card out
24
+ body_root.shapes.last.dispose
25
+ body_root.shapes.last.drag_source = true
26
+ else
27
+ body_root.content {
28
+ playing_card(model: model.playing_cards.last, parent_pile: self) {
29
+ drag_source true
30
+ }
24
31
  }
25
- }
32
+ end
26
33
  end
27
34
  end
28
35
  end
@@ -13,12 +13,13 @@ class KlondikeSolitaire
13
13
  end
14
14
 
15
15
  body {
16
- rectangle(card_x, card_y, 49, 79, 15, 15) {
16
+ rectangle(card_x, card_y, PLAYING_CARD_WIDTH - 1, PLAYING_CARD_HEIGHT - 1, 15, 15) {
17
17
  foreground :gray
18
18
 
19
19
  if suit
20
20
  text {
21
21
  string Model::PlayingCard.suit_text(suit)
22
+ font height: 20
22
23
  x :default
23
24
  y :default
24
25
  is_transparent true
@@ -8,10 +8,9 @@ class KlondikeSolitaire
8
8
 
9
9
  options :pile_x, :pile_y, :game, :suit
10
10
 
11
- attr_accessor :current_image, :model
11
+ attr_accessor :model
12
12
 
13
13
  before_body do
14
- self.current_image = image(50, 80) {empty_playing_card(suit: suit)}
15
14
  self.model = game.foundation_piles[Model::PlayingCard::SUITS.index(suit)]
16
15
  end
17
16
 
@@ -45,6 +44,7 @@ class KlondikeSolitaire
45
44
  card_source_model.remove!(card)
46
45
  drop_event.dragged_shape.dispose
47
46
  rescue => e
47
+ Glimmer::Config.logger.debug { "Error encountered on drop of a card to a foundation pile: #{e.full_message}" }
48
48
  drop_event.doit = false
49
49
  end
50
50
  end
@@ -11,11 +11,11 @@ class KlondikeSolitaire
11
11
  end
12
12
 
13
13
  body {
14
- rectangle(card_x, card_y, 49, 79, 15, 15) {
14
+ rectangle(card_x, card_y, PLAYING_CARD_WIDTH - 1, PLAYING_CARD_HEIGHT - 1, 15, 15) {
15
15
  background :red
16
16
 
17
17
  # border
18
- rectangle(0, 0, 49, 79, 15, 15) {
18
+ rectangle(0, 0, PLAYING_CARD_WIDTH - 1, PLAYING_CARD_HEIGHT - 1, 15, 15) {
19
19
  foreground :black
20
20
  }
21
21
  }
@@ -0,0 +1,60 @@
1
+ class KlondikeSolitaire
2
+ module View
3
+ class KlondikeSolitaireMenuBar
4
+ include Glimmer::UI::CustomWidget
5
+
6
+ option :game
7
+
8
+ before_body do
9
+ @display = display {
10
+ on_about {
11
+ display_about_dialog
12
+ }
13
+ on_preferences {
14
+ display_about_dialog
15
+ }
16
+ }
17
+ end
18
+
19
+ body {
20
+ menu_bar {
21
+ menu {
22
+ text '&Game'
23
+ menu_item {
24
+ text '&Restart'
25
+ accelerator (OS.mac? ? :command : :ctrl), :r
26
+
27
+ on_widget_selected {
28
+ game.restart!
29
+ }
30
+ }
31
+ menu_item {
32
+ text 'E&xit'
33
+ accelerator :alt, :f4
34
+
35
+ on_widget_selected {
36
+ exit(0)
37
+ }
38
+ }
39
+ }
40
+ menu {
41
+ text '&Help'
42
+ menu_item {
43
+ text '&About...'
44
+ on_widget_selected {
45
+ display_about_dialog
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ def display_about_dialog
53
+ message_box(body_root) {
54
+ text 'About'
55
+ message "Glimmer Klondike Solitaire\nGlimmer DSL for SWT Elaborate Sample"
56
+ }.open
57
+ end
58
+ end
59
+ end
60
+ end
@@ -11,17 +11,18 @@ class KlondikeSolitaire
11
11
  end
12
12
 
13
13
  body {
14
- rectangle(card_x, card_y, 49, 79, 15, 15) {
14
+ rectangle(card_x, card_y, PLAYING_CARD_WIDTH - 1, PLAYING_CARD_HEIGHT - 1, 15, 15) {
15
15
  background model.hidden ? :red : :white
16
16
 
17
17
  # border
18
- rectangle(0, 0, 49, 79, 15, 15) {
18
+ rectangle(0, 0, PLAYING_CARD_WIDTH - 1, PLAYING_CARD_HEIGHT - 1, 15, 15) {
19
19
  foreground :black
20
20
  }
21
21
 
22
22
  unless model.hidden?
23
23
  text {
24
24
  string model ? "#{model.rank_text}#{model.suit_text}" : ""
25
+ font height: PLAYING_CARD_FONT_HEIGHT
25
26
  x 5
26
27
  y 5
27
28
  foreground model ? model.color : :transparent
@@ -4,35 +4,26 @@ require_relative 'klondike_solitaire/model/game'
4
4
 
5
5
  require_relative 'klondike_solitaire/view/action_panel'
6
6
  require_relative 'klondike_solitaire/view/tableau'
7
+ require_relative 'klondike_solitaire/view/klondike_solitaire_menu_bar'
7
8
 
8
9
  class KlondikeSolitaire
9
10
  include Glimmer::UI::CustomShell
10
11
 
11
12
  PLAYING_CARD_WIDTH = 50
12
- PLAYING_CARD_HEIGHT = 80
13
+ PLAYING_CARD_HEIGHT = 76
13
14
  PLAYING_CARD_SPACING = 5
15
+ PLAYING_CARD_FONT_HEIGHT = 16
14
16
  MARGIN = 15
15
17
  TABLEAU_WIDTH = 2*MARGIN + 7*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING)
16
- TABLEAU_HEIGHT = 400
18
+ TABLEAU_HEIGHT = 420
17
19
 
18
20
  before_body do
19
21
  @game = Model::Game.new
20
- Display.app_name = 'Glimmer Klondike Solitaire'
21
- @display = display {
22
- on_about {
23
- display_about_dialog
24
- }
25
- on_preferences {
26
- display_about_dialog
27
- }
28
- }
29
22
  end
30
23
 
31
24
  body {
32
25
  shell {
33
- row_layout(:vertical) {
34
- fill true
35
- center true
26
+ grid_layout {
36
27
  margin_width 0
37
28
  margin_height 0
38
29
  margin_top 15
@@ -41,53 +32,20 @@ class KlondikeSolitaire
41
32
  text "Glimmer Klondike Solitaire"
42
33
  background :dark_green
43
34
 
44
- action_panel(game: @game)
45
- tableau(game: @game) {
46
- layout_data {
47
- width TABLEAU_WIDTH
48
- height TABLEAU_HEIGHT
49
- }
35
+ klondike_solitaire_menu_bar(game: @game)
36
+
37
+ action_panel(game: @game) {
38
+ layout_data(:fill, :center, true, false)
50
39
  }
51
40
 
52
- menu_bar {
53
- menu {
54
- text '&Game'
55
- menu_item {
56
- text '&Restart'
57
- accelerator (OS.mac? ? :command : :ctrl), :r
58
-
59
- on_widget_selected {
60
- @game.restart!
61
- }
62
- }
63
- menu_item {
64
- text 'E&xit'
65
- accelerator :alt, :f4
66
-
67
- on_widget_selected {
68
- body_root.close
69
- }
70
- }
71
- }
72
- menu {
73
- text '&Help'
74
- menu_item {
75
- text '&About...'
76
- on_widget_selected {
77
- display_about_dialog
78
- }
79
- }
41
+ tableau(game: @game) {
42
+ layout_data(:fill, :fill, true, true) {
43
+ width_hint TABLEAU_WIDTH
44
+ height_hint TABLEAU_HEIGHT
80
45
  }
81
46
  }
82
47
  }
83
48
  }
84
-
85
- def display_about_dialog
86
- message_box(body_root) {
87
- text 'About'
88
- message "Glimmer Klondike Solitaire\nGlimmer DSL for SWT Elaborate Sample"
89
- }.open
90
- end
91
49
  end
92
50
 
93
51
  KlondikeSolitaire.launch
@@ -21,7 +21,9 @@
21
21
 
22
22
  require 'glimmer-dsl-swt'
23
23
  require 'complex'
24
- require 'concurrent-ruby'
24
+ require 'concurrent/executor/fixed_thread_pool'
25
+ require 'concurrent/utility/processor_counter'
26
+ require 'concurrent/array'
25
27
 
26
28
  # Mandelbrot multi-threaded implementation leveraging all processor cores.
27
29
  class Mandelbrot