glimmer-dsl-swt 4.21.1.0 → 4.21.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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