glimmer-dsl-swt 0.2.3 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fee38949564fb2b0f3874a1bad1229cfb813439f0dca2e08b8d293b8c61fecb9
4
- data.tar.gz: eb0e920dba273a6a343aeeb34cc664c33b7238b151df0e8cd5a4679aaee85b29
3
+ metadata.gz: d5cda7a8bb248622a5f6ce1347622064f56c2f9ce64d788c94b3ae7e9d4a633b
4
+ data.tar.gz: 324e1458a7bfc6f6f10e92ac61080e5d046e2c6466ec89e42ebe12ece76b77e4
5
5
  SHA512:
6
- metadata.gz: c5ca29f9d303aa9320acb7f97492c8caf9d7e1135597ba646a3e5b238ec6e47408da2e4ea87f74c50ae283cd313def6d35c93e622040123dfb438c12d9330f8c
7
- data.tar.gz: cd22b1bf5093d4a3a1c9caea73d152678395e7aa0110bdcfbe1df2ee923ca85d601c8529120a17acadabe75af979fc3791477ec00dde075b59a1f13565f5cf2a
6
+ metadata.gz: 7bd2e99cac06446f683102ae9825fbcda7c0ede916b842480688b2a76e5b1ceb9863bf006c683217a432b65a87accc86bba2b7521b7b1daa8b7d429bd12b5108
7
+ data.tar.gz: 84d7055deee13d4b2c955edb555202ba882fdb961ed2b49759b27588777bca90000fceb51607a8cfbe2b5a023c4741012e98f8f1e9693318943985b79dbe751a
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 /> Glimmer DSL for SWT 0.2.3 (Desktop GUI)
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 /> Glimmer DSL for SWT 0.4.1 (Desktop GUI)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-swt.svg)](http://badge.fury.io/rb/glimmer-dsl-swt)
3
3
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-swt.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-swt)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer-dsl-swt/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer-dsl-swt?branch=master)
@@ -10,7 +10,7 @@
10
10
 
11
11
  You may find full setup/usage instructions at the main [Glimmer project page](https://github.com/AndyObtiva/glimmer).
12
12
 
13
- Other Glimmer DSL gems:
13
+ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
14
14
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
15
15
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
16
16
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.4.1
@@ -15,6 +15,7 @@ module Glimmer
15
15
  def initialize(parent, model_binding, column_properties)
16
16
  @table = parent
17
17
  @model_binding = model_binding
18
+ @table.swt_widget.data = @model_binding
18
19
  @column_properties = column_properties
19
20
  if @table.respond_to?(:column_properties=)
20
21
  @table.column_properties = @column_properties
@@ -0,0 +1,20 @@
1
+ require 'glimmer/dsl/expression'
2
+
3
+ module Glimmer
4
+ module DSL
5
+ module SWT
6
+ class BlockPropertyExpression < Expression
7
+ def can_interpret?(parent, keyword, *args, &block)
8
+ block_given? and
9
+ args.size == 0 and
10
+ parent.respond_to?("#{keyword}_block=")
11
+ end
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ parent.send("#{keyword}_block=", block)
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -25,6 +25,7 @@ module Glimmer
25
25
  table_items_data_binding
26
26
  data_binding
27
27
  property
28
+ block_property
28
29
  widget
29
30
  custom_widget
30
31
  ]
@@ -20,7 +20,7 @@ module Glimmer
20
20
  end
21
21
 
22
22
  def interpret(parent, keyword, *args, &block)
23
- Glimmer::SWT::DisplayProxy.instance.send(exec_operation, &block)
23
+ Glimmer::SWT::DisplayProxy.instance.swt_display.send(exec_operation, &block)
24
24
  end
25
25
  end
26
26
  end
@@ -31,5 +31,7 @@ module Glimmer
31
31
  end
32
32
 
33
33
  require 'glimmer/swt/widget_proxy'
34
+ require 'glimmer/swt/scrolled_composite_proxy'
34
35
  require 'glimmer/swt/tree_proxy'
35
36
  require 'glimmer/swt/table_proxy'
37
+ require 'glimmer/swt/table_column_proxy'
@@ -485,12 +485,10 @@ class Scaffold
485
485
  custom_shell_file_content += <<-MULTI_LINE_STRING
486
486
 
487
487
  def display_about_dialog
488
- message_box = MessageBox.new(swt_widget)
489
- message_box.setText("About")
490
- message = "#{human_name(namespace)} - #{human_name(custom_shell_name)} \#{VERSION}\n\n"
491
- message += LICENSE
492
- message_box.setMessage(message)
493
- message_box.open
488
+ message_box(body_root) {
489
+ text 'About'
490
+ message "#{human_name(namespace)} - #{human_name(custom_shell_name)} \#{VERSION}\\n\\n\#{LICENSE}"
491
+ }.open
494
492
  end
495
493
 
496
494
  def display_preferences_dialog
@@ -48,6 +48,17 @@ module Glimmer
48
48
  end
49
49
  @swt_color
50
50
  end
51
+
52
+ def method_missing(method, *args, &block)
53
+ swt_color.send(method, *args, &block)
54
+ rescue => e
55
+ Glimmer::Config.logger&.debug "Neither ColorProxy nor #{swt_color.class.name} can handle the method ##{method}"
56
+ super
57
+ end
58
+
59
+ def respond_to?(method, *args, &block)
60
+ super || swt_color.respond_to?(method, *args, &block)
61
+ end
51
62
  end
52
63
  end
53
64
  end
@@ -33,26 +33,24 @@ module Glimmer
33
33
 
34
34
  def initialize(*args)
35
35
  @swt_display = Display.new(*args)
36
+ @swt_display.set_data('proxy', self)
36
37
  end
37
38
 
38
- def dispose
39
- @swt_display.dispose
39
+ def method_missing(method, *args, &block)
40
+ swt_display.send(method, *args, &block)
41
+ rescue => e
42
+ Glimmer::Config.logger&.debug "Neither DisplayProxy nor #{swt_display.class.name} can handle the method ##{method}"
43
+ super
40
44
  end
41
-
42
- # Executes code block asynchronously with respect to SWT UI thread
43
- def async_exec(&block)
44
- @swt_display.asyncExec(&block)
45
- end
46
-
47
- # Executes code block synchronously with respect to SWT UI thread
48
- def sync_exec(&block)
49
- @swt_display.syncExec(&block)
45
+
46
+ def respond_to?(method, *args, &block)
47
+ super || swt_display.respond_to?(method, *args, &block)
50
48
  end
51
49
 
52
50
  def can_handle_observation_request?(observation_request)
53
51
  observation_request = observation_request.to_s
54
- if observation_request.start_with?('on_event_')
55
- constant_name = observation_request.sub(/^on_event_/, '')
52
+ if observation_request.start_with?('on_swt_')
53
+ constant_name = observation_request.sub(/^on_swt_/, '')
56
54
  SWTProxy.has_constant?(constant_name)
57
55
  elsif observation_request.start_with?('on_')
58
56
  event_name = observation_request.sub(/^on_/, '')
@@ -63,8 +61,8 @@ module Glimmer
63
61
  end
64
62
 
65
63
  def handle_observation_request(observation_request, &block)
66
- if observation_request.start_with?('on_event_')
67
- constant_name = observation_request.sub(/^on_event_/, '')
64
+ if observation_request.start_with?('on_swt_')
65
+ constant_name = observation_request.sub(/^on_swt_/, '')
68
66
  add_swt_event_listener(constant_name, &block)
69
67
  elsif observation_request.start_with?('on_')
70
68
  event_name = observation_request.sub(/^on_/, '')
@@ -0,0 +1,21 @@
1
+ require 'glimmer/swt/widget_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class ScrolledCompositeProxy < Glimmer::SWT::WidgetProxy
6
+ def initialize(underscored_widget_name, parent, args)
7
+ unless args.first.is_a?(Numeric)
8
+ args.unshift(:h_scroll)
9
+ args.unshift(:v_scroll)
10
+ end
11
+ super
12
+ swt_widget.expand_horizontal = true
13
+ swt_widget.expand_vertical = true
14
+ end
15
+
16
+ def post_initialize_child(child)
17
+ swt_widget.content = child.swt_widget
18
+ end
19
+ end
20
+ end
21
+ end
@@ -40,9 +40,10 @@ module Glimmer
40
40
  end
41
41
  args = args.compact
42
42
  @swt_widget = Shell.new(*args)
43
+ @swt_widget.set_data('proxy', self)
43
44
  @swt_widget.setLayout(FillLayout.new)
44
45
  @swt_widget.setMinimumSize(WIDTH_MIN, HEIGHT_MIN)
45
- on_event_show do
46
+ on_swt_show do
46
47
  Thread.new do
47
48
  sleep(0.25)
48
49
  async_exec do
@@ -130,7 +131,11 @@ module Glimmer
130
131
  # This method is not needed except in rare circumstances where there is a need to start the SWT Event Loop before opening the shell.
131
132
  def start_event_loop
132
133
  until @swt_widget.isDisposed
133
- @display.sleep unless @display.readAndDispatch
134
+ begin
135
+ @display.sleep unless @display.readAndDispatch
136
+ rescue => e
137
+ Glimmer::Config.logger&.debug e.full_message
138
+ end
134
139
  end
135
140
  end
136
141
 
@@ -140,9 +145,9 @@ module Glimmer
140
145
  visibility_notifier = proc do
141
146
  observer.call(visible?)
142
147
  end
143
- on_event_show(&visibility_notifier)
144
- on_event_hide(&visibility_notifier)
145
- on_event_close(&visibility_notifier)
148
+ on_swt_show(&visibility_notifier)
149
+ on_swt_hide(&visibility_notifier)
150
+ on_swt_close(&visibility_notifier)
146
151
  else
147
152
  super
148
153
  end
@@ -31,7 +31,8 @@ module Glimmer
31
31
  end
32
32
 
33
33
  EXTRA_STYLES = {
34
- NO_RESIZE: self[:shell_trim, :resize!, :max!]
34
+ NO_RESIZE: self[:shell_trim, :resize!, :max!],
35
+ NO_SORT: -7,
35
36
  }
36
37
  end
37
38
  end
@@ -0,0 +1,28 @@
1
+ require 'glimmer/swt/widget_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class TableColumnProxy < Glimmer::SWT::WidgetProxy
6
+ attr_reader :no_sort, :sort_property, :editor
7
+ alias no_sort? no_sort
8
+ attr_accessor :sort_block, :sort_by_block
9
+
10
+ def initialize(underscored_widget_name, parent, args)
11
+ @no_sort = args.delete(:no_sort)
12
+ super
13
+ on_widget_selected do |event|
14
+ parent.sort_by_column(self)
15
+ end unless no_sort?
16
+ end
17
+
18
+ def sort_property=(args)
19
+ @sort_property = args unless args.empty?
20
+ end
21
+
22
+ def editor=(args)
23
+ @editor = args
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -23,8 +23,8 @@ module Glimmer
23
23
  def find_table_item_and_column_index
24
24
  {}.tap do |result|
25
25
  if respond_to?(:x) && respond_to?(:y)
26
- result[:table_item] = widget.getItems.detect do |ti|
27
- result[:column_index] = widget.getColumnCount.times.to_a.detect do |ci|
26
+ result[:table_item] = widget.items.detect do |ti|
27
+ result[:column_index] = widget.column_count.times.to_a.detect do |ci|
28
28
  ti.getBounds(ci).contains(x, y)
29
29
  end
30
30
  end
@@ -33,7 +33,61 @@ module Glimmer
33
33
  end
34
34
  end
35
35
 
36
- attr_reader :table_editor, :table_editor_text_proxy
36
+ class << self
37
+ def editors
38
+ @editors ||= {
39
+ text: {
40
+ widget_value_property: :text,
41
+ editor_gui: lambda do |args, model, property, table_proxy|
42
+ table_proxy.table_editor.minimumHeight = 20
43
+ table_editor_widget_proxy = text(*args) {
44
+ text model.send(property)
45
+ focus true
46
+ on_focus_lost {
47
+ table_proxy.finish_edit!
48
+ }
49
+ on_key_pressed { |key_event|
50
+ if key_event.keyCode == swt(:cr)
51
+ table_proxy.finish_edit!
52
+ elsif key_event.keyCode == swt(:esc)
53
+ table_proxy.cancel_edit!
54
+ end
55
+ }
56
+ }
57
+ table_editor_widget_proxy.swt_widget.selectAll
58
+ table_editor_widget_proxy
59
+ end,
60
+ },
61
+ combo: {
62
+ widget_value_property: :text,
63
+ editor_gui: lambda do |args, model, property, table_proxy|
64
+ table_proxy.table_editor.minimumHeight = 25
65
+ table_editor_widget_proxy = combo(*args) {
66
+ items model.send("#{property}_options")
67
+ text model.send(property)
68
+ focus true
69
+ on_focus_lost {
70
+ table_proxy.finish_edit!
71
+ }
72
+ on_key_pressed { |key_event|
73
+ if key_event.keyCode == swt(:cr)
74
+ table_proxy.finish_edit!
75
+ elsif key_event.keyCode == swt(:esc)
76
+ table_proxy.cancel_edit!
77
+ end
78
+ }
79
+ on_widget_selected {
80
+ table_proxy.finish_edit!
81
+ }
82
+ }
83
+ table_editor_widget_proxy
84
+ end,
85
+ }
86
+ }
87
+ end
88
+ end
89
+
90
+ attr_reader :table_editor, :table_editor_widget_proxy, :sort_property, :sort_direction, :sort_block, :sort_type, :sort_by_block, :additional_sort_properties, :editor
37
91
  attr_accessor :column_properties
38
92
 
39
93
  def initialize(underscored_widget_name, parent, args)
@@ -43,7 +97,95 @@ module Glimmer
43
97
  @table_editor.grabHorizontal = true
44
98
  @table_editor.minimumHeight = 20
45
99
  end
46
-
100
+
101
+ def model_binding
102
+ swt_widget.data
103
+ end
104
+
105
+ def sort_by_column(table_column_proxy)
106
+ index = swt_widget.columns.to_a.index(table_column_proxy.swt_widget)
107
+ new_sort_property = table_column_proxy.sort_property || [column_properties[index]]
108
+ if new_sort_property.size == 1 && !additional_sort_properties.to_a.empty?
109
+ selected_additional_sort_properties = additional_sort_properties.clone
110
+ if selected_additional_sort_properties.include?(new_sort_property.first)
111
+ selected_additional_sort_properties.delete(new_sort_property.first)
112
+ new_sort_property += selected_additional_sort_properties
113
+ else
114
+ new_sort_property += additional_sort_properties
115
+ end
116
+ end
117
+
118
+ @sort_direction = @sort_direction.nil? || @sort_property != new_sort_property || @sort_direction == :descending ? :ascending : :descending
119
+ swt_widget.sort_direction = @sort_direction == :ascending ? SWTProxy[:up] : SWTProxy[:down]
120
+
121
+ @sort_property = new_sort_property
122
+ swt_widget.sort_column = table_column_proxy.swt_widget
123
+
124
+ @sort_by_block = nil
125
+ @sort_block = nil
126
+ @sort_type = nil
127
+ if table_column_proxy.sort_by_block
128
+ @sort_by_block = table_column_proxy.sort_by_block
129
+ elsif table_column_proxy.sort_block
130
+ @sort_block = table_column_proxy.sort_block
131
+ else
132
+ detect_sort_type
133
+ end
134
+ sort
135
+ end
136
+
137
+ def detect_sort_type
138
+ @sort_type = sort_property.size.times.map { String }
139
+ array = model_binding.evaluate_property
140
+ sort_property.each_with_index do |a_sort_property, i|
141
+ values = array.map { |object| object.send(a_sort_property) }
142
+ value_classes = values.map(&:class).uniq
143
+ if value_classes.size == 1
144
+ @sort_type[i] = value_classes.first
145
+ elsif value_classes.include?(Integer)
146
+ @sort_type[i] = Integer
147
+ elsif value_classes.include?(Float)
148
+ @sort_type[i] = Float
149
+ end
150
+ end
151
+ end
152
+
153
+ def additional_sort_properties=(args)
154
+ @additional_sort_properties = args unless args.empty?
155
+ end
156
+
157
+ def editor=(args)
158
+ @editor = args
159
+ end
160
+
161
+ def sort
162
+ return unless sort_property && (sort_type || sort_block || sort_by_block)
163
+ array = model_binding.evaluate_property
164
+ # Converting value to_s first to handle nil cases. Should work with numeric, boolean, and date fields
165
+ if sort_block
166
+ sorted_array = array.sort(&sort_block)
167
+ elsif sort_by_block
168
+ sorted_array = array.sort_by(&sort_by_block)
169
+ else
170
+ sorted_array = array.sort_by do |object|
171
+ sort_property.each_with_index.map do |a_sort_property, i|
172
+ value = object.send(a_sort_property)
173
+ # handle nil and difficult to compare types gracefully
174
+ if sort_type[i] == Integer
175
+ value = value.to_i
176
+ elsif sort_type[i] == Float
177
+ value = value.to_f
178
+ elsif sort_type[i] == String
179
+ value = value.to_s
180
+ end
181
+ value
182
+ end
183
+ end
184
+ end
185
+ sorted_array = sorted_array.reverse if sort_direction == :descending
186
+ model_binding.call(sorted_array)
187
+ end
188
+
47
189
  # Performs a search for table items matching block condition
48
190
  # If no condition block is passed, returns all table items
49
191
  # Returns a Java TableItem array to easily set as selection on org.eclipse.swt.Table if needed
@@ -68,6 +210,14 @@ module Glimmer
68
210
  })
69
211
  end
70
212
 
213
+ def post_initialize_child(table_column_proxy)
214
+ table_column_proxies << table_column_proxy
215
+ end
216
+
217
+ def table_column_proxies
218
+ @table_column_proxies ||= []
219
+ end
220
+
71
221
  # Indicates if table is in edit mode, thus displaying a text widget for a table item cell
72
222
  def edit_mode?
73
223
  !!@edit_mode
@@ -93,58 +243,62 @@ module Glimmer
93
243
 
94
244
  def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
95
245
  return if table_item.nil?
246
+ model = table_item.data
247
+ property = column_properties[column_index]
96
248
  @cancel_edit&.call if @edit_mode
249
+ action_taken = false
97
250
  @edit_mode = true
98
- content {
99
- @table_editor_text_proxy = text {
100
- focus true
101
- text table_item.getText(column_index)
102
- action_taken = false
103
- @cancel_edit = lambda do
104
- @cancel_in_progress = true
105
- @table_editor_text_proxy&.swt_widget&.dispose
106
- @table_editor_text_proxy = nil
107
- after_cancel&.call
251
+
252
+ editor_config = table_column_proxies[column_index].editor || editor
253
+ editor_config = editor_config.to_a
254
+ editor_widget_options = editor_config.last.is_a?(Hash) ? editor_config.last : {}
255
+ editor_widget_arg_last_index = editor_config.last.is_a?(Hash) ? -2 : -1
256
+ editor_widget = editor_config[0] || :text
257
+ editor_widget_args = editor_config[1..editor_widget_arg_last_index]
258
+ model_editing_property = editor_widget_options[:property] || property
259
+ widget_value_property = TableProxy::editors[editor_widget][:widget_value_property]
260
+
261
+ @cancel_edit = lambda do |event=nil|
262
+ @cancel_in_progress = true
263
+ @table_editor_widget_proxy&.swt_widget&.dispose
264
+ @table_editor_widget_proxy = nil
265
+ after_cancel&.call
266
+ @edit_in_progress = false
267
+ @cancel_in_progress = false
268
+ @cancel_edit = nil
269
+ @edit_mode = false
270
+ end
271
+
272
+ @finish_edit = lambda do |event=nil|
273
+ new_value = @table_editor_widget_proxy&.swt_widget&.send(widget_value_property)
274
+ if table_item.isDisposed
275
+ @cancel_edit.call
276
+ elsif new_value && !action_taken && !@edit_in_progress && !@cancel_in_progress
277
+ action_taken = true
278
+ @edit_in_progress = true
279
+ if new_value == model.send(model_editing_property)
280
+ @cancel_edit.call
281
+ else
282
+ before_write&.call
283
+ model.send("#{model_editing_property}=", new_value) # makes table update itself, so must search for selected table item again
284
+ # Table refresh happens here because of model update triggering observers, so must retrieve table item again
285
+ edited_table_item = search { |ti| ti.getData == model }.first
286
+ swt_widget.showItem(edited_table_item)
287
+ @table_editor_widget_proxy&.swt_widget&.dispose
288
+ @table_editor_widget_proxy = nil
289
+ after_write&.call(edited_table_item)
108
290
  @edit_in_progress = false
109
- @cancel_in_progress = false
110
- @cancel_edit = nil
111
- @edit_mode = false
112
- end
113
- @finish_edit = lambda do |event=nil|
114
- if table_item.isDisposed
115
- @cancel_edit.call
116
- elsif !action_taken && !@edit_in_progress && !@cancel_in_progress
117
- action_taken = true
118
- @edit_in_progress = true
119
- new_text = @table_editor_text_proxy.swt_widget.getText
120
- if new_text == table_item.getText(column_index)
121
- @cancel_edit.call
122
- else
123
- before_write&.call
124
- table_item.setText(column_index, new_text)
125
- model = table_item.getData
126
- model.send("#{column_properties[column_index]}=", new_text) # makes table update itself, so must search for selected table item again
127
- edited_table_item = search { |ti| ti.getData == model }.first
128
- swt_widget.showItem(edited_table_item)
129
- @table_editor_text_proxy&.swt_widget&.dispose
130
- @table_editor_text_proxy = nil
131
- after_write&.call(edited_table_item)
132
- @edit_in_progress = false
133
- end
134
- end
135
291
  end
136
- on_focus_lost(&@finish_edit)
137
- on_key_pressed { |key_event|
138
- if key_event.keyCode == swt(:cr)
139
- @finish_edit.call(key_event)
140
- elsif key_event.keyCode == swt(:esc)
141
- @cancel_edit.call
142
- end
143
- }
144
- }
145
- @table_editor_text_proxy.swt_widget.selectAll
292
+ end
293
+ end
294
+
295
+ content {
296
+ @table_editor_widget_proxy = TableProxy::editors[editor_widget][:editor_gui].call(editor_widget_args, model, model_editing_property, self)
146
297
  }
147
- @table_editor.setEditor(@table_editor_text_proxy.swt_widget, table_item, column_index)
298
+ @table_editor.setEditor(@table_editor_widget_proxy.swt_widget, table_item, column_index)
299
+ rescue => e
300
+ Glimmer::Config.logger&.error e.full_message
301
+ raise e
148
302
  end
149
303
 
150
304
  def add_listener(underscored_listener_name, &block)
@@ -60,7 +60,14 @@ module Glimmer
60
60
  styles, extra_options = extract_args(underscored_widget_name, args)
61
61
  swt_widget_class = self.class.swt_widget_class_for(underscored_widget_name)
62
62
  @swt_widget = swt_widget_class.new(parent.swt_widget, style(underscored_widget_name, styles), *extra_options)
63
+ @swt_widget.set_data('proxy', self)
63
64
  DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@swt_widget)
65
+ parent.post_initialize_child(self)
66
+ end
67
+
68
+ # Subclasses may override to perform post initialization work on an added child
69
+ def post_initialize_child(child)
70
+ # No Op by default
64
71
  end
65
72
 
66
73
  def extract_args(underscored_widget_name, args)
@@ -170,44 +177,44 @@ module Glimmer
170
177
  }
171
178
  end,
172
179
  :caret_position => lambda do |observer|
173
- on_event_keydown { |event|
180
+ on_swt_keydown { |event|
174
181
  observer.call(@swt_widget.getCaretPosition)
175
182
  }
176
- on_event_keyup { |event|
183
+ on_swt_keyup { |event|
177
184
  observer.call(@swt_widget.getCaretPosition)
178
185
  }
179
- on_event_mousedown { |event|
186
+ on_swt_mousedown { |event|
180
187
  observer.call(@swt_widget.getCaretPosition)
181
188
  }
182
- on_event_mouseup { |event|
189
+ on_swt_mouseup { |event|
183
190
  observer.call(@swt_widget.getCaretPosition)
184
191
  }
185
192
  end,
186
193
  :selection => lambda do |observer|
187
- on_event_keydown { |event|
194
+ on_swt_keydown { |event|
188
195
  observer.call(@swt_widget.getSelection)
189
196
  }
190
- on_event_keyup { |event|
197
+ on_swt_keyup { |event|
191
198
  observer.call(@swt_widget.getSelection)
192
199
  }
193
- on_event_mousedown { |event|
200
+ on_swt_mousedown { |event|
194
201
  observer.call(@swt_widget.getSelection)
195
202
  }
196
- on_event_mouseup { |event|
203
+ on_swt_mouseup { |event|
197
204
  observer.call(@swt_widget.getSelection)
198
205
  }
199
206
  end,
200
207
  :selection_count => lambda do |observer|
201
- on_event_keydown { |event|
208
+ on_swt_keydown { |event|
202
209
  observer.call(@swt_widget.getSelectionCount)
203
210
  }
204
- on_event_keyup { |event|
211
+ on_swt_keyup { |event|
205
212
  observer.call(@swt_widget.getSelectionCount)
206
213
  }
207
- on_event_mousedown { |event|
214
+ on_swt_mousedown { |event|
208
215
  observer.call(@swt_widget.getSelectionCount)
209
216
  }
210
- on_event_mouseup { |event|
217
+ on_swt_mouseup { |event|
211
218
  observer.call(@swt_widget.getSelectionCount)
212
219
  }
213
220
  end,
@@ -265,12 +272,12 @@ module Glimmer
265
272
  return nil
266
273
  end
267
274
  swt_widget_class
268
- rescue NameError => e
269
- Glimmer::Config.logger&.debug e.message
275
+ rescue SyntaxError, NameError => e
276
+ Glimmer::Config.logger&.debug e.full_message
270
277
  # Glimmer::Config.logger&.debug("#{e.message}\n#{e.backtrace.join("\n")}")
271
278
  nil
272
279
  rescue => e
273
- Glimmer::Config.logger&.debug e.message
280
+ Glimmer::Config.logger&.debug e.full_message
274
281
  # Glimmer::Config.logger&.debug("#{e.message}\n#{e.backtrace.join("\n")}")
275
282
  nil
276
283
  end
@@ -332,8 +339,8 @@ module Glimmer
332
339
 
333
340
  def can_handle_observation_request?(observation_request)
334
341
  observation_request = observation_request.to_s
335
- if observation_request.start_with?('on_event_')
336
- constant_name = observation_request.sub(/^on_event_/, '')
342
+ if observation_request.start_with?('on_swt_')
343
+ constant_name = observation_request.sub(/^on_swt_/, '')
337
344
  SWTProxy.has_constant?(constant_name)
338
345
  elsif observation_request.start_with?('on_')
339
346
  event = observation_request.sub(/^on_/, '')
@@ -351,6 +358,9 @@ module Glimmer
351
358
  @drag_source_proxy = nil
352
359
  end
353
360
  end
361
+ rescue => e
362
+ Glimmer::Config.logger&.debug(e.full_message)
363
+ false
354
364
  end
355
365
 
356
366
  def can_handle_drop_observation_request?(observation_request)
@@ -366,8 +376,8 @@ module Glimmer
366
376
  end
367
377
 
368
378
  def handle_observation_request(observation_request, &block)
369
- if observation_request.start_with?('on_event_')
370
- constant_name = observation_request.sub(/^on_event_/, '')
379
+ if observation_request.start_with?('on_swt_')
380
+ constant_name = observation_request.sub(/^on_swt_/, '')
371
381
  add_swt_event_listener(constant_name, &block)
372
382
  elsif observation_request.start_with?('on_')
373
383
  event = observation_request.sub(/^on_/, '')
@@ -386,6 +396,17 @@ module Glimmer
386
396
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::WidgetExpression.new, &block)
387
397
  end
388
398
 
399
+ def method_missing(method, *args, &block)
400
+ swt_widget.send(method, *args, &block)
401
+ rescue => e
402
+ Glimmer::Config.logger&.debug "Neither WidgetProxy nor #{swt_widget.class.name} can handle the method ##{method}"
403
+ super
404
+ end
405
+
406
+ def respond_to?(method, *args, &block)
407
+ super || swt_widget.respond_to?(method, *args, &block)
408
+ end
409
+
389
410
  private
390
411
 
391
412
  def style(underscored_widget_name, styles)
@@ -431,7 +452,7 @@ module Glimmer
431
452
  def add_listener(underscored_listener_name, &block)
432
453
  widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
433
454
  widget_listener_proxy = nil
434
- safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
455
+ safe_block = lambda { |*args| block.call(*args) unless @swt_widget.isDisposed }
435
456
  listener = listener_class.new(listener_method => safe_block)
436
457
  @swt_widget.send(widget_add_listener_method, listener)
437
458
  widget_listener_proxy = WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: listener, widget_add_listener_method: widget_add_listener_method, swt_listener_class: listener_class, swt_listener_method: listener_method)
@@ -473,9 +494,9 @@ module Glimmer
473
494
  listener_class.define_method('initialize') do |event_method_block_mapping|
474
495
  @event_method_block_mapping = event_method_block_mapping
475
496
  end
476
- listener_type.getMethods.each do |event_method|
477
- listener_class.define_method(event_method.getName) do |event|
478
- @event_method_block_mapping[event_method.getName]&.call(event)
497
+ listener_type.getMethods.each do |event_method|
498
+ listener_class.define_method(event_method.getName) do |*args|
499
+ @event_method_block_mapping[event_method.getName]&.call(*args)
479
500
  end
480
501
  end
481
502
  end
@@ -486,7 +507,7 @@ module Glimmer
486
507
  def add_swt_event_listener(swt_constant, &block)
487
508
  event_type = SWTProxy[swt_constant]
488
509
  widget_listener_proxy = nil
489
- safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
510
+ safe_block = lambda { |*args| block.call(*args) unless @swt_widget.isDisposed }
490
511
  @swt_widget.addListener(event_type, &safe_block)
491
512
  widget_listener_proxy = WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: @swt_widget.getListeners(event_type).last, event_type: event_type, swt_constant: swt_constant)
492
513
  end
@@ -573,7 +594,7 @@ module Glimmer
573
594
  end
574
595
  image_data = ImageData.new(value)
575
596
  # TODO in the future, look into unregistering this listener when no longer needed
576
- on_event_Resize do |resize_event|
597
+ on_swt_Resize do |resize_event|
577
598
  new_image_data = image_data.scaledTo(@swt_widget.getSize.x, @swt_widget.getSize.y)
578
599
  @swt_widget.getBackgroundImage&.dispose
579
600
  @swt_widget.setBackgroundImage(Image.new(@swt_widget.getDisplay, new_image_data))
@@ -8,6 +8,7 @@ module Glimmer
8
8
 
9
9
  def initialize(parent, *swt_constants, options, &content)
10
10
  super
11
+ @swt_widget.set_data('custom_shell', self)
11
12
  raise Error, 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.swt_widget.is_a?(org.eclipse.swt.widgets.Shell)
12
13
  end
13
14
 
@@ -134,11 +134,13 @@ module Glimmer
134
134
  body_block = self.class.instance_variable_get("@body_block")
135
135
  raise Glimmer::Error, 'Invalid custom widget for having no body! Please define body block!' if body_block.nil?
136
136
  @body_root = instance_exec(&body_block)
137
- execute_hooks('after_body')
138
137
  @swt_widget = @body_root.swt_widget
138
+ @swt_widget.set_data('custom_widget', self)
139
+ execute_hooks('after_body')
139
140
  end
140
-
141
+
141
142
  def can_handle_observation_request?(observation_request)
143
+ observation_request = observation_request.to_s
142
144
  result = false
143
145
  if observation_request.start_with?('on_updated_')
144
146
  property = observation_request.sub(/^on_updated_/, '')
@@ -148,6 +150,7 @@ module Glimmer
148
150
  end
149
151
 
150
152
  def handle_observation_request(observation_request, &block)
153
+ observation_request = observation_request.to_s
151
154
  if observation_request.start_with?('on_updated_')
152
155
  property = observation_request.sub(/^on_updated_/, '') # TODO look into eliminating duplication from above
153
156
  add_observer(DataBinding::Observer.proc(&block), property) if can_add_observer?(property)
@@ -157,7 +160,7 @@ module Glimmer
157
160
  end
158
161
 
159
162
  def can_add_observer?(attribute_name)
160
- has_instance_method?(attribute_name) || respond_to?("#{attribute_name}?") || @body_root.can_add_observer?(attribute_name)
163
+ has_instance_method?(attribute_name) || has_instance_method?("#{attribute_name}?") || @body_root.can_add_observer?(attribute_name)
161
164
  end
162
165
 
163
166
  def add_observer(observer, attribute_name)
@@ -169,12 +172,12 @@ module Glimmer
169
172
  end
170
173
 
171
174
  def has_attribute?(attribute_name, *args)
172
- respond_to?(attribute_setter(attribute_name), args) ||
175
+ has_instance_method?(attribute_setter(attribute_name)) ||
173
176
  @body_root.has_attribute?(attribute_name, *args)
174
177
  end
175
178
 
176
179
  def set_attribute(attribute_name, *args)
177
- if respond_to?(attribute_setter(attribute_name), args)
180
+ if has_instance_method?(attribute_setter(attribute_name))
178
181
  send(attribute_setter(attribute_name), *args)
179
182
  else
180
183
  @body_root.set_attribute(attribute_name, *args)
@@ -183,7 +186,10 @@ module Glimmer
183
186
 
184
187
  # This method ensures it has an instance method not coming from Glimmer DSL
185
188
  def has_instance_method?(method_name)
186
- respond_to?(method_name) && !method(method_name)&.source_location&.first&.include?('glimmer/dsl/engine.rb')
189
+ respond_to?(method_name) &&
190
+ !swt_widget.respond_to?(method_name) &&
191
+ !method(method_name)&.source_location&.first&.include?('glimmer/dsl/engine.rb') &&
192
+ !method(method_name)&.source_location&.first&.include?('glimmer/swt/widget_proxy.rb')
187
193
  end
188
194
 
189
195
  def get_attribute(attribute_name)
@@ -198,7 +204,6 @@ module Glimmer
198
204
  "#{attribute_name}="
199
205
  end
200
206
 
201
-
202
207
  def has_style?(style)
203
208
  (swt_style & SWT::SWTProxy[style]) == SWT::SWTProxy[style]
204
209
  end
@@ -224,14 +229,16 @@ module Glimmer
224
229
  end
225
230
  end
226
231
 
227
- def dispose
228
- body_root.dispose
229
- end
230
-
231
232
  def method_missing(method, *args, &block)
232
233
  body_root.send(method, *args, &block)
233
234
  end
234
235
 
236
+ alias local_respond_to? respond_to?
237
+ def respond_to?(method, *args, &block)
238
+ super or
239
+ body_root.respond_to?(method, *args, &block)
240
+ end
241
+
235
242
  private
236
243
 
237
244
  def execute_hooks(hook_name)
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-swt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-13 00:00:00.000000000 Z
11
+ date: 2020-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.9.4
18
+ version: 0.9.5
19
19
  name: glimmer
20
20
  type: :runtime
21
21
  prerelease: false
@@ -23,7 +23,7 @@ dependencies:
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.9.4
26
+ version: 0.9.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
@@ -285,6 +285,7 @@ files:
285
285
  - lib/glimmer/data_binding/widget_binding.rb
286
286
  - lib/glimmer/dsl/swt/async_exec_expression.rb
287
287
  - lib/glimmer/dsl/swt/bind_expression.rb
288
+ - lib/glimmer/dsl/swt/block_property_expression.rb
288
289
  - lib/glimmer/dsl/swt/color_expression.rb
289
290
  - lib/glimmer/dsl/swt/column_properties_expression.rb
290
291
  - lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb
@@ -328,10 +329,12 @@ files:
328
329
  - lib/glimmer/swt/menu_proxy.rb
329
330
  - lib/glimmer/swt/message_box_proxy.rb
330
331
  - lib/glimmer/swt/packages.rb
332
+ - lib/glimmer/swt/scrolled_composite_proxy.rb
331
333
  - lib/glimmer/swt/shell_proxy.rb
332
334
  - lib/glimmer/swt/style_constantizable.rb
333
335
  - lib/glimmer/swt/swt_proxy.rb
334
336
  - lib/glimmer/swt/tab_item_proxy.rb
337
+ - lib/glimmer/swt/table_column_proxy.rb
335
338
  - lib/glimmer/swt/table_proxy.rb
336
339
  - lib/glimmer/swt/tree_proxy.rb
337
340
  - lib/glimmer/swt/widget_listener_proxy.rb