glimmer-dsl-swt 0.2.3 → 0.4.1

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.
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