glimmer-dsl-swt 4.21.1.0 → 4.21.2.2

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.
@@ -110,6 +110,7 @@ module Glimmer
110
110
 
111
111
  def deregister_shape_painting
112
112
  @paint_listener_proxy&.deregister
113
+ @resize_listener_proxy&.deregister
113
114
  end
114
115
 
115
116
  def setup_shape_painting
@@ -143,6 +144,7 @@ module Glimmer
143
144
  shape_painter.call(self) # treat self as paint event since image has its own gc and doesn't do repaints (it's a one time deal for now though could be adjusted in the future.)
144
145
  else
145
146
  @paint_listener_proxy = on_swt_paint(&shape_painter)
147
+ @resize_listener_proxy = on_swt_Resize { shapes.each(&:calculated_args_changed!) }
146
148
  end
147
149
  else
148
150
  redraw if respond_to?(:redraw) && @finished_add_content && !is_disposed
@@ -122,9 +122,11 @@ module Glimmer
122
122
  def input_stream
123
123
  if @file_path.start_with?('uri:classloader')
124
124
  @jar_file_path = @file_path
125
- file_path = @jar_file_path.sub(/^uri\:classloader\:/, '').sub('//', '') # the latter sub is needed for Mac
126
- project_name = java.lang.System.getProperty('project_name')
127
- file_input_stream = java_import("#{project_name}.Resource").last.java_class.resource_as_stream(file_path)
125
+ file_path = @jar_file_path.sub(/^uri\:classloader\:/, '').sub(/^\/+/, '')
126
+ require 'jruby'
127
+ jcl = JRuby.runtime.jruby_class_loader
128
+ resource = jcl.get_resource_as_stream(file_path)
129
+ file_input_stream = resource.to_io.to_input_stream
128
130
  else
129
131
  file_input_stream = java.io.FileInputStream.new(@file_path)
130
132
  end
@@ -151,6 +151,8 @@ module Glimmer
151
151
  def include?(swt_constant, *symbols)
152
152
  swt_constant & self[symbols] == self[symbols]
153
153
  end
154
+
155
+ # TODO support listing all symbols
154
156
  end
155
157
  end
156
158
  end
@@ -743,6 +743,13 @@ module Glimmer
743
743
 
744
744
  def handle_observation_request(observation_request, &block)
745
745
  observation_request = normalize_observation_request(observation_request)
746
+ if observation_request.start_with?('on_drag_enter')
747
+ original_block = block
748
+ block = Proc.new do |event|
749
+ event.detail = DNDProxy[:drop_copy]
750
+ original_block.call(event)
751
+ end
752
+ end
746
753
  if observation_request.start_with?('on_swt_')
747
754
  constant_name = observation_request.sub(/^on_swt_/, '')
748
755
  add_swt_event_listener(constant_name, &block)
@@ -886,6 +893,75 @@ module Glimmer
886
893
  def widget_custom_attribute_mapping
887
894
  # TODO scope per widget class type just like other mappings
888
895
  @swt_widget_custom_attribute_mapping ||= {
896
+ 'drag_source' => {
897
+ getter: {name: 'getShell', invoker: lambda { |widget, args|
898
+ @drag_source
899
+ }},
900
+ setter: {name: 'getShell', invoker: lambda { |widget, args|
901
+ @drag_source = args.first
902
+ if @drag_source
903
+ case @swt_widget
904
+ when List
905
+ on_drag_set_data do |event|
906
+ drag_widget = event.widget.control
907
+ event.data = drag_widget.selection.first
908
+ end
909
+ when Label
910
+ on_drag_set_data do |event|
911
+ drag_widget = event.widget.control
912
+ event.data = drag_widget.text
913
+ end
914
+ when Text
915
+ on_drag_set_data do |event|
916
+ drag_widget = event.widget.control
917
+ event.data = drag_widget.selection_text
918
+ end
919
+ when Spinner
920
+ on_drag_set_data do |event|
921
+ drag_widget = event.widget.control
922
+ event.data = drag_widget.selection.to_s
923
+ end
924
+ end
925
+ end
926
+ }},
927
+ },
928
+ 'drop_target' => {
929
+ getter: {name: 'getShell', invoker: lambda { |widget, args|
930
+ @drop_target
931
+ }},
932
+ setter: {name: 'getShell', invoker: lambda { |widget, args|
933
+ @drop_target = args.first
934
+ if @drop_target
935
+ case @swt_widget
936
+ when List
937
+ on_drop do |event|
938
+ drop_widget = event.widget.control
939
+ drop_widget.add(event.data) unless @drop_target == :unique && drop_widget.items.include?(event.data)
940
+ drop_widget.select(drop_widget.items.count - 1)
941
+ end
942
+ when Label
943
+ on_drop do |event|
944
+ drop_widget = event.widget.control
945
+ drop_widget.text = event.data
946
+ end
947
+ when Text
948
+ on_drop do |event|
949
+ drop_widget = event.widget.control
950
+ if @drop_target == :replace
951
+ drop_widget.text = event.data
952
+ else
953
+ drop_widget.insert(event.data)
954
+ end
955
+ end
956
+ when Spinner
957
+ on_drop do |event|
958
+ drop_widget = event.widget.control
959
+ drop_widget.selection = event.data.to_f
960
+ end
961
+ end
962
+ end
963
+ }},
964
+ },
889
965
  'window' => {
890
966
  getter: {name: 'getShell'},
891
967
  setter: {name: 'getShell', invoker: lambda { |widget, args| @swt_widget.getShell }}, # No Op
@@ -45,21 +45,21 @@ class Battleship
45
45
  }
46
46
 
47
47
  text player.to_s.capitalize
48
- font height: 20, style: :bold
48
+ font height: OS.windows? ? 18 : 20, style: :bold
49
49
  }
50
50
 
51
51
  label # filler
52
52
  Model::Grid::WIDTH.times do |column_index|
53
53
  label {
54
54
  text (column_index + 1).to_s
55
- font height: 16
55
+ font height: OS.windows? ? 14 : 16
56
56
  }
57
57
  end
58
58
 
59
59
  Model::Grid::HEIGHT.times do |row_index|
60
60
  label {
61
61
  text Model::Grid::ROW_ALPHABETS[row_index]
62
- font height: 16
62
+ font height: OS.windows? ? 14 : 16
63
63
  }
64
64
  Model::Grid::WIDTH.times do |column_index|
65
65
  cell(game: game, player: player, row_index: row_index, column_index: column_index) {
@@ -38,7 +38,7 @@ class Battleship
38
38
 
39
39
  label {
40
40
  text ship_name.to_s.titlecase
41
- font height: 16
41
+ font height: OS.windows? ? 14 : 16
42
42
  }
43
43
 
44
44
  composite {
@@ -23,8 +23,6 @@ require 'glimmer-dsl-swt'
23
23
  require 'fileutils'
24
24
 
25
25
  class Sample
26
- include Glimmer::DataBinding::ObservableModel
27
-
28
26
  class << self
29
27
  def glimmer_directory
30
28
  File.expand_path('../../..', __FILE__)
@@ -42,6 +40,10 @@ class Sample
42
40
  end
43
41
  end
44
42
  end
43
+
44
+ include Glimmer::DataBinding::ObservableModel
45
+
46
+ UNEDITABLE = ['meta_sample.rb'] + (OS.windows? ? ['calculator.rb', 'weather.rb'] : []) # Windows StyledText does not support unicode characters found in certain samples
45
47
 
46
48
  attr_accessor :sample_directory, :file, :selected
47
49
 
@@ -74,9 +76,13 @@ class Sample
74
76
  end
75
77
 
76
78
  def editable
79
+ !UNEDITABLE.include?(File.basename(file))
80
+ end
81
+ alias editable? editable
82
+
83
+ def launchable
77
84
  File.basename(file) != 'meta_sample.rb'
78
85
  end
79
- alias launchable editable
80
86
 
81
87
  def file_relative_path
82
88
  file.sub(self.class.glimmer_directory, '')
@@ -97,6 +103,7 @@ class Sample
97
103
  def launch(modified_code)
98
104
  launch_file = user_file
99
105
  begin
106
+ raise 'Unsupported through editor!' unless editable?
100
107
  FileUtils.cp_r(file, user_file_parent_directory)
101
108
  FileUtils.cp_r(directory, user_file_parent_directory) if File.exist?(directory)
102
109
  File.write(user_file, modified_code)
@@ -207,7 +214,7 @@ class MetaSampleApplication
207
214
  image File.expand_path('../../icons/scaffold_app.png', __dir__)
208
215
 
209
216
  sash_form {
210
- weights 4, 14
217
+ weights 1, 2
211
218
 
212
219
  composite {
213
220
  grid_layout(1, false) {
@@ -45,8 +45,8 @@ class Tetris
45
45
  menu_item(:check) {
46
46
  text '&Pause'
47
47
  accelerator COMMAND_KEY, :p
48
- enabled <= [game, :game_over, on_read: ->(value) { value && !game.show_high_scores }]
49
- enabled <= [game, :show_high_scores, on_read: ->(value) { value && !game.game_over }]
48
+ enabled <= [game, :game_over, on_read: ->(value) { !value && !game.show_high_scores }]
49
+ enabled <= [game, :show_high_scores, on_read: ->(value) { !value && !game.game_over }]
50
50
  selection <=> [game, :paused]
51
51
  }
52
52
  menu_item {
@@ -57,7 +57,17 @@ class Tetris
57
57
  on_swt_keydown { |key_event|
58
58
  case key_event.keyCode
59
59
  when swt(:arrow_down), 's'.bytes.first
60
- game.down! unless OS.windows?
60
+ if OS.mac?
61
+ game.down!
62
+ else
63
+ # rate limit downs in Windows/Linux as they go too fast when key is held
64
+ @queued_downs ||= 0
65
+ @queued_downs += 1
66
+ async_exec do
67
+ game.down! if @queued_downs < 3
68
+ @queued_downs -= 1
69
+ end
70
+ end
61
71
  when swt(:arrow_up)
62
72
  case game.up_arrow_action
63
73
  when :instant_down
@@ -80,16 +90,6 @@ class Tetris
80
90
  end
81
91
  }
82
92
 
83
- # invoke game.down! on keyup with Windows/Linux since they seem to group-render similar events, preventing intermediate renders (causing invisiblity while holding keys)
84
- if !OS.mac?
85
- on_swt_keyup { |key_event|
86
- case key_event.keyCode
87
- when swt(:arrow_down), 's'.bytes.first
88
- game.down!
89
- end
90
- }
91
- end
92
-
93
93
  # if running in app mode, set the Mac app about dialog (ignored in platforms)
94
94
  on_about {
95
95
  show_about_dialog
@@ -170,9 +170,7 @@ class Tetris
170
170
  sleep @game.delay
171
171
  break if @game.game_over? || body_root.disposed?
172
172
  # ensure entire game tetromino down movement happens as one GUI update event with sync_exec (to avoid flicker/stutter)
173
- sync_exec {
174
- @game.down! unless @game.paused?
175
- }
173
+ sync_exec { @game.down! unless @game.paused? }
176
174
  end
177
175
  end
178
176
  end
@@ -41,18 +41,21 @@ class TicTacToe
41
41
  shell {
42
42
  text "Tic-Tac-Toe"
43
43
  minimum_size 176, 200
44
+
44
45
  composite {
45
46
  grid_layout 3, true
47
+
46
48
  (1..3).each { |row|
47
49
  (1..3).each { |column|
48
50
  button {
49
51
  layout_data :fill, :fill, true, true
50
52
  text <= [@tic_tac_toe_board[row, column], :sign]
51
53
  enabled <= [@tic_tac_toe_board[row, column], :empty]
52
- font style: :bold, height: 20
53
- on_widget_selected {
54
+ font style: :bold, height: (OS.windows? ? 18 : 20)
55
+
56
+ on_widget_selected do
54
57
  @tic_tac_toe_board.mark(row, column)
55
- }
58
+ end
56
59
  }
57
60
  }
58
61
  }
@@ -67,7 +67,6 @@ class Timer
67
67
 
68
68
  # Replace example content below with custom shell content
69
69
  minimum_size (OS.windows? ? 214 : 200), 114
70
- image File.join(APP_ROOT, 'package', 'windows', "Timer.ico") if OS.windows?
71
70
  text "Glimmer Timer"
72
71
 
73
72
  timer_menu_bar
@@ -102,6 +102,7 @@ class Weather
102
102
  layout_data(:fill, :center, true, false)
103
103
  text <= [self, field_name, on_read: ->(t) { "#{kelvin_to_temp_unit(t, temp_unit).to_f.round}°" }]
104
104
  font height: DEFAULT_FONT_HEIGHT
105
+ background DEFAULT_BACKGROUND
105
106
  foreground DEFAULT_FOREGROUND
106
107
  }
107
108
  end
@@ -112,6 +113,7 @@ class Weather
112
113
  layout_data(:fill, :center, true, false)
113
114
  text <= [self, 'humidity', on_read: ->(h) { "#{h.to_f.round}%" }]
114
115
  font height: DEFAULT_FONT_HEIGHT
116
+ background DEFAULT_BACKGROUND
115
117
  foreground DEFAULT_FOREGROUND
116
118
  }
117
119
  end
@@ -121,6 +123,7 @@ class Weather
121
123
  layout_data :fill, :center, false, false
122
124
  text field_name.titlecase
123
125
  font height: DEFAULT_FONT_HEIGHT
126
+ background DEFAULT_BACKGROUND
124
127
  foreground DEFAULT_FOREGROUND
125
128
  }
126
129
  end
@@ -65,7 +65,7 @@ class HelloCanvas
65
65
  y :default, 1 # add 1 pixel to default y (shape centered within parent vertically)
66
66
  background :yellow
67
67
  foreground :dark_magenta
68
- font name: 'Courier', height: 30
68
+ font name: 'Courier', height: (OS.windows? ? 26 : 30)
69
69
  }
70
70
  }
71
71
  rectangle(155, 30) { # width and height are assumed to be the default (calculated from children)
@@ -6,7 +6,7 @@ glimmer_logo = File.expand_path('../../icons/scaffold_app.png', __dir__)
6
6
 
7
7
  shell {
8
8
  text 'Hello, Canvas Transform!'
9
- minimum_size 330, 352
9
+ minimum_size (OS.windows? ? 347 : 330), (OS.windows? ? 372 : 352)
10
10
 
11
11
  canvas {
12
12
  background :white
@@ -40,27 +40,28 @@ class HelloCoolBar
40
40
  margin_width 0
41
41
  margin_height 0
42
42
  }
43
-
43
+
44
44
  text 'Hello, Cool Bar!'
45
+ minimum_size 280, 50
45
46
 
46
47
  cool_bar { # optionally takes a :flat style and/or :vertical style if you need vertical layout
47
48
  tool_bar {
48
49
  tool_item {
49
- image cut_image # alternatively you can pass an image file path
50
+ image File.expand_path('./images/cut.png', __dir__), height: 16
50
51
 
51
52
  on_widget_selected do
52
53
  self.operation = 'Cut'
53
54
  end
54
55
  }
55
56
  tool_item {
56
- image copy_image # alternatively you can pass an image file path
57
+ image File.expand_path('./images/copy.png', __dir__), height: 16
57
58
 
58
59
  on_widget_selected do
59
60
  self.operation = 'Copy'
60
61
  end
61
62
  }
62
63
  tool_item {
63
- image paste_image # alternatively you can pass an image file path
64
+ image File.expand_path('./images/paste.png', __dir__), height: 16
64
65
 
65
66
  on_widget_selected do
66
67
  self.operation = 'Paste'
@@ -86,62 +87,6 @@ class HelloCoolBar
86
87
  }
87
88
  }
88
89
  }
89
-
90
- def cut_image
91
- # building image on the fly with Canvas Shape DSL
92
- image(25, 25) {
93
- rectangle(0, 0, 25, 25) {
94
- background_pattern 0, 0, 0, 25, :white, :gray
95
- line(20, 2, 9, 15) {
96
- line_width 2
97
- }
98
- line(5, 2, 16, 15) {
99
- line_width 2
100
- }
101
- oval(2, 15, 8, 8) {
102
- line_width 2
103
- }
104
- oval(16, 15, 8, 8) {
105
- line_width 2
106
- }
107
- }
108
- }
109
- end
110
-
111
- def copy_image
112
- # building image on the fly with Canvas Shape DSL
113
- image(25, 25) {
114
- rectangle(0, 0, 25, 25) {
115
- background_pattern 0, 0, 0, 25, :white, :gray
116
- rectangle([:default, 2], [:default, -2], 14, 14, 5, 5) {
117
- line_width 2
118
- }
119
- rectangle([:default, -2], [:default, 2], 14, 14, 5, 5) {
120
- line_width 2
121
- }
122
- }
123
- }
124
- end
125
-
126
- def paste_image
127
- image(25, 25) {
128
- rectangle(0, 0, 25, 25) {
129
- background_pattern 0, 0, 0, 25, :white, :gray
130
- rectangle(:default, [:default, 1], 15, 20, 5, 5) {
131
- line_width 2
132
- }
133
- line(7, 8, 18, 8) {
134
- line_width 2
135
- }
136
- line(7, 13, 18, 13) {
137
- line_width 2
138
- }
139
- line(7, 18, 18, 18) {
140
- line_width 2
141
- }
142
- }
143
- }
144
- end
145
90
  end
146
91
 
147
92
  HelloCoolBar.launch
@@ -35,18 +35,215 @@ include Glimmer
35
35
 
36
36
  shell {
37
37
  text 'Hello, Drag and Drop!'
38
- list {
39
- selection <=> [@location, :country]
40
- on_drag_set_data { |event|
41
- list = event.widget.getControl
42
- event.data = list.getSelection.first
38
+
39
+ tab_folder {
40
+ tab_item {
41
+ fill_layout
42
+ text 'List'
43
+
44
+ list {
45
+ selection <=> [@location, :country]
46
+
47
+ # Option 1: Automatic Drag Data Setting
48
+ drag_source true
49
+
50
+ # Option 2: Manual Drag Data Setting
51
+ # on_drag_set_data do |event|
52
+ # drag_widget = event.widget.control
53
+ # event.data = drag_widget.selection.first
54
+ # end
55
+
56
+ # Option 3: Full Customization of Drag Source (details at: https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html)
57
+ # drag_source(:drop_copy) { # options: :drop_copy, :drop_link, :drop_move, :drop_target_move
58
+ # transfer :text # options: :text, :file, :rtf
59
+ #
60
+ # on_drag_start do |event|
61
+ # drag_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting cursor via symbol
62
+ # drag_widget.cursor = :wait
63
+ # end
64
+ #
65
+ # on_drag_set_data do |event|
66
+ # drag_widget = event.widget.control
67
+ # event.data = drag_widget.selection.first
68
+ # end
69
+ #
70
+ # on_drag_finished do |event|
71
+ # drag_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting cursor via symbol
72
+ # drag_widget.cursor = :arrow
73
+ # end
74
+ # }
75
+ }
76
+
77
+ list {
78
+ # Option 1: Automatic Drop Data Consumption
79
+ drop_target true
80
+ # drop_target :unique # setting drop_target to :unique makes the list not add the same data twice
81
+
82
+ # Option 2: Manual Drop Data Consumption
83
+ # on_drop do |event|
84
+ # drop_widget = event.widget.control
85
+ # drop_widget.add(event.data)
86
+ # drop_widget.select(drop_widget.items.count - 1)
87
+ # end
88
+
89
+ # Option 3: Full Customization of Drop Target (details at: https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html)
90
+ # drop_target(:drop_copy) { # options: :drop_copy, :drop_link, :drop_move, :drop_target_move
91
+ # transfer :text # options: :text, :file, :rtf
92
+ #
93
+ # on_drag_enter do |event|
94
+ # ### event.detail = DND::DROP_NONE # To reject a drop, you can set event.detail to DND::DROP_NONE
95
+ # drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol
96
+ # drop_widget.background = :red
97
+ # end
98
+ #
99
+ # on_drag_leave do |event|
100
+ # drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol
101
+ # drop_widget.background = :white
102
+ # end
103
+ #
104
+ # on_drop do |event|
105
+ # drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background/cursor via symbol
106
+ # drop_widget.background = :white
107
+ # drop_widget.add(event.data)
108
+ # drop_widget.select(drop_widget.items.count - 1)
109
+ # drop_widget.cursor = :arrow
110
+ # end
111
+ # }
112
+ }
43
113
  }
44
- }
45
- label(:center) {
46
- text 'Drag a country here!'
47
- font height: 20
48
- on_drop { |event|
49
- event.widget.getControl.setText(event.data)
114
+
115
+ tab_item {
116
+ grid_layout 2, true
117
+ text 'Label'
118
+
119
+ label {
120
+ layout_data {
121
+ horizontal_span 2
122
+ }
123
+ text 'Drag text from any label and drop it unto another label'
124
+ }
125
+
126
+ {
127
+ Argentina: :green,
128
+ Brazil: :red,
129
+ Finland: :yellow,
130
+ Sweden: :magenta,
131
+ Denmark: :gray,
132
+ Iceland: :cyan
133
+ }.each do |country, color|
134
+ label {
135
+ layout_data :fill, :fill, true, true
136
+ text country
137
+ font height: 20
138
+ background color
139
+ drag_source true
140
+ drop_target true
141
+ }
142
+ end
143
+ }
144
+
145
+ tab_item {
146
+ grid_layout 2, true
147
+ text 'Text'
148
+
149
+ label {
150
+ text 'Drag'
151
+ }
152
+
153
+ label {
154
+ text 'Drop To Insert'
155
+ }
156
+
157
+ text {
158
+ layout_data :fill, :center, true, false
159
+ text 'Text1'
160
+ drag_source true
161
+ }
162
+
163
+ text {
164
+ layout_data :fill, :center, true, false
165
+ text 'Drop To Insert'
166
+ drop_target true
167
+ }
168
+
169
+ label {
170
+ text 'Drag'
171
+ }
172
+
173
+ label {
174
+ text 'Drop To Replace'
175
+ }
176
+
177
+ text {
178
+ layout_data :fill, :center, true, false
179
+ text 'Text2'
180
+ drag_source true
181
+ }
182
+
183
+ text {
184
+ layout_data :fill, :center, true, false
185
+ text 'Drop To Replace'
186
+ drop_target :replace
187
+ }
188
+ }
189
+
190
+ tab_item {
191
+ grid_layout 2, true
192
+ text 'Spinner'
193
+
194
+ label {
195
+ text 'Drag'
196
+ }
197
+
198
+ label {
199
+ text 'Drop To Insert'
200
+ }
201
+
202
+ spinner {
203
+ layout_data :fill, :center, true, false
204
+ selection 30
205
+ drag_source true
206
+ }
207
+
208
+ spinner {
209
+ layout_data :fill, :center, true, false
210
+ drop_target true
211
+ }
212
+ }
213
+ tab_item {
214
+ fill_layout
215
+ text 'File'
216
+
217
+ @drop_zone_label = label(:center, :wrap) {
218
+ text 'Drop One File Or More Here'
219
+ background :white
220
+
221
+ rectangle {
222
+ foreground :black
223
+ line_width 4
224
+ line_style :dash
225
+ }
226
+
227
+ drop_target(:drop_copy) {
228
+ transfer :file
229
+
230
+ on_drag_enter do |event|
231
+ drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol
232
+ drop_widget.background = :yellow
233
+ end
234
+
235
+ on_drag_leave do |event|
236
+ drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol
237
+ drop_widget.background = :white
238
+ end
239
+
240
+ on_drop do |event|
241
+ drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background/cursor via symbol
242
+ drop_widget.background = :white
243
+ @drop_zone_label.text = event.data.to_a.join("\n")
244
+ end
245
+ }
246
+ }
50
247
  }
51
248
  }
52
249
  }.open