glimmer-dsl-swt 4.20.13.8 → 4.20.13.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +5 -5
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_SAMPLES.md +24 -0
  6. data/docs/reference/GLIMMER_STYLE_GUIDE.md +2 -1
  7. data/glimmer-dsl-swt.gemspec +0 -0
  8. data/lib/glimmer/rake_task/scaffold.rb +14 -14
  9. data/lib/glimmer/swt/custom/code_text.rb +4 -4
  10. data/lib/glimmer/swt/custom/shape.rb +1 -1
  11. data/samples/elaborate/calculator.rb +2 -2
  12. data/samples/elaborate/contact_manager.rb +2 -2
  13. data/samples/elaborate/game_of_life.rb +111 -0
  14. data/samples/elaborate/game_of_life/model/cell.rb +72 -0
  15. data/samples/elaborate/game_of_life/model/grid.rb +97 -0
  16. data/samples/elaborate/klondike_solitaire.rb +30 -23
  17. data/samples/elaborate/klondike_solitaire/model/playing_card.rb +36 -0
  18. data/samples/elaborate/klondike_solitaire/view/empty_playing_card.rb +12 -4
  19. data/samples/elaborate/klondike_solitaire/view/foundation_pile.rb +4 -4
  20. data/samples/elaborate/klondike_solitaire/view/hidden_playing_card.rb +8 -1
  21. data/samples/elaborate/klondike_solitaire/view/playing_card.rb +3 -3
  22. data/samples/elaborate/klondike_solitaire/view/tableau.rb +4 -4
  23. data/samples/elaborate/login.rb +2 -2
  24. data/samples/elaborate/mandelbrot_fractal.rb +12 -12
  25. data/samples/elaborate/meta_sample.rb +2 -2
  26. data/samples/elaborate/metronome.rb +2 -2
  27. data/samples/elaborate/stock_ticker.rb +8 -8
  28. data/samples/elaborate/tetris.rb +4 -4
  29. data/samples/elaborate/tetris/view/bevel.rb +2 -2
  30. data/samples/elaborate/tetris/view/score_lane.rb +2 -2
  31. data/samples/elaborate/tic_tac_toe.rb +6 -6
  32. data/samples/elaborate/timer.rb +4 -4
  33. data/samples/elaborate/weather.rb +4 -4
  34. data/samples/hello/hello_button.rb +2 -2
  35. data/samples/hello/hello_c_combo.rb +2 -2
  36. data/samples/hello/hello_canvas.rb +4 -4
  37. data/samples/hello/hello_canvas_animation.rb +2 -2
  38. data/samples/hello/hello_canvas_data_binding.rb +2 -2
  39. data/samples/hello/hello_checkbox.rb +2 -2
  40. data/samples/hello/hello_checkbox_group.rb +2 -2
  41. data/samples/hello/hello_code_text.rb +2 -2
  42. data/samples/hello/hello_color_dialog.rb +2 -2
  43. data/samples/hello/hello_combo.rb +2 -2
  44. data/samples/hello/hello_computed.rb +14 -22
  45. data/samples/hello/hello_cool_bar.rb +2 -2
  46. data/samples/hello/hello_cursor.rb +2 -2
  47. data/samples/hello/hello_custom_shape.rb +2 -2
  48. data/samples/hello/hello_custom_shell.rb +2 -2
  49. data/samples/hello/hello_custom_widget.rb +4 -4
  50. data/samples/hello/hello_date_time.rb +2 -2
  51. data/samples/hello/hello_directory_dialog.rb +2 -2
  52. data/samples/hello/hello_file_dialog.rb +2 -2
  53. data/samples/hello/hello_font_dialog.rb +2 -2
  54. data/samples/hello/hello_group.rb +2 -2
  55. data/samples/hello/hello_list_multi_selection.rb +2 -2
  56. data/samples/hello/hello_list_single_selection.rb +2 -2
  57. data/samples/hello/hello_progress_bar.rb +2 -2
  58. data/samples/hello/hello_radio.rb +2 -2
  59. data/samples/hello/hello_radio_group.rb +2 -2
  60. data/samples/hello/hello_scale.rb +2 -2
  61. data/samples/hello/hello_spinner.rb +2 -2
  62. data/samples/hello/hello_table.rb +2 -2
  63. data/samples/hello/hello_text.rb +2 -2
  64. data/samples/hello/hello_tool_bar.rb +2 -2
  65. data/samples/hello/hello_tray_item.rb +2 -2
  66. data/samples/hello/hello_tree.rb +4 -4
  67. metadata +5 -2
@@ -0,0 +1,97 @@
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_relative 'cell'
23
+
24
+ class GameOfLife
25
+ module Model
26
+ class Grid
27
+ include Glimmer # included only to utilize sync_exec/async_exec
28
+ DEFAULT_ROW_COUNT = 100
29
+ DEFAULT_COLUMN_COUNT = 100
30
+
31
+ attr_reader :row_count, :column_count
32
+ attr_accessor :cell_rows, :previous_cell_rows, :playing, :speed
33
+ alias playing? playing
34
+
35
+ def initialize(row_count=DEFAULT_ROW_COUNT, column_count=DEFAULT_COLUMN_COUNT)
36
+ @row_count = row_count
37
+ @column_count = column_count
38
+ @speed = 1.0
39
+ build_cells
40
+ end
41
+
42
+ def clear!
43
+ cell_rows.each do |row|
44
+ row.each do |cell|
45
+ cell.die!
46
+ end
47
+ end
48
+ end
49
+
50
+ # steps into the next generation of cells given their current neighbors
51
+ def step!
52
+ self.previous_cell_rows = cell_rows.map do |row|
53
+ row.map do |cell|
54
+ cell.clone
55
+ end
56
+ end
57
+ cell_rows.each do |row|
58
+ row.each do |cell|
59
+ cell.step!
60
+ end
61
+ end
62
+ end
63
+
64
+ def toggle_playback!
65
+ if playing?
66
+ stop!
67
+ else
68
+ play!
69
+ end
70
+ end
71
+
72
+ def play!
73
+ self.playing = true
74
+ Thread.new do
75
+ while @playing
76
+ sync_exec { step! }
77
+ sleep(1.0/@speed)
78
+ end
79
+ end
80
+ end
81
+
82
+ def stop!
83
+ self.playing = false
84
+ end
85
+
86
+ private
87
+
88
+ def build_cells
89
+ @cell_rows = @row_count.times.map do |row_index|
90
+ @column_count.times.map do |column_index|
91
+ Cell.new(self, row_index, column_index)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -11,17 +11,11 @@ class KlondikeSolitaire
11
11
  PLAYING_CARD_WIDTH = 50
12
12
  PLAYING_CARD_HEIGHT = 80
13
13
  PLAYING_CARD_SPACING = 5
14
+ MARGIN = 15
15
+ TABLEAU_WIDTH = 2*MARGIN + 7*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING)
16
+ TABLEAU_HEIGHT = 400
14
17
 
15
- ## Add options like the following to configure CustomShell by outside consumers
16
- #
17
- # options :title, :background_color
18
- # option :width, default: 320
19
- # option :height, default: 240
20
-
21
- ## Use before_body block to pre-initialize variables to use in body
22
- #
23
- #
24
- before_body {
18
+ before_body do
25
19
  @game = Model::Game.new
26
20
  Display.app_name = 'Glimmer Klondike Solitaire'
27
21
  @display = display {
@@ -32,36 +26,49 @@ class KlondikeSolitaire
32
26
  display_about_dialog
33
27
  }
34
28
  }
35
- }
36
-
37
- ## Use after_body block to setup observers for widgets in body
38
- #
39
- # after_body {
40
- #
41
- # }
29
+ end
42
30
 
43
- ## Add widget content inside custom shell body
44
- ## Top-most widget must be a shell or another custom shell
45
- #
46
31
  body {
47
32
  shell(:no_resize) {
48
33
  row_layout(:vertical) {
49
34
  fill true
50
35
  center true
36
+ margin_width 0
37
+ margin_height 0
38
+ margin_top 15
51
39
  }
52
- minimum_size 400, 400
40
+ minimum_size TABLEAU_WIDTH, TABLEAU_HEIGHT
53
41
  text "Glimmer Klondike Solitaire"
54
42
  background :dark_green
55
43
 
56
44
  action_panel(game: @game)
57
45
  tableau(game: @game) {
58
46
  layout_data {
59
- width 380
60
- height 400
47
+ width TABLEAU_WIDTH
48
+ height TABLEAU_HEIGHT
61
49
  }
62
50
  }
63
51
 
64
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
+ }
65
72
  menu {
66
73
  text '&Help'
67
74
  menu_item {
@@ -22,6 +22,34 @@ class KlondikeSolitaire
22
22
  new(rank, suit)
23
23
  end
24
24
  end
25
+
26
+ def rank_text(rank)
27
+ case rank
28
+ when 1
29
+ 'A'
30
+ when 11
31
+ 'J'
32
+ when 12
33
+ 'Q'
34
+ when 13
35
+ 'K'
36
+ else
37
+ rank
38
+ end
39
+ end
40
+
41
+ def suit_text(suit)
42
+ case suit
43
+ when :spades
44
+ "♠"
45
+ when :hearts
46
+ "♥"
47
+ when :clubs
48
+ "♣"
49
+ when :diamonds
50
+ "♦"
51
+ end
52
+ end
25
53
  end
26
54
 
27
55
  attr_reader :rank, :suit
@@ -45,6 +73,14 @@ class KlondikeSolitaire
45
73
  def to_s
46
74
  "Playing Card #{rank}#{suit.to_s[0].upcase}"
47
75
  end
76
+
77
+ def suit_text
78
+ self.class.suit_text(suit)
79
+ end
80
+
81
+ def rank_text
82
+ self.class.rank_text(rank)
83
+ end
48
84
  end
49
85
  end
50
86
  end
@@ -1,20 +1,28 @@
1
+ require_relative '../model/playing_card'
2
+
1
3
  class KlondikeSolitaire
2
4
  module View
3
5
  class EmptyPlayingCard
4
6
  include Glimmer::UI::CustomShape
5
7
 
6
- option :suit
7
-
8
+ options :card_x, :card_y, :suit
9
+
10
+ before_body do
11
+ self.card_x ||= 0
12
+ self.card_y ||= 0
13
+ end
14
+
8
15
  body {
9
- rectangle(0, 0, 49, 79, 15, 15) {
16
+ rectangle(card_x, card_y, 49, 79, 15, 15) {
10
17
  foreground :gray
11
18
 
12
19
  if suit
13
20
  text {
14
- string suit.to_s[0].upcase
21
+ string Model::PlayingCard.suit_text(suit)
15
22
  x :default
16
23
  y :default
17
24
  is_transparent true
25
+ foreground Model::PlayingCard::BLACK_SUITS.include?(suit) ? :black : :red
18
26
  }
19
27
  end
20
28
  }
@@ -10,12 +10,12 @@ class KlondikeSolitaire
10
10
 
11
11
  attr_accessor :current_image, :model
12
12
 
13
- before_body {
13
+ before_body do
14
14
  self.current_image = image(50, 80) {empty_playing_card(suit: suit)}
15
15
  self.model = game.foundation_piles[Model::PlayingCard::SUITS.index(suit)]
16
- }
16
+ end
17
17
 
18
- after_body {
18
+ after_body do
19
19
  observe(model, 'playing_cards.last') do |last_card|
20
20
  if last_card
21
21
  body_root.content {
@@ -28,7 +28,7 @@ class KlondikeSolitaire
28
28
  }
29
29
  end
30
30
  end
31
- }
31
+ end
32
32
 
33
33
  body {
34
34
  shape(pile_x, pile_y) {
@@ -3,8 +3,15 @@ class KlondikeSolitaire
3
3
  class HiddenPlayingCard
4
4
  include Glimmer::UI::CustomShape
5
5
 
6
+ options :card_x, :card_y
7
+
8
+ before_body do
9
+ self.card_x ||= 0
10
+ self.card_y ||= 0
11
+ end
12
+
6
13
  body {
7
- rectangle(0, 0, 49, 79, 15, 15) {
14
+ rectangle(card_x, card_y, 49, 79, 15, 15) {
8
15
  background :red
9
16
 
10
17
  # border
@@ -5,10 +5,10 @@ class KlondikeSolitaire
5
5
 
6
6
  options :card_x, :card_y, :model, :parent_pile
7
7
 
8
- before_body {
8
+ before_body do
9
9
  self.card_x ||= 0
10
10
  self.card_y ||= 0
11
- }
11
+ end
12
12
 
13
13
  body {
14
14
  rectangle(card_x, card_y, 49, 79, 15, 15) {
@@ -21,7 +21,7 @@ class KlondikeSolitaire
21
21
 
22
22
  unless model.hidden?
23
23
  text {
24
- string model ? "#{model.rank} #{model.suit.to_s[0].upcase}" : ""
24
+ string model ? "#{model.rank_text}#{model.suit_text}" : ""
25
25
  x 5
26
26
  y 5
27
27
  foreground model ? model.color : :transparent
@@ -18,14 +18,14 @@ class KlondikeSolitaire
18
18
 
19
19
  # row 1
20
20
  @foundation_piles = Model::PlayingCard::SUITS.each_with_index.map do |suit, i|
21
- foundation_pile(pile_x: i*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: 0, game: game, suit: suit)
21
+ foundation_pile(pile_x: MARGIN + i*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: 0, game: game, suit: suit)
22
22
  end
23
- @dealt_pile = dealt_pile(pile_x: 5*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: 0, model: game.dealt_pile)
24
- @dealing_pile = dealing_pile(pile_x: 6*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: 0, model: game.dealing_pile)
23
+ @dealt_pile = dealt_pile(pile_x: MARGIN + 5*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: 0, model: game.dealt_pile)
24
+ @dealing_pile = dealing_pile(pile_x: MARGIN + 6*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: 0, model: game.dealing_pile)
25
25
 
26
26
  # row 2
27
27
  @column_piles = 7.times.map do |n|
28
- column_pile(pile_x: n*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: PLAYING_CARD_HEIGHT + PLAYING_CARD_SPACING, model: game.column_piles[n])
28
+ column_pile(pile_x: MARGIN + n*(PLAYING_CARD_WIDTH + PLAYING_CARD_SPACING), pile_y: PLAYING_CARD_HEIGHT + PLAYING_CARD_SPACING, model: game.column_piles[n])
29
29
  end
30
30
 
31
31
  on_mouse_up do |event|
@@ -65,9 +65,9 @@ end
65
65
  class Login
66
66
  include Glimmer::UI::CustomShell
67
67
 
68
- before_body {
68
+ before_body do
69
69
  @presenter = LoginPresenter.new
70
- }
70
+ end
71
71
 
72
72
  body {
73
73
  shell {
@@ -149,33 +149,33 @@ class MandelbrotFractal
149
149
 
150
150
  option :zoom, default: 1.0
151
151
 
152
- before_body {
152
+ before_body do
153
153
  Display.app_name = 'Mandelbrot Fractal'
154
154
  # pre-calculate mandelbrot image
155
155
  @mandelbrot_image = build_mandelbrot_image
156
- }
156
+ end
157
157
 
158
- after_body {
159
- observe(Mandelbrot, :work_in_progress) {
158
+ after_body do
159
+ observe(Mandelbrot, :work_in_progress) do
160
160
  update_mandelbrot_shell_title!
161
- }
162
- observe(Mandelbrot, :zoom) {
161
+ end
162
+ observe(Mandelbrot, :zoom) do
163
163
  update_mandelbrot_shell_title!
164
- }
164
+ end
165
165
  # pre-calculate zoomed mandelbrot images even before the user zooms in
166
166
  puts 'Starting background calculation thread...'
167
- @thread = Thread.new {
167
+ @thread = Thread.new do
168
168
  future_zoom = 1.5
169
- loop {
169
+ loop do
170
170
  puts "Creating mandelbrot for background calculation at zoom: #{future_zoom}"
171
171
  the_mandelbrot = Mandelbrot.for(max_iterations: color_palette.size - 1, zoom: future_zoom, background: true)
172
172
  pixels = the_mandelbrot.calculate_points
173
173
  build_mandelbrot_image(mandelbrot_zoom: future_zoom)
174
174
  @canvas.cursor = :cross unless @canvas.disposed?
175
175
  future_zoom += 0.5
176
- }
177
- }
178
- }
176
+ end
177
+ end
178
+ end
179
179
 
180
180
  body {
181
181
  shell(:no_resize) {
@@ -192,13 +192,13 @@ end
192
192
  class MetaSampleApplication
193
193
  include Glimmer::UI::CustomShell
194
194
 
195
- before_body {
195
+ before_body do
196
196
  Sample.ensure_user_glimmer_directory
197
197
  selected_sample_directory = SampleDirectory.sample_directories.first
198
198
  selected_sample = selected_sample_directory.samples.first
199
199
  selected_sample_directory.selected_sample_name = selected_sample.name
200
200
  Display.app_name = 'Glimmer Meta-Sample'
201
- }
201
+ end
202
202
 
203
203
  body {
204
204
  shell(:fill_screen) {
@@ -64,9 +64,9 @@ class Metronome
64
64
 
65
65
  attr_accessor :rhythm
66
66
 
67
- before_body {
67
+ before_body do
68
68
  @rhythm = Rhythm.new(4)
69
- }
69
+ end
70
70
 
71
71
  body {
72
72
  shell(:no_resize) {
@@ -65,7 +65,7 @@ class StockTicker
65
65
 
66
66
  include Glimmer::UI::CustomShell
67
67
 
68
- before_body {
68
+ before_body do
69
69
  @stocks = [
70
70
  Stock.new('DELL', 81),
71
71
  Stock.new('AAPL', 121),
@@ -126,16 +126,16 @@ class StockTicker
126
126
  end
127
127
  end
128
128
  end
129
- }
129
+ end
130
130
 
131
- after_body {
132
- @thread = Thread.new {
133
- loop {
131
+ after_body do
132
+ @thread = Thread.new do
133
+ loop do
134
134
  @stocks.each(&:tick!)
135
135
  sleep(0.01)
136
- }
137
- }
138
- }
136
+ end
137
+ end
138
+ end
139
139
 
140
140
  body {
141
141
  shell {