glimmer-dsl-swt 4.18.4.11 → 4.18.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +7 -5
  4. data/VERSION +1 -1
  5. data/bin/glimmer +3 -3
  6. data/docs/reference/GLIMMER_CONFIGURATION.md +7 -3
  7. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +121 -5
  8. data/docs/reference/GLIMMER_SAMPLES.md +17 -4
  9. data/glimmer-dsl-swt.gemspec +19 -9
  10. data/lib/ext/glimmer/config.rb +3 -7
  11. data/lib/glimmer/data_binding/list_selection_binding.rb +13 -7
  12. data/lib/glimmer/data_binding/table_items_binding.rb +22 -17
  13. data/lib/glimmer/data_binding/tree_items_binding.rb +19 -15
  14. data/lib/glimmer/data_binding/widget_binding.rb +9 -27
  15. data/lib/glimmer/dsl/swt/auto_exec_expression.rb +36 -0
  16. data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +9 -6
  17. data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +16 -14
  18. data/lib/glimmer/dsl/swt/data_binding_expression.rb +1 -2
  19. data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
  20. data/lib/glimmer/dsl/swt/image_expression.rb +8 -1
  21. data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +11 -8
  22. data/lib/glimmer/dsl/swt/pixel_expression.rb +1 -1
  23. data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +8 -5
  24. data/lib/glimmer/dsl/swt/shape_expression.rb +1 -1
  25. data/lib/glimmer/dsl/swt/widget_expression.rb +4 -3
  26. data/lib/glimmer/launcher.rb +3 -0
  27. data/lib/glimmer/rake_task/scaffold.rb +3 -0
  28. data/lib/glimmer/swt/custom/code_text.rb +11 -11
  29. data/lib/glimmer/swt/custom/drawable.rb +4 -0
  30. data/lib/glimmer/swt/custom/shape.rb +129 -20
  31. data/lib/glimmer/swt/custom/shape/arc.rb +43 -0
  32. data/lib/glimmer/swt/custom/shape/focus.rb +43 -0
  33. data/lib/glimmer/swt/custom/shape/image.rb +86 -0
  34. data/lib/glimmer/swt/custom/shape/line.rb +58 -0
  35. data/lib/glimmer/swt/custom/shape/oval.rb +43 -0
  36. data/lib/glimmer/swt/custom/shape/point.rb +52 -0
  37. data/lib/glimmer/swt/custom/shape/polygon.rb +73 -0
  38. data/lib/glimmer/swt/custom/shape/polyline.rb +73 -0
  39. data/lib/glimmer/swt/custom/shape/rectangle.rb +87 -0
  40. data/lib/glimmer/swt/custom/shape/text.rb +73 -0
  41. data/lib/glimmer/swt/date_time_proxy.rb +9 -3
  42. data/lib/glimmer/swt/directory_dialog_proxy.rb +20 -18
  43. data/lib/glimmer/swt/display_proxy.rb +62 -2
  44. data/lib/glimmer/swt/expand_item_proxy.rb +18 -12
  45. data/lib/glimmer/swt/file_dialog_proxy.rb +20 -18
  46. data/lib/glimmer/swt/font_proxy.rb +1 -1
  47. data/lib/glimmer/swt/image_proxy.rb +1 -1
  48. data/lib/glimmer/swt/layout_data_proxy.rb +21 -15
  49. data/lib/glimmer/swt/layout_proxy.rb +19 -15
  50. data/lib/glimmer/swt/menu_proxy.rb +2 -2
  51. data/lib/glimmer/swt/message_box_proxy.rb +20 -7
  52. data/lib/glimmer/swt/scrolled_composite_proxy.rb +6 -2
  53. data/lib/glimmer/swt/shell_proxy.rb +94 -80
  54. data/lib/glimmer/swt/swt_proxy.rb +16 -0
  55. data/lib/glimmer/swt/tab_item_proxy.rb +5 -3
  56. data/lib/glimmer/swt/table_proxy.rb +32 -11
  57. data/lib/glimmer/swt/tree_proxy.rb +11 -16
  58. data/lib/glimmer/swt/widget_listener_proxy.rb +6 -2
  59. data/lib/glimmer/swt/widget_proxy.rb +200 -117
  60. data/lib/glimmer/ui.rb +5 -0
  61. data/lib/glimmer/ui/custom_shell.rb +11 -5
  62. data/lib/glimmer/ui/custom_widget.rb +4 -5
  63. data/samples/elaborate/contact_manager.rb +7 -7
  64. data/samples/elaborate/login.rb +25 -21
  65. data/samples/elaborate/mandelbrot_fractal.rb +3 -5
  66. data/samples/elaborate/tetris.rb +1 -0
  67. data/samples/elaborate/tic_tac_toe.rb +16 -14
  68. data/samples/elaborate/tic_tac_toe/board.rb +5 -5
  69. data/samples/elaborate/tic_tac_toe/cell.rb +5 -5
  70. data/samples/hello/hello_button.rb +7 -7
  71. data/samples/hello/hello_canvas.rb +43 -2
  72. data/samples/hello/hello_checkbox.rb +16 -14
  73. data/samples/hello/hello_checkbox_group.rb +11 -9
  74. data/samples/hello/hello_combo.rb +14 -12
  75. data/samples/hello/hello_computed.rb +7 -7
  76. data/samples/hello/hello_cursor.rb +2 -1
  77. data/samples/hello/hello_custom_shell.rb +17 -21
  78. data/samples/hello/hello_custom_widget.rb +4 -6
  79. data/samples/hello/hello_date_time.rb +14 -12
  80. data/samples/hello/hello_directory_dialog.rb +7 -7
  81. data/samples/hello/hello_expand_bar.rb +8 -8
  82. data/samples/hello/hello_file_dialog.rb +7 -7
  83. data/samples/hello/hello_group.rb +18 -16
  84. data/samples/hello/hello_list_multi_selection.rb +13 -11
  85. data/samples/hello/hello_list_single_selection.rb +13 -11
  86. data/samples/hello/hello_progress_bar.rb +3 -7
  87. data/samples/hello/hello_radio.rb +18 -16
  88. data/samples/hello/hello_radio_group.rb +14 -12
  89. data/samples/hello/hello_spinner.rb +7 -7
  90. data/samples/hello/hello_tab.rb +5 -5
  91. data/samples/hello/hello_table.rb +10 -5
  92. data/samples/hello/hello_tree.rb +485 -0
  93. metadata +17 -18
data/lib/glimmer/ui.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Glimmer
2
+ module UI
3
+ end
4
+ GUI = UI # alias
5
+ end
@@ -19,6 +19,7 @@
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 'glimmer/ui'
22
23
  require 'glimmer/error'
23
24
 
24
25
  module Glimmer
@@ -29,16 +30,20 @@ module Glimmer
29
30
 
30
31
  class << self
31
32
  def launch(*args, &content)
32
- @launched_custom_shell = send(keyword, *args, &content) if @launched_custom_shell.nil? || @launched_custom_shell.disposed?
33
- @launched_custom_shell.swt_widget.set_data('launched', true)
34
- @launched_custom_shell.open
33
+ auto_exec do
34
+ @launched_custom_shell = send(keyword, *args, &content)
35
+ @launched_custom_shell.swt_widget.set_data('launched', true)
36
+ @launched_custom_shell.open
37
+ end
35
38
  end
36
39
  end
37
40
 
38
41
  def initialize(parent, *swt_constants, options, &content)
39
42
  super
40
- @swt_widget.set_data('custom_shell', self)
41
- @swt_widget.set_data('custom_window', self)
43
+ auto_exec do
44
+ @swt_widget.set_data('custom_shell', self)
45
+ @swt_widget.set_data('custom_window', self)
46
+ end
42
47
  raise Error, 'Invalid custom shell (window) body root! Must be a shell (window) or another custom shell (window).' unless body_root.swt_widget.is_a?(org.eclipse.swt.widgets.Shell)
43
48
  end
44
49
 
@@ -78,5 +83,6 @@ module Glimmer
78
83
  end
79
84
  end
80
85
  CustomWindow = CustomShell
86
+ Application = CustomShell
81
87
  end
82
88
  end
@@ -20,6 +20,7 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  require 'glimmer'
23
+ require 'glimmer/ui'
23
24
  require 'glimmer/error'
24
25
  require 'glimmer/swt/swt_proxy'
25
26
  require 'glimmer/swt/display_proxy'
@@ -181,7 +182,9 @@ module Glimmer
181
182
  @body_root = instance_exec(&body_block)
182
183
  raise Glimmer::Error, 'Invalid custom widget for having an empty body! Please fill body block!' if @body_root.nil?
183
184
  @swt_widget = @body_root.swt_widget
184
- @swt_widget.set_data('custom_widget', self)
185
+ auto_exec do
186
+ @swt_widget.set_data('custom_widget', self)
187
+ end
185
188
  execute_hook('after_body')
186
189
  @dispose_listener_registration = @body_root.on_widget_disposed do
187
190
  observer_registrations.each(&:deregister)
@@ -271,10 +274,6 @@ module Glimmer
271
274
  (swt_style & SWT::SWTProxy[style]) == SWT::SWTProxy[style]
272
275
  end
273
276
 
274
- def pack(*args)
275
- body_root.pack(*args)
276
- end
277
-
278
277
  # TODO see if it is worth it to eliminate duplication of async_exec/sync_exec
279
278
  # delegation to DisplayProxy, via a module
280
279
 
@@ -22,14 +22,14 @@
22
22
  require_relative "contact_manager/contact_manager_presenter"
23
23
 
24
24
  class ContactManager
25
- include Glimmer
25
+ include Glimmer::UI::CustomShell
26
26
 
27
- def initialize
27
+ before_body {
28
28
  @contact_manager_presenter = ContactManagerPresenter.new
29
29
  @contact_manager_presenter.list
30
- end
30
+ }
31
31
 
32
- def launch
32
+ body {
33
33
  shell {
34
34
  text "Contact Manager"
35
35
  composite {
@@ -135,8 +135,8 @@ class ContactManager
135
135
  }
136
136
  }
137
137
  }
138
- }.open
139
- end
138
+ }
139
+ }
140
140
  end
141
141
 
142
- ContactManager.new.launch
142
+ ContactManager.launch
@@ -45,17 +45,19 @@ class LoginPresenter
45
45
  def logged_in
46
46
  self.status == "Logged In"
47
47
  end
48
+ alias logged_in? logged_in
48
49
 
49
50
  def logged_out
50
51
  !self.logged_in
51
52
  end
53
+ alias logged_out? logged_out
52
54
 
53
- def login
55
+ def login!
54
56
  return unless valid?
55
57
  self.status = "Logged In"
56
58
  end
57
59
 
58
- def logout
60
+ def logout!
59
61
  self.user_name = ""
60
62
  self.password = ""
61
63
  self.status = "Logged Out"
@@ -64,19 +66,22 @@ class LoginPresenter
64
66
  end
65
67
 
66
68
  class Login
67
- include Glimmer
69
+ include Glimmer::UI::CustomShell
68
70
 
69
- def launch
70
- presenter = LoginPresenter.new
71
- @shell = shell {
71
+ before_body {
72
+ @presenter = LoginPresenter.new
73
+ }
74
+
75
+ body {
76
+ shell {
72
77
  text "Login"
73
78
  composite {
74
79
  grid_layout 2, false #two columns with differing widths
75
80
 
76
81
  label { text "Username:" } # goes in column 1
77
82
  @user_name_text = text { # goes in column 2
78
- text bind(presenter, :user_name)
79
- enabled bind(presenter, :logged_out)
83
+ text bind(@presenter, :user_name)
84
+ enabled bind(@presenter, :logged_out)
80
85
  on_key_pressed { |event|
81
86
  @password_text.set_focus if event.keyCode == swt(:cr)
82
87
  }
@@ -84,40 +89,39 @@ class Login
84
89
 
85
90
  label { text "Password:" }
86
91
  @password_text = text(:password, :border) {
87
- text bind(presenter, :password)
88
- enabled bind(presenter, :logged_out)
92
+ text bind(@presenter, :password)
93
+ enabled bind(@presenter, :logged_out)
89
94
  on_key_pressed { |event|
90
- presenter.login if event.keyCode == swt(:cr)
95
+ @presenter.login! if event.keyCode == swt(:cr)
91
96
  }
92
97
  }
93
98
 
94
99
  label { text "Status:" }
95
- label { text bind(presenter, :status) }
100
+ label { text bind(@presenter, :status) }
96
101
 
97
102
  button {
98
103
  text "Login"
99
- enabled bind(presenter, :logged_out)
100
- on_widget_selected { presenter.login }
104
+ enabled bind(@presenter, :logged_out)
105
+ on_widget_selected { @presenter.login! }
101
106
  on_key_pressed { |event|
102
- presenter.login if event.keyCode == swt(:cr)
107
+ @presenter.login! if event.keyCode == swt(:cr)
103
108
  }
104
109
  }
105
110
 
106
111
  button {
107
112
  text "Logout"
108
- enabled bind(presenter, :logged_in)
109
- on_widget_selected { presenter.logout }
113
+ enabled bind(@presenter, :logged_in)
114
+ on_widget_selected { @presenter.logout! }
110
115
  on_key_pressed { |event|
111
116
  if event.keyCode == swt(:cr)
112
- presenter.logout
117
+ @presenter.logout!
113
118
  @user_name_text.set_focus
114
119
  end
115
120
  }
116
121
  }
117
122
  }
118
123
  }
119
- @shell.open
120
- end
124
+ }
121
125
  end
122
126
 
123
- Login.new.launch
127
+ Login.launch
@@ -170,9 +170,7 @@ class MandelbrotFractal
170
170
  the_mandelbrot = Mandelbrot.for(max_iterations: color_palette.size - 1, zoom: future_zoom, background: true)
171
171
  pixels = the_mandelbrot.calculate_points
172
172
  build_mandelbrot_image(mandelbrot_zoom: future_zoom)
173
- sync_exec {
174
- @canvas.cursor = :cross
175
- }
173
+ @canvas.cursor = :cross unless @canvas.disposed?
176
174
  future_zoom += 0.5
177
175
  }
178
176
  }
@@ -181,7 +179,7 @@ class MandelbrotFractal
181
179
  body {
182
180
  shell(:no_resize) {
183
181
  grid_layout
184
- text bind(self, :mandelbrot_shell_title, sync_exec: true)
182
+ text bind(self, :mandelbrot_shell_title)
185
183
  minimum_size mandelbrot.width + 29, mandelbrot.height + 77
186
184
  image @mandelbrot_image
187
185
 
@@ -190,7 +188,7 @@ class MandelbrotFractal
190
188
 
191
189
  minimum 0
192
190
  maximum Mandelbrot::PROGRESS_MAX
193
- selection bind(Mandelbrot, :progress, sync_exec: true)
191
+ selection bind(Mandelbrot, :progress)
194
192
  }
195
193
 
196
194
  @scrolled_composite = scrolled_composite {
@@ -182,6 +182,7 @@ class Tetris
182
182
  time = Time.now
183
183
  sleep @game.delay
184
184
  break if @game.game_over? || body_root.disposed?
185
+ # ensure entire game tetromino down movement happens as one GUI update event with sync_exec (to avoid flicker/stutter)
185
186
  sync_exec {
186
187
  @game.down! unless @game.paused?
187
188
  }
@@ -22,11 +22,21 @@
22
22
  require_relative "tic_tac_toe/board"
23
23
 
24
24
  class TicTacToe
25
- include Glimmer
25
+ include Glimmer::UI::CustomShell
26
26
 
27
- def initialize
27
+ before_body {
28
28
  @tic_tac_toe_board = Board.new
29
- @shell = shell {
29
+ }
30
+
31
+ after_body {
32
+ observe(@tic_tac_toe_board, :game_status) { |game_status|
33
+ display_win_message if game_status == Board::WIN
34
+ display_draw_message if game_status == Board::DRAW
35
+ }
36
+ }
37
+
38
+ body {
39
+ shell {
30
40
  text "Tic-Tac-Toe"
31
41
  minimum_size 176, 200
32
42
  composite {
@@ -46,11 +56,7 @@ class TicTacToe
46
56
  }
47
57
  }
48
58
  }
49
- observe(@tic_tac_toe_board, :game_status) { |game_status|
50
- display_win_message if game_status == Board::WIN
51
- display_draw_message if game_status == Board::DRAW
52
- }
53
- end
59
+ }
54
60
 
55
61
  def display_win_message
56
62
  display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
@@ -65,12 +71,8 @@ class TicTacToe
65
71
  text 'Game Over'
66
72
  message message_text
67
73
  }.open
68
- @tic_tac_toe_board.reset
69
- end
70
-
71
- def open
72
- @shell.open
74
+ @tic_tac_toe_board.reset!
73
75
  end
74
76
  end
75
77
 
76
- TicTacToe.new.open
78
+ TicTacToe.launch
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -60,10 +60,10 @@ class TicTacToe
60
60
  win
61
61
  end
62
62
 
63
- def reset
63
+ def reset!
64
64
  (1..3).each do |row|
65
65
  (1..3).each do |column|
66
- self[row, column].reset
66
+ self[row, column].reset!
67
67
  end
68
68
  end
69
69
  @winning_sign = Cell::EMPTY
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -25,14 +25,14 @@ class TicTacToe
25
25
  attr_accessor :sign, :empty
26
26
 
27
27
  def initialize
28
- reset
28
+ reset!
29
29
  end
30
30
 
31
31
  def mark(sign)
32
32
  self.sign = sign
33
33
  end
34
34
 
35
- def reset
35
+ def reset!
36
36
  self.sign = EMPTY
37
37
  end
38
38
 
@@ -20,15 +20,15 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  class HelloButton
23
- include Glimmer
23
+ include Glimmer::UI::CustomShell
24
24
 
25
25
  attr_accessor :count
26
26
 
27
- def initialize
27
+ before_body {
28
28
  @count = 0
29
- end
29
+ }
30
30
 
31
- def launch
31
+ body {
32
32
  shell {
33
33
  text 'Hello, Button!'
34
34
 
@@ -39,8 +39,8 @@ class HelloButton
39
39
  self.count += 1
40
40
  }
41
41
  }
42
- }.open
43
- end
42
+ }
43
+ }
44
44
  end
45
45
 
46
- HelloButton.new.launch
46
+ HelloButton.launch
@@ -21,13 +21,17 @@
21
21
 
22
22
  include Glimmer
23
23
 
24
+ image_object = image(File.expand_path('../../icons/scaffold_app.png', __dir__), width: 50)
25
+
24
26
  shell {
25
- text 'Hello, Canvas Image Icon!'
27
+ text 'Hello, Canvas!'
26
28
  minimum_size 320, 400
27
29
 
28
- canvas {
30
+ @canvas = canvas {
29
31
  background :yellow
30
32
  rectangle(0, 0, 220, 400) {
33
+ transform {
34
+ }
31
35
  background :red
32
36
  }
33
37
  rectangle(50, 20, 300, 150, 30, 50) {
@@ -60,5 +64,42 @@ shell {
60
64
  background :dark_yellow
61
65
  }
62
66
  polyline(250, 110, 260, 70, 270, 110, 290, 130, 250, 110)
67
+ 3.times { |n|
68
+ line(250, 120 + n*10, 270 + n*10, 80 + n*10) {
69
+ foreground :yellow
70
+ }
71
+ }
72
+ 10.times {|n|
73
+ point(220 + n*5, 100 + n*5) {
74
+ foreground :yellow
75
+ }
76
+ }
77
+ image(image_object, 205, 55)
78
+
79
+ on_mouse_down { |mouse_event|
80
+ @drag_detected = false
81
+ @canvas.cursor = :hand
82
+ @shape_to_move = @canvas.shape_at_location(mouse_event.x, mouse_event.y)
83
+ }
84
+
85
+ on_drag_detected { |drag_detect_event|
86
+ @drag_detected = true
87
+ @drag_current_x = drag_detect_event.x
88
+ @drag_current_y = drag_detect_event.y
89
+ }
90
+
91
+ on_mouse_move { |mouse_event|
92
+ if @drag_detected
93
+ @shape_to_move&.move_by(mouse_event.x - @drag_current_x, mouse_event.y - @drag_current_y)
94
+ @drag_current_x = mouse_event.x
95
+ @drag_current_y = mouse_event.y
96
+ end
97
+ }
98
+
99
+ on_mouse_up { |mouse_event|
100
+ @canvas.cursor = :arrow
101
+ @drag_detected = false
102
+ @shape_to_move = nil
103
+ }
63
104
  }
64
105
  }.open