glimmer-dsl-swt 4.18.6.3 → 4.18.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +4 -4
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_COMMAND.md +46 -3
  6. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +26 -3
  7. data/docs/reference/GLIMMER_SAMPLES.md +56 -0
  8. data/glimmer-dsl-swt.gemspec +15 -6
  9. data/lib/glimmer/dsl/swt/animation_expression.rb +1 -1
  10. data/lib/glimmer/dsl/swt/custom_shape_expression.rb +61 -0
  11. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +1 -1
  12. data/lib/glimmer/dsl/swt/dsl.rb +1 -0
  13. data/lib/glimmer/dsl/swt/expand_item_expression.rb +4 -4
  14. data/lib/glimmer/dsl/swt/image_expression.rb +1 -1
  15. data/lib/glimmer/dsl/swt/multiply_expression.rb +1 -1
  16. data/lib/glimmer/dsl/swt/shape_expression.rb +1 -1
  17. data/lib/glimmer/dsl/swt/transform_expression.rb +1 -1
  18. data/lib/glimmer/dsl/swt/widget_expression.rb +1 -1
  19. data/lib/glimmer/rake_task.rb +36 -6
  20. data/lib/glimmer/rake_task/list.rb +8 -0
  21. data/lib/glimmer/rake_task/scaffold.rb +103 -0
  22. data/lib/glimmer/swt/custom/shape.rb +464 -181
  23. data/lib/glimmer/swt/custom/shape/image.rb +7 -9
  24. data/lib/glimmer/swt/custom/shape/path.rb +1 -5
  25. data/lib/glimmer/swt/custom/shape/polygon.rb +24 -8
  26. data/lib/glimmer/swt/custom/shape/polyline.rb +5 -0
  27. data/lib/glimmer/swt/custom/shape/rectangle.rb +10 -19
  28. data/lib/glimmer/swt/display_proxy.rb +1 -1
  29. data/lib/glimmer/swt/message_box_proxy.rb +1 -1
  30. data/lib/glimmer/swt/shell_proxy.rb +1 -1
  31. data/lib/glimmer/swt/transform_proxy.rb +1 -1
  32. data/lib/glimmer/swt/widget_proxy.rb +1 -1
  33. data/lib/glimmer/ui/custom_shape.rb +281 -0
  34. data/samples/elaborate/meta_sample.rb +5 -5
  35. data/samples/elaborate/metronome.rb +177 -0
  36. data/samples/elaborate/tetris.rb +1 -15
  37. data/samples/elaborate/tetris/model/game.rb +3 -0
  38. data/samples/elaborate/tetris/view/bevel.rb +81 -0
  39. data/samples/elaborate/tetris/view/block.rb +5 -30
  40. data/samples/hello/hello_canvas.rb +3 -0
  41. data/samples/hello/hello_canvas_animation_data_binding.rb +66 -0
  42. data/samples/hello/hello_canvas_data_binding.rb +1 -1
  43. data/samples/hello/hello_custom_shape.rb +78 -0
  44. data/samples/hello/hello_shape.rb +71 -0
  45. data/samples/hello/hello_spinner.rb +7 -2
  46. data/sounds/metronome-down.wav +0 -0
  47. data/sounds/metronome-up.wav +0 -0
  48. metadata +13 -4
@@ -215,7 +215,7 @@ class MetaSampleApplication
215
215
 
216
216
  expand_bar {
217
217
  layout_data(:fill, :fill, true, true)
218
- font height: 30
218
+ font height: 25
219
219
 
220
220
  SampleDirectory.sample_directories.each { |sample_directory|
221
221
  expand_item {
@@ -227,7 +227,7 @@ class MetaSampleApplication
227
227
  fill true
228
228
  }
229
229
  selection bind(sample_directory, :selected_sample_name)
230
- font height: 24
230
+ font height: 20
231
231
  }
232
232
  }
233
233
  }
@@ -236,12 +236,12 @@ class MetaSampleApplication
236
236
  composite {
237
237
  fill_layout
238
238
  layout_data(:fill, :center, true, false) {
239
- height_hint 120
239
+ height_hint 96
240
240
  }
241
241
 
242
242
  button {
243
243
  text 'Launch'
244
- font height: 30
244
+ font height: 25
245
245
  enabled bind(SampleDirectory, 'selected_sample.launchable')
246
246
 
247
247
  on_widget_selected {
@@ -254,7 +254,7 @@ class MetaSampleApplication
254
254
  }
255
255
  button {
256
256
  text 'Reset'
257
- font height: 30
257
+ font height: 25
258
258
  enabled bind(SampleDirectory, 'selected_sample.editable')
259
259
 
260
260
  on_widget_selected {
@@ -0,0 +1,177 @@
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 'glimmer-dsl-swt'
23
+
24
+ class Metronome
25
+ class Beat
26
+ attr_accessor :on
27
+
28
+ def off!
29
+ self.on = false
30
+ end
31
+
32
+ def on!
33
+ self.on = true
34
+ end
35
+ end
36
+
37
+ class Rhythm
38
+ attr_reader :beat_count
39
+ attr_accessor :beats, :bpm
40
+
41
+ def initialize(beat_count)
42
+ self.beat_count = beat_count
43
+ @bpm = 120
44
+ end
45
+
46
+ def beat_count=(value)
47
+ @beat_count = value
48
+ reset_beats!
49
+ end
50
+
51
+ def reset_beats!
52
+ @beats = beat_count.times.map {Beat.new}
53
+ @beats.first.on!
54
+ end
55
+ end
56
+
57
+ include Glimmer::UI::CustomShell
58
+
59
+ import 'javax.sound.sampled'
60
+
61
+ GEM_ROOT = File.expand_path(File.join('..', '..'), __dir__)
62
+ FILE_SOUND_METRONOME_UP = File.join(GEM_ROOT, 'sounds', 'metronome-up.wav')
63
+ FILE_SOUND_METRONOME_DOWN = File.join(GEM_ROOT, 'sounds', 'metronome-down.wav')
64
+
65
+ attr_accessor :rhythm
66
+
67
+ before_body {
68
+ @rhythm = Rhythm.new(4)
69
+ }
70
+
71
+ body {
72
+ shell {
73
+ row_layout(:vertical) {
74
+ center true
75
+ }
76
+ text 'Glimmer Metronome'
77
+
78
+ label {
79
+ text 'Beat Count'
80
+ font height: 30, style: :bold
81
+ }
82
+
83
+ spinner {
84
+ minimum 1
85
+ maximum 64
86
+ selection bind(self, 'rhythm.beat_count', after_write: ->(v) {restart_metronome})
87
+ font height: 30
88
+ }
89
+
90
+ label {
91
+ text 'BPM'
92
+ font height: 30, style: :bold
93
+ }
94
+
95
+ spinner {
96
+ minimum 30
97
+ maximum 1000
98
+ selection bind(self, 'rhythm.bpm')
99
+ font height: 30
100
+ }
101
+
102
+ @beat_container = beat_container
103
+
104
+ on_swt_show {
105
+ start_metronome
106
+ }
107
+
108
+ on_widget_disposed {
109
+ stop_metronome
110
+ }
111
+ }
112
+ }
113
+
114
+ def beat_container
115
+ composite {
116
+ grid_layout(@rhythm.beat_count, true)
117
+
118
+ @rhythm.beat_count.times { |n|
119
+ canvas {
120
+ layout_data {
121
+ width_hint 50
122
+ height_hint 50
123
+ }
124
+ rectangle(0, 0, :default, :default, 36, 36) {
125
+ background bind(self, "rhythm.beats[#{n}].on") {|on| on ? :red : :yellow}
126
+ }
127
+ }
128
+ }
129
+ }
130
+ end
131
+
132
+ def start_metronome
133
+ @thread ||= Thread.new {
134
+ @rhythm.beat_count.times.cycle { |n|
135
+ sleep(60.0/@rhythm.bpm.to_f)
136
+ @rhythm.beats.each(&:off!)
137
+ @rhythm.beats[n].on!
138
+ sound_file = n == 0 ? FILE_SOUND_METRONOME_UP : FILE_SOUND_METRONOME_DOWN
139
+ play_sound(sound_file)
140
+ }
141
+ }
142
+ if @beat_container.nil?
143
+ body_root.content {
144
+ @beat_container = beat_container
145
+ }
146
+ body_root.layout(true, true)
147
+ body_root.pack(true)
148
+ end
149
+ end
150
+
151
+ def stop_metronome
152
+ @thread&.kill # safe since no stored data is involved
153
+ @thread = nil
154
+ @beat_container&.dispose
155
+ @beat_container = nil
156
+ end
157
+
158
+ def restart_metronome
159
+ stop_metronome
160
+ start_metronome
161
+ end
162
+
163
+ # Play sound with the Java Sound library
164
+ def play_sound(sound_file)
165
+ begin
166
+ file_or_stream = java.io.File.new(sound_file)
167
+ audio_stream = AudioSystem.get_audio_input_stream(file_or_stream)
168
+ clip = AudioSystem.clip
169
+ clip.open(audio_stream)
170
+ clip.start
171
+ rescue => e
172
+ puts e.full_message
173
+ end
174
+ end
175
+ end
176
+
177
+ Metronome.launch
@@ -156,21 +156,7 @@ class Tetris
156
156
  color = colored ? color(([:white] + Model::Tetromino::LETTER_COLORS.values).sample) : color(:white)
157
157
  x = column * icon_block_size
158
158
  y = row * icon_block_size
159
- rectangle(x, y, icon_block_size, icon_block_size) {
160
- background color
161
- }
162
- 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) {
163
- background rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
164
- }
165
- 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) {
166
- background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
167
- }
168
- 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) {
169
- background rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
170
- }
171
- 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) {
172
- background rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
173
- }
159
+ bevel(x: x, y: y, base_color: color, size: icon_block_size)
174
160
  }
175
161
  }
176
162
  }
@@ -33,6 +33,8 @@ class Tetris
33
33
  class Game
34
34
  PLAYFIELD_WIDTH = 10
35
35
  PLAYFIELD_HEIGHT = 20
36
+ # PLAYFIELD_WIDTH = 5
37
+ # PLAYFIELD_HEIGHT = 5
36
38
  PREVIEW_PLAYFIELD_WIDTH = 4
37
39
  PREVIEW_PLAYFIELD_HEIGHT = 2
38
40
  SCORE_MULTIPLIER = {1 => 40, 2 => 100, 3 => 300, 4 => 1200}
@@ -199,6 +201,7 @@ class Tetris
199
201
 
200
202
  def delay
201
203
  [1.1 - (level.to_i * 0.1), 0.001].max
204
+ # 99999
202
205
  end
203
206
 
204
207
  def beep
@@ -0,0 +1,81 @@
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
+ # Creates a class-based custom shape representing the `bevel` keyword by convention
23
+ class Tetris
24
+ module View
25
+ class Bevel
26
+ include Glimmer::UI::CustomShape
27
+
28
+ options :base_color, :size, :bevel_pixel_size
29
+ option :x, default: 0
30
+ option :y, default: 0
31
+
32
+ before_body {
33
+ self.bevel_pixel_size = 0.16*size.to_f if bevel_pixel_size.nil?
34
+ }
35
+
36
+ body {
37
+ rectangle(x, y, size, size) {
38
+ background bind(self, :base_color)
39
+ polygon(0, 0, size, 0, size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size, bevel_pixel_size) {
40
+ background bind(self, :base_color) { |color_value|
41
+ unless color_value.nil?
42
+ color = color(color_value)
43
+ rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
44
+ end
45
+ }
46
+ }
47
+ polygon(size, 0, size - bevel_pixel_size, bevel_pixel_size, size - bevel_pixel_size, size - bevel_pixel_size, size, size) {
48
+ background bind(self, :base_color) { |color_value|
49
+ unless color_value.nil?
50
+ color = color(color_value)
51
+ rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
52
+ end
53
+ }
54
+ }
55
+ polygon(size, size, 0, size, bevel_pixel_size, size - bevel_pixel_size, size - bevel_pixel_size, size - bevel_pixel_size) {
56
+ background bind(self, :base_color) { |color_value|
57
+ unless color_value.nil?
58
+ color = color(color_value)
59
+ rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
60
+ end
61
+ }
62
+ }
63
+ polygon(0, 0, 0, size, bevel_pixel_size, size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size) {
64
+ background bind(self, :base_color) { |color_value|
65
+ unless color_value.nil?
66
+ color = color(color_value)
67
+ rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
68
+ end
69
+ }
70
+ }
71
+ rectangle(0, 0, size, size) {
72
+ foreground bind(self, :base_color) { |color_value|
73
+ # use gray instead of white for the border
74
+ color_value == Model::Block::COLOR_CLEAR ? :gray : color_value
75
+ }
76
+ }
77
+ }
78
+ }
79
+ end
80
+ end
81
+ end
@@ -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_relative 'bevel'
23
+
22
24
  class Tetris
23
25
  module View
24
26
  class Block
@@ -27,36 +29,9 @@ class Tetris
27
29
  options :game_playfield, :block_size, :row, :column
28
30
 
29
31
  body {
30
- canvas {
31
- background bind(game_playfield[row][column], :color)
32
- polygon(0, 0, block_size, 0, block_size - 4, 4, 4, 4) {
33
- background bind(game_playfield[row][column], :color) { |color_value|
34
- color = color(color_value)
35
- rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
36
- }
37
- }
38
- polygon(block_size, 0, block_size - 4, 4, block_size - 4, block_size - 4, block_size, block_size) {
39
- background bind(game_playfield[row][column], :color) { |color_value|
40
- color = color(color_value)
41
- rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
42
- }
43
- }
44
- polygon(block_size, block_size, 0, block_size, 4, block_size - 4, block_size - 4, block_size - 4) {
45
- background bind(game_playfield[row][column], :color) { |color_value|
46
- color = color(color_value)
47
- rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
48
- }
49
- }
50
- polygon(0, 0, 0, block_size, 4, block_size - 4, 4, 4) {
51
- background bind(game_playfield[row][column], :color) { |color_value|
52
- color = color(color_value)
53
- rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
54
- }
55
- }
56
- rectangle(0, 0, block_size, block_size) {
57
- foreground bind(game_playfield[row][column], :color) { |color_value|
58
- color_value == Model::Block::COLOR_CLEAR ? :gray : color_value
59
- }
32
+ canvas { |canvas_proxy|
33
+ bevel(size: block_size) {
34
+ base_color bind(game_playfield[row][column], :color)
60
35
  }
61
36
  }
62
37
  }
@@ -53,6 +53,9 @@ class HelloCanvas
53
53
  }
54
54
  rectangle(50, 20, 300, 150, 30, 50) {
55
55
  background :magenta
56
+ rectangle(:default, :default, :max, :max, 30, 50) {
57
+ foreground :yellow
58
+ }
56
59
  rectangle([:default, -70], :default, :default, [:default, 1]) {
57
60
  foreground :cyan
58
61
  text {
@@ -0,0 +1,66 @@
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 'glimmer-dsl-swt'
23
+ require 'bigdecimal'
24
+
25
+ class HelloAnimationDataBinding
26
+ include Glimmer::UI::CustomShell
27
+
28
+ attr_accessor :delay_time
29
+
30
+ before_body {
31
+ @delay_time = 0.050
32
+ }
33
+
34
+ body {
35
+ shell {
36
+ text 'Hello, Canvas Animation Data Binding!'
37
+ minimum_size 320, 320
38
+
39
+ canvas {
40
+ grid_layout
41
+
42
+ spinner {
43
+ layout_data(:center, :center, true, true) {
44
+ minimum_width 75
45
+ }
46
+ digits 3
47
+ minimum 1
48
+ maximum 100
49
+ selection bind(self, :delay_time, on_read: ->(v) {(BigDecimal(v.to_s)*1000).to_f}, on_write: ->(v) {(BigDecimal(v.to_s)/1000).to_f})
50
+ }
51
+ animation {
52
+ every bind(self, :delay_time)
53
+
54
+ frame { |index|
55
+ background rgb(index%100, index%100 + 100, index%55 + 200)
56
+ oval(index*3%300, index*3%300, 20, 20) {
57
+ background :yellow
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ end
65
+
66
+ HelloAnimationDataBinding.launch