glimmer 0.7.3 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -47,7 +47,7 @@ module Glimmer
47
47
  Thread.new do
48
48
  sleep(0.25)
49
49
  async_exec do
50
- @swt_widget.setActive
50
+ @swt_widget.setActive unless @swt_widget.isDisposed
51
51
  end
52
52
  end
53
53
  end
@@ -102,15 +102,12 @@ module Glimmer
102
102
  end
103
103
 
104
104
  def pack_same_size
105
- minimum_size = @swt_widget.getMinimumSize
106
105
  bounds = @swt_widget.getBounds
107
106
  width = @swt_widget.getBounds.width
108
107
  height = @swt_widget.getBounds.height
109
108
  x = @swt_widget.getBounds.x
110
109
  y = @swt_widget.getBounds.y
111
- @swt_widget.setMinimumSize(bounds.width, bounds.height)
112
110
  @swt_widget.pack
113
- @swt_widget.setMinimumSize(minimum_size)
114
111
  @swt_widget.setSize(width, height)
115
112
  @swt_widget.setLocation(x, y)
116
113
  end
@@ -54,6 +54,12 @@ module Glimmer
54
54
  super(attribute_name)
55
55
  end
56
56
  end
57
+
58
+ def dispose
59
+ swt_tab_item.setControl(nil)
60
+ swt_widget.dispose
61
+ swt_tab_item.dispose
62
+ end
57
63
  end
58
64
  end
59
65
  end
@@ -0,0 +1,120 @@
1
+ require 'glimmer/swt/widget_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class TreeProxy < Glimmer::SWT::WidgetProxy
6
+ include Glimmer
7
+
8
+ attr_reader :tree_editor, :tree_editor_text_proxy
9
+ attr_accessor :tree_properties
10
+
11
+ def initialize(underscored_widget_name, parent, args)
12
+ super
13
+ @tree_editor = TreeEditor.new(swt_widget)
14
+ @tree_editor.horizontalAlignment = SWTProxy[:left]
15
+ @tree_editor.grabHorizontal = true
16
+ @tree_editor.minimumHeight = 20
17
+ end
18
+
19
+ # Performs depth first search for tree items matching block condition
20
+ # If no condition block is passed, returns all tree items
21
+ # Returns a Java TreeItem array to easily set as selection on org.eclipse.swt.Tree if needed
22
+ def depth_first_search(&condition)
23
+ found = []
24
+ recursive_depth_first_search(swt_widget.getItems.first, found, &condition)
25
+ found.to_java(TreeItem)
26
+ end
27
+
28
+ # Returns all tree items including descendants
29
+ def all_tree_items
30
+ depth_first_search
31
+ end
32
+
33
+ def widget_property_listener_installers
34
+ super.merge({
35
+ Java::OrgEclipseSwtWidgets::Tree => {
36
+ selection: lambda do |observer|
37
+ on_widget_selected { |selection_event|
38
+ observer.call(@swt_widget.getSelection)
39
+ }
40
+ end
41
+ },
42
+ })
43
+ end
44
+
45
+ def edit_in_progress?
46
+ !!@edit_in_progress
47
+ end
48
+
49
+ def edit_selected_tree_item(before_write: nil, after_write: nil, after_cancel: nil)
50
+ edit_tree_item(swt_widget.getSelection.first, before_write: before_write, after_write: after_write, after_cancel: after_cancel)
51
+ end
52
+
53
+ def edit_tree_item(tree_item, before_write: nil, after_write: nil, after_cancel: nil)
54
+ return if tree_item.nil?
55
+ content {
56
+ @tree_editor_text_proxy = text {
57
+ focus true
58
+ text tree_item.getText
59
+ action_taken = false
60
+ cancel = lambda {
61
+ @tree_editor_text_proxy.swt_widget.dispose
62
+ @tree_editor_text_proxy = nil
63
+ after_cancel&.call
64
+ @edit_in_progress = false
65
+ }
66
+ action = lambda { |event|
67
+ if !action_taken && !@edit_in_progress
68
+ action_taken = true
69
+ @edit_in_progress = true
70
+ new_text = @tree_editor_text_proxy.swt_widget.getText
71
+ if new_text == tree_item.getText
72
+ cancel.call
73
+ else
74
+ before_write&.call
75
+ tree_item.setText(new_text)
76
+ model = tree_item.getData
77
+ model.send("#{tree_properties[:text]}=", new_text) # makes tree update itself, so must search for selected tree item again
78
+ edited_tree_item = depth_first_search { |ti| ti.getData == model }.first
79
+ swt_widget.showItem(edited_tree_item)
80
+ @tree_editor_text_proxy.swt_widget.dispose
81
+ @tree_editor_text_proxy = nil
82
+ after_write&.call(edited_tree_item)
83
+ @edit_in_progress = false
84
+ end
85
+ end
86
+ }
87
+ on_focus_lost(&action)
88
+ on_key_pressed { |key_event|
89
+ if key_event.keyCode == swt(:cr)
90
+ action.call(key_event)
91
+ elsif key_event.keyCode == swt(:esc)
92
+ cancel.call
93
+ end
94
+ }
95
+ }
96
+ @tree_editor_text_proxy.swt_widget.selectAll
97
+ }
98
+ @tree_editor.setEditor(@tree_editor_text_proxy.swt_widget, tree_item);
99
+ end
100
+
101
+ private
102
+
103
+ def recursive_depth_first_search(tree_item, found, &condition)
104
+ return if tree_item.nil?
105
+ found << tree_item if condition.nil? || condition.call(tree_item)
106
+ tree_item.getItems.each do |child_tree_item|
107
+ recursive_depth_first_search(child_tree_item, found, &condition)
108
+ end
109
+ end
110
+
111
+ def property_type_converters
112
+ super.merge({
113
+ selection: lambda do |value|
114
+ depth_first_search {|ti| ti.getData == value}
115
+ end,
116
+ })
117
+ end
118
+ end
119
+ end
120
+ end
@@ -5,12 +5,29 @@ module Glimmer
5
5
  # Follows the Proxy Design Pattern
6
6
  class WidgetListenerProxy
7
7
 
8
- attr_reader :swt_listener
8
+ attr_reader :swt_widget, :swt_listener, :widget_add_listener_method, :swt_listener_class, :swt_listener_method, :event_type, :swt_constant
9
9
 
10
- # TODO capture its widget and support unregistering
11
-
12
- def initialize(swt_listener)
10
+ def initialize(swt_widget:, swt_listener:, widget_add_listener_method: nil, swt_listener_class: nil, swt_listener_method: nil, event_type: nil, swt_constant: nil)
11
+ @swt_widget = swt_widget
13
12
  @swt_listener = swt_listener
13
+ @widget_add_listener_method = widget_add_listener_method
14
+ @swt_listener_class = swt_listener_class
15
+ @swt_listener_method = swt_listener_method
16
+ @event_type = event_type
17
+ @swt_constant = swt_constant
18
+ end
19
+
20
+ def widget_remove_listener_method
21
+ @widget_add_listener_method.sub('add', 'remove')
22
+ end
23
+
24
+ def unregister
25
+ # TODO consider renaming to deregister (and in Observer too)
26
+ if @event_type
27
+ @swt_widget.removeListener(@event_type, @swt_listener)
28
+ else
29
+ @swt_widget.send(widget_remove_listener_method, @swt_listener)
30
+ end
14
31
  end
15
32
  end
16
33
  end
@@ -5,6 +5,8 @@ require 'glimmer/swt/font_proxy'
5
5
  require 'glimmer/swt/swt_proxy'
6
6
  require 'glimmer/data_binding/observable_widget'
7
7
 
8
+ # TODO refactor to make file smaller and extract sub-widget-proxies out of this
9
+
8
10
  module Glimmer
9
11
  module SWT
10
12
  # Proxy for SWT Widget objects
@@ -23,6 +25,7 @@ module Glimmer
23
25
  DEFAULT_STYLES = {
24
26
  "text" => [:border],
25
27
  "table" => [:border],
28
+ "tree" => [:virtual, :border, :h_scroll, :v_scroll],
26
29
  "spinner" => [:border],
27
30
  "styled_text" => [:border],
28
31
  "list" => [:border, :v_scroll],
@@ -31,17 +34,17 @@ module Glimmer
31
34
  }
32
35
 
33
36
  DEFAULT_INITIALIZERS = {
34
- "composite" => proc do |composite|
37
+ "composite" => lambda do |composite|
35
38
  composite.setLayout(GridLayout.new)
36
39
  end,
37
- "table" => proc do |table|
40
+ "table" => lambda do |table|
38
41
  table.setHeaderVisible(true)
39
42
  table.setLinesVisible(true)
40
43
  end,
41
- "table_column" => proc do |table_column|
44
+ "table_column" => lambda do |table_column|
42
45
  table_column.setWidth(80)
43
46
  end,
44
- "group" => proc do |group|
47
+ "group" => lambda do |group|
45
48
  group.setLayout(GridLayout.new)
46
49
  end,
47
50
  }
@@ -119,7 +122,7 @@ module Glimmer
119
122
  def widget_property_listener_installers
120
123
  @swt_widget_property_listener_installers ||= {
121
124
  Java::OrgEclipseSwtWidgets::Control => {
122
- :focus => proc do |observer|
125
+ :focus => lambda do |observer|
123
126
  on_focus_gained { |focus_event|
124
127
  observer.call(true)
125
128
  }
@@ -129,12 +132,12 @@ module Glimmer
129
132
  end,
130
133
  },
131
134
  Java::OrgEclipseSwtWidgets::Text => {
132
- :text => proc do |observer|
135
+ :text => lambda do |observer|
133
136
  on_modify_text { |modify_event|
134
137
  observer.call(@swt_widget.getText)
135
138
  }
136
139
  end,
137
- :caret_position => proc do |observer|
140
+ :caret_position => lambda do |observer|
138
141
  on_event_keydown { |event|
139
142
  observer.call(@swt_widget.getCaretPosition)
140
143
  }
@@ -148,7 +151,21 @@ module Glimmer
148
151
  observer.call(@swt_widget.getCaretPosition)
149
152
  }
150
153
  end,
151
- :selection_count => proc do |observer|
154
+ :selection => lambda do |observer|
155
+ on_event_keydown { |event|
156
+ observer.call(@swt_widget.getSelection)
157
+ }
158
+ on_event_keyup { |event|
159
+ observer.call(@swt_widget.getSelection)
160
+ }
161
+ on_event_mousedown { |event|
162
+ observer.call(@swt_widget.getSelection)
163
+ }
164
+ on_event_mouseup { |event|
165
+ observer.call(@swt_widget.getSelection)
166
+ }
167
+ end,
168
+ :selection_count => lambda do |observer|
152
169
  on_event_keydown { |event|
153
170
  observer.call(@swt_widget.getSelectionCount)
154
171
  }
@@ -162,7 +179,7 @@ module Glimmer
162
179
  observer.call(@swt_widget.getSelectionCount)
163
180
  }
164
181
  end,
165
- :top_index => proc do |observer|
182
+ :top_index => lambda do |observer|
166
183
  @last_top_index = @swt_widget.getTopIndex
167
184
  on_paint_control { |event|
168
185
  if @swt_widget.getTopIndex != @last_top_index
@@ -173,33 +190,33 @@ module Glimmer
173
190
  end,
174
191
  },
175
192
  Java::OrgEclipseSwtCustom::StyledText => {
176
- :text => proc do |observer|
193
+ :text => lambda do |observer|
177
194
  on_modify_text { |modify_event|
178
195
  observer.call(@swt_widget.getText)
179
196
  }
180
197
  end,
181
198
  },
182
199
  Java::OrgEclipseSwtWidgets::Button => {
183
- :selection => proc do |observer|
200
+ :selection => lambda do |observer|
184
201
  on_widget_selected { |selection_event|
185
202
  observer.call(@swt_widget.getSelection)
186
203
  }
187
204
  end
188
205
  },
189
206
  Java::OrgEclipseSwtWidgets::MenuItem => {
190
- :selection => proc do |observer|
207
+ :selection => lambda do |observer|
191
208
  on_widget_selected { |selection_event|
192
209
  observer.call(@swt_widget.getSelection)
193
210
  }
194
211
  end
195
212
  },
196
213
  Java::OrgEclipseSwtWidgets::Spinner => {
197
- :selection => proc do |observer|
214
+ :selection => lambda do |observer|
198
215
  on_widget_selected { |selection_event|
199
216
  observer.call(@swt_widget.getSelection)
200
217
  }
201
218
  end
202
- }
219
+ },
203
220
  }
204
221
  end
205
222
 
@@ -321,10 +338,12 @@ module Glimmer
321
338
  end
322
339
 
323
340
  def add_listener(underscored_listener_name, &block)
324
- widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
325
- listener = listener_class.new(listener_method => block)
341
+ widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
342
+ widget_listener_proxy = nil
343
+ safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
344
+ listener = listener_class.new(listener_method => safe_block)
326
345
  @swt_widget.send(widget_add_listener_method, listener)
327
- WidgetListenerProxy.new(listener)
346
+ 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)
328
347
  end
329
348
 
330
349
  # Looks through SWT class add***Listener methods till it finds one for which
@@ -375,8 +394,10 @@ module Glimmer
375
394
 
376
395
  def add_swt_event_listener(swt_constant, &block)
377
396
  event_type = SWTProxy[swt_constant]
378
- @swt_widget.addListener(event_type, &block)
379
- WidgetListenerProxy.new(@swt_widget.getListeners(event_type).last)
397
+ widget_listener_proxy = nil
398
+ safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
399
+ @swt_widget.addListener(event_type, &safe_block)
400
+ 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)
380
401
  end
381
402
 
382
403
  def widget_custom_attribute_mapping
@@ -409,7 +430,7 @@ module Glimmer
409
430
  end
410
431
 
411
432
  def property_type_converters
412
- color_converter = proc do |value|
433
+ color_converter = lambda do |value|
413
434
  if value.is_a?(Symbol) || value.is_a?(String)
414
435
  ColorProxy.new(value).swt_color
415
436
  else
@@ -419,7 +440,7 @@ module Glimmer
419
440
  # TODO consider detecting type on widget method and automatically invoking right converter (e.g. :to_s for String, :to_i for Integer)
420
441
  @property_type_converters ||= {
421
442
  :background => color_converter,
422
- :background_image => proc do |value|
443
+ :background_image => lambda do |value|
423
444
  if value.is_a?(String)
424
445
  if value.start_with?('uri:classloader')
425
446
  value = value.sub(/^uri\:classloader\:\//, '')
@@ -440,7 +461,7 @@ module Glimmer
440
461
  end
441
462
  end,
442
463
  :foreground => color_converter,
443
- :font => proc do |value|
464
+ :font => lambda do |value|
444
465
  if value.is_a?(Hash)
445
466
  font_properties = value
446
467
  FontProxy.new(self, font_properties).swt_font
@@ -448,17 +469,17 @@ module Glimmer
448
469
  value
449
470
  end
450
471
  end,
451
- :items => proc do |value|
472
+ :items => lambda do |value|
452
473
  value.to_java :string
453
474
  end,
454
- :text => proc do |value|
475
+ :text => lambda do |value|
455
476
  if swt_widget.is_a?(Browser)
456
477
  value.to_s
457
478
  else
458
479
  value.to_s
459
480
  end
460
481
  end,
461
- :visible => proc do |value|
482
+ :visible => lambda do |value|
462
483
  !!value
463
484
  end,
464
485
  }
@@ -83,7 +83,7 @@ module Glimmer
83
83
  else
84
84
  new_options = new_options.reduce({}) {|new_options_hash, new_option| new_options_hash.merge(new_option => nil)}
85
85
  @options = options.merge(new_options)
86
- def_option_attr_readers(new_options)
86
+ def_option_attr_accessors(new_options)
87
87
  end
88
88
  end
89
89
 
@@ -91,15 +91,18 @@ module Glimmer
91
91
  new_option = new_option.to_s.to_sym
92
92
  new_options = {new_option => new_option_default}
93
93
  @options = options.merge(new_options)
94
- def_option_attr_readers(new_options)
94
+ def_option_attr_accessors(new_options)
95
95
  end
96
96
 
97
- def def_option_attr_readers(new_options)
97
+ def def_option_attr_accessors(new_options)
98
98
  new_options.each do |option, default|
99
99
  class_eval <<-end_eval, __FILE__, __LINE__
100
100
  def #{option}
101
101
  options[:#{option}]
102
102
  end
103
+ def #{option}=(option_value)
104
+ self.options[:#{option}] = option_value
105
+ end
103
106
  end_eval
104
107
  end
105
108
  end
@@ -224,6 +227,10 @@ module Glimmer
224
227
  def dispose
225
228
  body_root.dispose
226
229
  end
230
+
231
+ def method_missing(method, *args, &block)
232
+ body_root.send(method, *args, &block)
233
+ end
227
234
 
228
235
  private
229
236
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-16 00:00:00.000000000 Z
11
+ date: 2020-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -150,34 +150,6 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: 3.5.0
153
- - !ruby/object:Gem::Dependency
154
- requirement: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - '='
157
- - !ruby/object:Gem::Version
158
- version: 0.8.5
159
- name: coveralls
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - '='
165
- - !ruby/object:Gem::Version
166
- version: 0.8.5
167
- - !ruby/object:Gem::Dependency
168
- requirement: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
171
- - !ruby/object:Gem::Version
172
- version: 0.10.0
173
- name: simplecov
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: 0.10.0
181
153
  - !ruby/object:Gem::Dependency
182
154
  requirement: !ruby/object:Gem::Requirement
183
155
  requirements:
@@ -192,9 +164,7 @@ dependencies:
192
164
  - - "~>"
193
165
  - !ruby/object:Gem::Version
194
166
  version: 0.8.1
195
- description: JRuby Desktop UI DSL + Data-Binding native-UI cross-platform library
196
- that enables productive and efficient authoring of desktop user-interfaces using
197
- the robust Eclipse SWT library
167
+ description: Desktop Development Library for Ruby
198
168
  email: andy.am@gmail.com
199
169
  executables:
200
170
  - glimmer
@@ -202,10 +172,10 @@ executables:
202
172
  extensions: []
203
173
  extra_rdoc_files:
204
174
  - LICENSE.txt
205
- - README.markdown
175
+ - README.md
206
176
  files:
207
177
  - LICENSE.txt
208
- - README.markdown
178
+ - README.md
209
179
  - RUBY_VERSION
210
180
  - VERSION
211
181
  - bin/girb
@@ -246,6 +216,7 @@ files:
246
216
  - lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb
247
217
  - lib/glimmer/dsl/swt/custom_widget_expression.rb
248
218
  - lib/glimmer/dsl/swt/data_binding_expression.rb
219
+ - lib/glimmer/dsl/swt/dialog_expression.rb
249
220
  - lib/glimmer/dsl/swt/display_expression.rb
250
221
  - lib/glimmer/dsl/swt/dsl.rb
251
222
  - lib/glimmer/dsl/swt/exec_expression.rb
@@ -292,6 +263,7 @@ files:
292
263
  - lib/glimmer/swt/shell_proxy.rb
293
264
  - lib/glimmer/swt/swt_proxy.rb
294
265
  - lib/glimmer/swt/tab_item_proxy.rb
266
+ - lib/glimmer/swt/tree_proxy.rb
295
267
  - lib/glimmer/swt/widget_listener_proxy.rb
296
268
  - lib/glimmer/swt/widget_proxy.rb
297
269
  - lib/glimmer/ui/custom_shell.rb
@@ -327,5 +299,5 @@ requirements: []
327
299
  rubygems_version: 3.0.6
328
300
  signing_key:
329
301
  specification_version: 4
330
- summary: Desktop development library for Ruby
302
+ summary: Desktop Development Library for Ruby
331
303
  test_files: []