glimmer-dsl-swt 0.2.2 → 0.4.0

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: 564118c89658344e48e07e795447c78db4b4d61fd6e48c48ba0fae9e48e4cc2c
4
- data.tar.gz: a36895cc1374171c078546a986cdbfb6b677d0547d20099c42d631be9d4865bd
3
+ metadata.gz: 8dda5c40a0a65d36e4615d40f3456b80d2d990121ed63fa9f447a1d110af3a93
4
+ data.tar.gz: 4bcdc319eda7a7c3542e0d1b8caeda9329726623ae20b87236be0690dbd263c4
5
5
  SHA512:
6
- metadata.gz: 3f1edda00261bc1fa2f4d8459f08378b0924d440c6e0b7ebd42281c0d689a66870089da127f8ef45a18110808a201852d71481582f8712136151863cff848c88
7
- data.tar.gz: 75742ed4193c5139a2a800787211342e19cee44bd0aa34abe794db8b8c37a2ccfc5300de35b31de95f5fa5826e23a8207db8d6bd097512eb0c1b256de4ffb277
6
+ metadata.gz: 12f2085517a77a30197dd499887e0ca55756b2a0d0ec26275be60b38d6b266722c6574256e3f9830e145763eec7cb74543b0df37932d9c751b0497c4ea277a38
7
+ data.tar.gz: bb174b6427e2814b02f4509dc4b31698ca2e28c460f2d18749c2505ec9cb0635641275a5300db0fbb7821d1fdb0cdc8474e9220d2718201073076d567b2865d0
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.2 (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.0 (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.2
1
+ 0.4.0
@@ -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
  ]
@@ -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'
@@ -7,6 +7,12 @@ module Glimmer
7
7
  class << self
8
8
  attr_accessor :javapackager_extra_args
9
9
 
10
+ def clean
11
+ require 'fileutils'
12
+ FileUtils.rm_rf('dist')
13
+ FileUtils.rm_rf('packages')
14
+ end
15
+
10
16
  def config
11
17
  project_name = File.basename(File.expand_path('.'))
12
18
  if !File.exists?('config/warble.rb')
@@ -15,7 +21,7 @@ module Glimmer
15
21
  system('warble config')
16
22
  new_config = File.read('config/warble.rb').split("\n").inject('') do |output, line|
17
23
  if line.include?('config.dirs =')
18
- line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos)')
24
+ line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos vendor)')
19
25
  end
20
26
  if line.include?('config.includes =')
21
27
  line = line.sub('# ', '').sub(/=[^=\n]+$/, "= FileList['LICENSE.txt', 'VERSION']")
@@ -4,6 +4,11 @@ require_relative 'package'
4
4
 
5
5
  namespace :glimmer do
6
6
  namespace :package do
7
+ desc 'Clean by removing "dist" and "packages" directories'
8
+ task :clean do
9
+ Glimmer::Package.clean
10
+ end
11
+
7
12
  desc 'Generate JAR config file'
8
13
  task :config do
9
14
  Glimmer::Package.config
@@ -179,6 +179,7 @@ class Scaffold
179
179
  end
180
180
 
181
181
  def custom_shell_gem(custom_shell_name, namespace)
182
+ return puts('Namespace is required! Usage: glimmer scaffold:custom_shell_gem[custom_shell_name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
182
183
  gem_name = "glimmer-cs-#{compact_name(custom_shell_name)}"
183
184
  gem_summary = "#{human_name(custom_shell_name)} - Glimmer Custom Shell"
184
185
  if namespace
@@ -218,6 +219,7 @@ class Scaffold
218
219
  end
219
220
 
220
221
  def custom_widget_gem(custom_widget_name, namespace)
222
+ return puts('Namespace is required! Usage: glimmer scaffold:custom_widget_gem[custom_widget_name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
221
223
  gem_name = "glimmer-cw-#{compact_name(custom_widget_name)}"
222
224
  gem_summary = "#{human_name(custom_widget_name)} - Glimmer Custom Widget"
223
225
  if namespace
@@ -483,12 +485,10 @@ class Scaffold
483
485
  custom_shell_file_content += <<-MULTI_LINE_STRING
484
486
 
485
487
  def display_about_dialog
486
- message_box = MessageBox.new(swt_widget)
487
- message_box.setText("About")
488
- message = "#{human_name(namespace)} - #{human_name(custom_shell_name)} \#{VERSION}\n\n"
489
- message += LICENSE
490
- message_box.setMessage(message)
491
- 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
492
492
  end
493
493
 
494
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,28 @@ 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
39
  def dispose
39
40
  @swt_display.dispose
40
41
  end
41
42
 
42
- # Executes code block asynchronously with respect to SWT UI thread
43
- def async_exec(&block)
44
- @swt_display.asyncExec(&block)
43
+ def method_missing(method, *args, &block)
44
+ swt_display.send(method, *args, &block)
45
+ rescue => e
46
+ Glimmer::Config.logger&.debug "Neither DisplayProxy nor #{swt_display.class.name} can handle the method ##{method}"
47
+ super
45
48
  end
46
-
47
- # Executes code block synchronously with respect to SWT UI thread
48
- def sync_exec(&block)
49
- @swt_display.syncExec(&block)
49
+
50
+ def respond_to?(method, *args, &block)
51
+ super || swt_display.respond_to?(method, *args, &block)
50
52
  end
51
53
 
52
54
  def can_handle_observation_request?(observation_request)
53
55
  observation_request = observation_request.to_s
54
- if observation_request.start_with?('on_event_')
55
- constant_name = observation_request.sub(/^on_event_/, '')
56
+ if observation_request.start_with?('on_swt_')
57
+ constant_name = observation_request.sub(/^on_swt_/, '')
56
58
  SWTProxy.has_constant?(constant_name)
57
59
  elsif observation_request.start_with?('on_')
58
60
  event_name = observation_request.sub(/^on_/, '')
@@ -63,8 +65,8 @@ module Glimmer
63
65
  end
64
66
 
65
67
  def handle_observation_request(observation_request, &block)
66
- if observation_request.start_with?('on_event_')
67
- constant_name = observation_request.sub(/^on_event_/, '')
68
+ if observation_request.start_with?('on_swt_')
69
+ constant_name = observation_request.sub(/^on_swt_/, '')
68
70
  add_swt_event_listener(constant_name, &block)
69
71
  elsif observation_request.start_with?('on_')
70
72
  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)
@@ -145,6 +152,16 @@ module Glimmer
145
152
  observer.call(false)
146
153
  }
147
154
  end,
155
+ :selection => lambda do |observer|
156
+ on_widget_selected { |selection_event|
157
+ observer.call(@swt_widget.getSelection)
158
+ } if can_handle_observation_request?(:on_widget_selected)
159
+ end,
160
+ :text => lambda do |observer|
161
+ on_modify_text { |modify_event|
162
+ observer.call(@swt_widget.getText)
163
+ } if can_handle_observation_request?(:on_modify_text)
164
+ end,
148
165
  },
149
166
  Java::OrgEclipseSwtWidgets::Combo => {
150
167
  :text => lambda do |observer|
@@ -160,44 +177,44 @@ module Glimmer
160
177
  }
161
178
  end,
162
179
  :caret_position => lambda do |observer|
163
- on_event_keydown { |event|
180
+ on_swt_keydown { |event|
164
181
  observer.call(@swt_widget.getCaretPosition)
165
182
  }
166
- on_event_keyup { |event|
183
+ on_swt_keyup { |event|
167
184
  observer.call(@swt_widget.getCaretPosition)
168
185
  }
169
- on_event_mousedown { |event|
186
+ on_swt_mousedown { |event|
170
187
  observer.call(@swt_widget.getCaretPosition)
171
188
  }
172
- on_event_mouseup { |event|
189
+ on_swt_mouseup { |event|
173
190
  observer.call(@swt_widget.getCaretPosition)
174
191
  }
175
192
  end,
176
193
  :selection => lambda do |observer|
177
- on_event_keydown { |event|
194
+ on_swt_keydown { |event|
178
195
  observer.call(@swt_widget.getSelection)
179
196
  }
180
- on_event_keyup { |event|
197
+ on_swt_keyup { |event|
181
198
  observer.call(@swt_widget.getSelection)
182
199
  }
183
- on_event_mousedown { |event|
200
+ on_swt_mousedown { |event|
184
201
  observer.call(@swt_widget.getSelection)
185
202
  }
186
- on_event_mouseup { |event|
203
+ on_swt_mouseup { |event|
187
204
  observer.call(@swt_widget.getSelection)
188
205
  }
189
206
  end,
190
207
  :selection_count => lambda do |observer|
191
- on_event_keydown { |event|
208
+ on_swt_keydown { |event|
192
209
  observer.call(@swt_widget.getSelectionCount)
193
210
  }
194
- on_event_keyup { |event|
211
+ on_swt_keyup { |event|
195
212
  observer.call(@swt_widget.getSelectionCount)
196
213
  }
197
- on_event_mousedown { |event|
214
+ on_swt_mousedown { |event|
198
215
  observer.call(@swt_widget.getSelectionCount)
199
216
  }
200
- on_event_mouseup { |event|
217
+ on_swt_mouseup { |event|
201
218
  observer.call(@swt_widget.getSelectionCount)
202
219
  }
203
220
  end,
@@ -255,12 +272,12 @@ module Glimmer
255
272
  return nil
256
273
  end
257
274
  swt_widget_class
258
- rescue NameError => e
259
- Glimmer::Config.logger&.debug e.message
275
+ rescue SyntaxError, NameError => e
276
+ Glimmer::Config.logger&.debug e.full_message
260
277
  # Glimmer::Config.logger&.debug("#{e.message}\n#{e.backtrace.join("\n")}")
261
278
  nil
262
279
  rescue => e
263
- Glimmer::Config.logger&.debug e.message
280
+ Glimmer::Config.logger&.debug e.full_message
264
281
  # Glimmer::Config.logger&.debug("#{e.message}\n#{e.backtrace.join("\n")}")
265
282
  nil
266
283
  end
@@ -296,9 +313,7 @@ module Glimmer
296
313
  def add_observer(observer, property_name)
297
314
  property_listener_installers = @swt_widget.class.ancestors.map {|ancestor| widget_property_listener_installers[ancestor]}.compact
298
315
  widget_listener_installers = property_listener_installers.map{|installer| installer[property_name.to_s.to_sym]}.compact if !property_listener_installers.empty?
299
- widget_listener_installers.to_a.each do |widget_listener_installer|
300
- widget_listener_installer.call(observer)
301
- end
316
+ widget_listener_installers.to_a.first&.call(observer)
302
317
  end
303
318
 
304
319
  def remove_observer(observer, property_name)
@@ -324,8 +339,8 @@ module Glimmer
324
339
 
325
340
  def can_handle_observation_request?(observation_request)
326
341
  observation_request = observation_request.to_s
327
- if observation_request.start_with?('on_event_')
328
- constant_name = observation_request.sub(/^on_event_/, '')
342
+ if observation_request.start_with?('on_swt_')
343
+ constant_name = observation_request.sub(/^on_swt_/, '')
329
344
  SWTProxy.has_constant?(constant_name)
330
345
  elsif observation_request.start_with?('on_')
331
346
  event = observation_request.sub(/^on_/, '')
@@ -343,6 +358,9 @@ module Glimmer
343
358
  @drag_source_proxy = nil
344
359
  end
345
360
  end
361
+ rescue => e
362
+ Glimmer::Config.logger&.debug(e.full_message)
363
+ false
346
364
  end
347
365
 
348
366
  def can_handle_drop_observation_request?(observation_request)
@@ -358,8 +376,8 @@ module Glimmer
358
376
  end
359
377
 
360
378
  def handle_observation_request(observation_request, &block)
361
- if observation_request.start_with?('on_event_')
362
- constant_name = observation_request.sub(/^on_event_/, '')
379
+ if observation_request.start_with?('on_swt_')
380
+ constant_name = observation_request.sub(/^on_swt_/, '')
363
381
  add_swt_event_listener(constant_name, &block)
364
382
  elsif observation_request.start_with?('on_')
365
383
  event = observation_request.sub(/^on_/, '')
@@ -378,6 +396,17 @@ module Glimmer
378
396
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::WidgetExpression.new, &block)
379
397
  end
380
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
+
381
410
  private
382
411
 
383
412
  def style(underscored_widget_name, styles)
@@ -423,7 +452,7 @@ module Glimmer
423
452
  def add_listener(underscored_listener_name, &block)
424
453
  widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
425
454
  widget_listener_proxy = nil
426
- safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
455
+ safe_block = lambda { |*args| block.call(*args) unless @swt_widget.isDisposed }
427
456
  listener = listener_class.new(listener_method => safe_block)
428
457
  @swt_widget.send(widget_add_listener_method, listener)
429
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)
@@ -465,9 +494,9 @@ module Glimmer
465
494
  listener_class.define_method('initialize') do |event_method_block_mapping|
466
495
  @event_method_block_mapping = event_method_block_mapping
467
496
  end
468
- listener_type.getMethods.each do |event_method|
469
- listener_class.define_method(event_method.getName) do |event|
470
- @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)
471
500
  end
472
501
  end
473
502
  end
@@ -478,7 +507,7 @@ module Glimmer
478
507
  def add_swt_event_listener(swt_constant, &block)
479
508
  event_type = SWTProxy[swt_constant]
480
509
  widget_listener_proxy = nil
481
- safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
510
+ safe_block = lambda { |*args| block.call(*args) unless @swt_widget.isDisposed }
482
511
  @swt_widget.addListener(event_type, &safe_block)
483
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)
484
513
  end
@@ -565,7 +594,7 @@ module Glimmer
565
594
  end
566
595
  image_data = ImageData.new(value)
567
596
  # TODO in the future, look into unregistering this listener when no longer needed
568
- on_event_Resize do |resize_event|
597
+ on_swt_Resize do |resize_event|
569
598
  new_image_data = image_data.scaledTo(@swt_widget.getSize.x, @swt_widget.getSize.y)
570
599
  @swt_widget.getBackgroundImage&.dispose
571
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.2
4
+ version: 0.4.0
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-11 00:00:00.000000000 Z
11
+ date: 2020-07-20 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.3
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.3
26
+ version: 0.9.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
@@ -256,7 +256,7 @@ dependencies:
256
256
  - - "~>"
257
257
  - !ruby/object:Gem::Version
258
258
  version: 0.7.0
259
- description: Glimmer DSL for SWT (Desktop GUI)
259
+ description: Glimmer DSL for SWT (Desktop GUI) - JRuby on SWT
260
260
  email: andy.am@gmail.com
261
261
  executables:
262
262
  - glimmer
@@ -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