glimmer-dsl-swt 4.18.3.1 → 4.18.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -1
  3. data/README.md +739 -324
  4. data/VERSION +1 -1
  5. data/glimmer-dsl-swt.gemspec +9 -4
  6. data/lib/ext/rouge/themes/glimmer.rb +29 -0
  7. data/lib/glimmer-dsl-swt.rb +0 -1
  8. data/lib/glimmer/data_binding/table_items_binding.rb +8 -5
  9. data/lib/glimmer/data_binding/widget_binding.rb +9 -1
  10. data/lib/glimmer/dsl/swt/image_expression.rb +14 -6
  11. data/lib/glimmer/dsl/swt/layout_data_expression.rb +4 -4
  12. data/lib/glimmer/dsl/swt/layout_expression.rb +5 -3
  13. data/lib/glimmer/swt/custom/code_text.rb +171 -53
  14. data/lib/glimmer/swt/custom/drawable.rb +4 -6
  15. data/lib/glimmer/swt/custom/shape.rb +69 -12
  16. data/lib/glimmer/swt/date_time_proxy.rb +1 -3
  17. data/lib/glimmer/swt/display_proxy.rb +12 -1
  18. data/lib/glimmer/swt/font_proxy.rb +1 -0
  19. data/lib/glimmer/swt/image_proxy.rb +79 -1
  20. data/lib/glimmer/swt/shell_proxy.rb +13 -1
  21. data/lib/glimmer/swt/table_proxy.rb +43 -15
  22. data/lib/glimmer/swt/widget_proxy.rb +11 -2
  23. data/lib/glimmer/ui/custom_shell.rb +1 -0
  24. data/lib/glimmer/ui/custom_widget.rb +10 -3
  25. data/samples/elaborate/meta_sample.rb +1 -1
  26. data/samples/elaborate/meta_sample/meta_sample_logo.png +0 -0
  27. data/samples/elaborate/tetris.rb +90 -17
  28. data/samples/elaborate/tetris/model/game.rb +89 -8
  29. data/samples/elaborate/tetris/{view/game_over_dialog.rb → model/past_game.rb} +12 -41
  30. data/samples/elaborate/tetris/model/tetromino.rb +18 -5
  31. data/samples/elaborate/tetris/view/block.rb +8 -13
  32. data/samples/elaborate/tetris/view/high_score_dialog.rb +131 -0
  33. data/samples/elaborate/tetris/view/playfield.rb +1 -1
  34. data/samples/elaborate/tetris/view/score_lane.rb +6 -6
  35. data/samples/elaborate/tetris/view/tetris_menu_bar.rb +70 -3
  36. data/samples/hello/hello_canvas.rb +10 -9
  37. data/samples/hello/hello_canvas_animation.rb +5 -5
  38. data/samples/hello/hello_code_text.rb +92 -0
  39. data/samples/hello/hello_table.rb +6 -4
  40. data/samples/hello/hello_table/baseball_park.png +0 -0
  41. metadata +8 -3
@@ -93,8 +93,8 @@ class Tetris
93
93
  playfield_remaining_heights = game.playfield_remaining_heights(self)
94
94
  result = bottom_most_blocks.any? do |bottom_most_block|
95
95
  playfield_column = @column + bottom_most_block[:column_index]
96
- playfield_remaining_heights[playfield_column] &&
97
- @row + bottom_most_block[:row] >= playfield_remaining_heights[playfield_column] - 1
96
+ playfield_remaining_heights[playfield_column] &&
97
+ @row + bottom_most_block[:row_index] >= playfield_remaining_heights[playfield_column] - 1
98
98
  end
99
99
  if result && !game.hypothetical?
100
100
  @stopped = result
@@ -114,7 +114,7 @@ class Tetris
114
114
  bottom_most_block_row = row_blocks_with_row_index[1]
115
115
  {
116
116
  block: bottom_most_block,
117
- row: bottom_most_block_row,
117
+ row_index: bottom_most_block_row,
118
118
  column_index: column_index
119
119
  }
120
120
  end
@@ -182,10 +182,15 @@ class Tetris
182
182
  @blocks.size
183
183
  end
184
184
 
185
- def down!
185
+ def down!(instant: false)
186
186
  launch! if preview?
187
187
  unless stopped?
188
- new_row = @row + 1
188
+ block_count = 1
189
+ if instant
190
+ remaining_height, bottom_touching_block = remaining_height_and_bottom_touching_block
191
+ block_count = remaining_height - @row
192
+ end
193
+ new_row = @row + block_count
189
194
  update_playfield(new_row, @column)
190
195
  end
191
196
  end
@@ -245,6 +250,14 @@ class Tetris
245
250
  end
246
251
  end
247
252
 
253
+ def remaining_height_and_bottom_touching_block
254
+ playfield_remaining_heights = game.playfield_remaining_heights(self)
255
+ bottom_most_blocks.map do |bottom_most_block|
256
+ playfield_column = @column + bottom_most_block[:column_index]
257
+ [playfield_remaining_heights[playfield_column] - (bottom_most_block[:row_index] + 1), bottom_most_block]
258
+ end.min_by(&:first)
259
+ end
260
+
248
261
  def default_blocks
249
262
  case @letter
250
263
  when :I
@@ -26,36 +26,31 @@ class Tetris
26
26
 
27
27
  options :game_playfield, :block_size, :row, :column
28
28
 
29
- before_body {
30
- @bevel_constant = 20
31
- }
32
-
33
29
  body {
34
30
  canvas {
35
- layout nil
36
31
  background bind(game_playfield[row][column], :color)
37
- polygon(0, 0, block_size, 0, block_size - 4, 4, 4, 4, fill: true) {
32
+ polygon(0, 0, block_size, 0, block_size - 4, 4, 4, 4) {
38
33
  background bind(game_playfield[row][column], :color) { |color_value|
39
34
  color = color(color_value)
40
- rgb(color.red + 4*@bevel_constant, color.green + 4*@bevel_constant, color.blue + 4*@bevel_constant)
35
+ rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
41
36
  }
42
37
  }
43
- polygon(block_size, 0, block_size - 4, 4, block_size - 4, block_size - 4, block_size, block_size, fill: true) {
38
+ polygon(block_size, 0, block_size - 4, 4, block_size - 4, block_size - 4, block_size, block_size) {
44
39
  background bind(game_playfield[row][column], :color) { |color_value|
45
40
  color = color(color_value)
46
- rgb(color.red - @bevel_constant, color.green - @bevel_constant, color.blue - @bevel_constant)
41
+ rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
47
42
  }
48
43
  }
49
- polygon(block_size, block_size, 0, block_size, 4, block_size - 4, block_size - 4, block_size - 4, fill: true) {
44
+ polygon(block_size, block_size, 0, block_size, 4, block_size - 4, block_size - 4, block_size - 4) {
50
45
  background bind(game_playfield[row][column], :color) { |color_value|
51
46
  color = color(color_value)
52
- rgb(color.red - 2*@bevel_constant, color.green - 2*@bevel_constant, color.blue - 2*@bevel_constant)
47
+ rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
53
48
  }
54
49
  }
55
- polygon(0, 0, 0, block_size, 4, block_size - 4, 4, 4, fill: true) {
50
+ polygon(0, 0, 0, block_size, 4, block_size - 4, 4, 4) {
56
51
  background bind(game_playfield[row][column], :color) { |color_value|
57
52
  color = color(color_value)
58
- rgb(color.red - @bevel_constant, color.green - @bevel_constant, color.blue - @bevel_constant)
53
+ rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
59
54
  }
60
55
  }
61
56
  rectangle(0, 0, block_size, block_size) {
@@ -0,0 +1,131 @@
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 'tetris_menu_bar'
23
+
24
+ class Tetris
25
+ module View
26
+ class HighScoreDialog
27
+ include Glimmer::UI::CustomShell
28
+
29
+ options :parent_shell, :game
30
+
31
+ after_body {
32
+ @game_over_observer = observe(game, :game_over) do |game_over|
33
+ close if !game_over
34
+ end
35
+ }
36
+
37
+ body {
38
+ dialog(parent_shell) {
39
+ row_layout {
40
+ type :vertical
41
+ center true
42
+ }
43
+ text 'Tetris'
44
+
45
+ tetris_menu_bar(game: game)
46
+
47
+ label(:center) {
48
+ text bind(game, :game_over) {|game_over| game_over ? 'Game Over!' : 'High Scores'}
49
+ font name: FONT_NAME, height: FONT_TITLE_HEIGHT, style: FONT_TITLE_STYLE
50
+ }
51
+ @high_score_table = table {
52
+ layout_data {
53
+ height 100
54
+ }
55
+
56
+ table_column {
57
+ text 'Name'
58
+ }
59
+ table_column {
60
+ text 'Score'
61
+ }
62
+ table_column {
63
+ text 'Lines'
64
+ }
65
+ table_column {
66
+ text 'Level'
67
+ }
68
+
69
+ items bind(game, :high_scores, read_only_sort: true), column_properties(:name, :score, :lines, :level)
70
+ }
71
+ composite {
72
+ row_layout :horizontal
73
+
74
+ button {
75
+ text 'Clear'
76
+
77
+ on_widget_selected {
78
+ game.clear_high_scores!
79
+ }
80
+ }
81
+ @play_close_button = button {
82
+ text bind(game, :game_over) {|game_over| game_over ? 'Play Again?' : 'Close'}
83
+ focus true # initial focus
84
+
85
+ on_widget_selected {
86
+ async_exec { close }
87
+ game.paused = @game_paused
88
+ game.restart! if game.game_over?
89
+ }
90
+ }
91
+ }
92
+
93
+ on_swt_show {
94
+ @game_paused = game.paused?
95
+ game.paused = true
96
+ if game.game_over? && game.added_high_score?
97
+ game.added_high_score = false
98
+ game.save_high_scores!
99
+ @high_score_table.edit_table_item(
100
+ @high_score_table.items.first, # row item
101
+ 0, # column
102
+ write_on_cancel: true,
103
+ after_write: -> {
104
+ game.save_high_scores!
105
+ @play_close_button.set_focus
106
+ },
107
+ )
108
+ end
109
+ }
110
+
111
+ on_shell_closed {
112
+ # guard is needed because there is an observer in Tetris closing on
113
+ # game.show_high_scores change, which gets set below
114
+ unless @closing
115
+ @closing = true
116
+ @high_score_table.cancel_edit!
117
+ game.paused = @game_paused
118
+ game.show_high_scores = false
119
+ else
120
+ @closing = false
121
+ end
122
+ }
123
+
124
+ on_widget_disposed {
125
+ @game_over_observer.deregister
126
+ }
127
+ }
128
+ }
129
+ end
130
+ end
131
+ end
@@ -29,7 +29,7 @@ class Tetris
29
29
  options :game_playfield, :playfield_width, :playfield_height, :block_size
30
30
 
31
31
  body {
32
- canvas {
32
+ composite {
33
33
  grid_layout {
34
34
  num_columns playfield_width
35
35
  make_columns_equal_width true
@@ -30,8 +30,8 @@ class Tetris
30
30
  options :block_size, :game
31
31
 
32
32
  before_body {
33
- @font_name = 'Menlo'
34
- @font_height = 32
33
+ @font_name = FONT_NAME
34
+ @font_height = FONT_TITLE_HEIGHT
35
35
  }
36
36
 
37
37
  body {
@@ -46,13 +46,13 @@ class Tetris
46
46
  }
47
47
  label(:center) {
48
48
  text 'Next'
49
- font name: @font_name, height: @font_height, style: :bold
49
+ font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
50
50
  }
51
51
  playfield(game_playfield: game.preview_playfield, playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: block_size)
52
52
 
53
53
  label(:center) {
54
54
  text 'Score'
55
- font name: @font_name, height: @font_height, style: :bold
55
+ font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
56
56
  }
57
57
  label(:center) {
58
58
  text bind(game, :score)
@@ -63,7 +63,7 @@ class Tetris
63
63
 
64
64
  label(:center) {
65
65
  text 'Lines'
66
- font name: @font_name, height: @font_height, style: :bold
66
+ font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
67
67
  }
68
68
  label(:center) {
69
69
  text bind(game, :lines)
@@ -74,7 +74,7 @@ class Tetris
74
74
 
75
75
  label(:center) {
76
76
  text 'Level'
77
- font name: @font_name, height: @font_height, style: :bold
77
+ font name: @font_name, height: @font_height, style: FONT_TITLE_STYLE
78
78
  }
79
79
  label(:center) {
80
80
  text bind(game, :level)
@@ -43,13 +43,13 @@ class Tetris
43
43
  menu_item(:check) {
44
44
  text '&Pause'
45
45
  accelerator :command, :p
46
- enabled bind(game, :game_over, on_read: :!)
46
+ enabled bind(game, :game_over, on_read: :!) {|value| value && !game.show_high_scores}
47
+ enabled bind(game, :show_high_scores, on_read: :!) {|value| value && !game.game_over}
47
48
  selection bind(game, :paused)
48
49
  }
49
50
  menu_item {
50
51
  text '&Restart'
51
52
  accelerator :command, :r
52
- enabled bind(game, :game_over, on_read: :!)
53
53
 
54
54
  on_widget_selected {
55
55
  game.restart!
@@ -64,9 +64,76 @@ class Tetris
64
64
  parent_proxy.close
65
65
  }
66
66
  }
67
- }
67
+ } # end of menu
68
+
69
+ menu {
70
+ text '&View'
71
+
72
+ menu {
73
+ text '&High Scores'
74
+ menu_item(:check) {
75
+ text '&Show'
76
+ accelerator :command, :shift, :h
77
+ selection bind(game, :show_high_scores)
78
+ }
79
+ menu_item {
80
+ text '&Clear'
81
+ accelerator :command, :shift, :c
82
+
83
+ on_widget_selected {
84
+ game.clear_high_scores!
85
+ }
86
+ }
87
+ }
88
+ } # end of menu
89
+
90
+ menu {
91
+ text '&Options'
92
+ menu_item(:check) {
93
+ text '&Beeping'
94
+ accelerator :command, :b
95
+ selection bind(game, :beeping)
96
+ }
97
+ menu {
98
+ text 'Up Arrow'
99
+ menu_item(:radio) {
100
+ text '&Instant Down'
101
+ accelerator :command, :shift, :i
102
+ selection bind(game, :instant_down_on_up, computed_by: :up_arrow_action)
103
+ }
104
+ menu_item(:radio) {
105
+ text 'Rotate &Right'
106
+ accelerator :command, :shift, :r
107
+ selection bind(game, :rotate_right_on_up, computed_by: :up_arrow_action)
108
+ }
109
+ menu_item(:radio) {
110
+ text 'Rotate &Left'
111
+ accelerator :command, :shift, :l
112
+ selection bind(game, :rotate_left_on_up, computed_by: :up_arrow_action)
113
+ }
114
+ }
115
+ } # end of menu
116
+
117
+ menu {
118
+ text '&Help'
119
+
120
+ menu_item {
121
+ text '&About'
122
+ accelerator :command, :shift, :a
123
+
124
+ on_widget_selected {
125
+ parent_custom_shell&.show_about_dialog
126
+ }
127
+ }
128
+ } # end of menu
68
129
  }
69
130
  }
131
+
132
+ def parent_custom_shell
133
+ # grab custom shell widget wrapping parent widget proxy (i.e. Tetris) and invoke method on it
134
+ the_parent_custom_shell = parent_proxy&.get_data('custom_shell')
135
+ the_parent_custom_shell if the_parent_custom_shell&.visible?
136
+ end
70
137
  end
71
138
  end
72
139
  end
@@ -22,22 +22,22 @@
22
22
  include Glimmer
23
23
 
24
24
  shell {
25
- text 'Hello, Canvas!'
25
+ text 'Hello, Canvas Image Icon!'
26
26
  minimum_size 320, 400
27
27
 
28
28
  canvas {
29
29
  background :yellow
30
- rectangle(0, 0, 220, 400, fill: true) {
30
+ rectangle(0, 0, 220, 400) {
31
31
  background :red
32
32
  }
33
- rectangle(50, 20, 300, 150, 30, 50, round: true, fill: true) {
33
+ rectangle(50, 20, 300, 150, 30, 50) {
34
34
  background :magenta
35
35
  }
36
- rectangle(150, 200, 100, 70, true, gradient: true) {
36
+ rectangle(150, 200, 100, 70, true) {
37
37
  background :dark_magenta
38
38
  foreground :yellow
39
39
  }
40
- rectangle(50, 200, 30, 70, false, gradient: true) {
40
+ rectangle(50, 200, 30, 70, false) {
41
41
  background :magenta
42
42
  foreground :dark_blue
43
43
  }
@@ -49,13 +49,14 @@ shell {
49
49
  foreground :dark_magenta
50
50
  font name: 'Courier', height: 30
51
51
  }
52
- oval(110, 310, 100, 100, fill: true) {
53
- background rgb(128, 138, 248)
52
+ oval(110, 310, 100, 100) {
53
+ # patterns provide a differnet way to make gradients
54
+ background_pattern 0, 0, 105, 0, :yellow, rgb(128, 138, 248)
54
55
  }
55
- arc(210, 210, 100, 100, 30, -77, fill: true) {
56
+ arc(210, 210, 100, 100, 30, -77) {
56
57
  background :red
57
58
  }
58
- polygon(250, 210, 260, 170, 270, 210, 290, 230, fill: true) {
59
+ polygon(250, 210, 260, 170, 270, 210, 290, 230) {
59
60
  background :dark_yellow
60
61
  }
61
62
  polyline(250, 110, 260, 70, 270, 110, 290, 130, 250, 110)
@@ -35,7 +35,7 @@ shell {
35
35
  oval(0, 0, 400, 400) { # x, y, width, height
36
36
  foreground :black # sets oval background color
37
37
  }
38
- arc(0, 0, 400, 400, -1.4*index%360, 10, fill: true) { # x, y, width, height, start angle, arc angle
38
+ arc(0, 0, 400, 400, -1.4*index%360, 10) { # x, y, width, height, start angle, arc angle
39
39
  background rgb(200, 200, 50) # sets arc background color
40
40
  }
41
41
  }
@@ -51,13 +51,13 @@ shell {
51
51
  frame { |index, color| # frame block loops indefinitely (unless frame_count or cycle_count is set to an integer)
52
52
  outside_color = colors[index % 2]
53
53
  inside_color = colors[(index + 1) % 2]
54
-
54
+
55
55
  background outside_color # sets canvas background color
56
-
57
- rectangle(0, 0, 200, 200, fill: true) {
56
+
57
+ rectangle(0, 0, 200, 200) {
58
58
  background inside_color # sets rectangle background color
59
59
  }
60
- rectangle(200, 200, 200, 200, fill: true) {
60
+ rectangle(200, 200, 200, 200) {
61
61
  background inside_color # sets rectangle background color
62
62
  }
63
63
  }