glimmer 0.7.4 → 0.8.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.
@@ -16,6 +16,8 @@ module Glimmer
16
16
  class DisplayProxy
17
17
  include_package 'org.eclipse.swt.widgets'
18
18
 
19
+ OBSERVED_MENU_ITEMS = ['about', 'preferences']
20
+
19
21
  class << self
20
22
  # Returns singleton instance
21
23
  def instance(*args)
@@ -52,6 +54,9 @@ module Glimmer
52
54
  if observation_request.start_with?('on_event_')
53
55
  constant_name = observation_request.sub(/^on_event_/, '')
54
56
  SWTProxy.has_constant?(constant_name)
57
+ elsif observation_request.start_with?('on_')
58
+ event_name = observation_request.sub(/^on_/, '')
59
+ OBSERVED_MENU_ITEMS.include?(event_name)
55
60
  else
56
61
  false
57
62
  end
@@ -61,6 +66,15 @@ module Glimmer
61
66
  if observation_request.start_with?('on_event_')
62
67
  constant_name = observation_request.sub(/^on_event_/, '')
63
68
  add_swt_event_listener(constant_name, &block)
69
+ elsif observation_request.start_with?('on_')
70
+ event_name = observation_request.sub(/^on_/, '')
71
+ if OBSERVED_MENU_ITEMS.include?(event_name)
72
+ if OS.mac?
73
+ system_menu = swt_display.getSystemMenu
74
+ menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
75
+ menu_item.addListener(SWTProxy[:Selection], &block)
76
+ end
77
+ end
64
78
  end
65
79
  end
66
80
 
@@ -79,6 +79,23 @@ module Glimmer
79
79
  super(attribute_name)
80
80
  end
81
81
  end
82
+
83
+ def can_handle_observation_request?(observation_request, super_only: false)
84
+ super_result = super(observation_request)
85
+ if observation_request.start_with?('on_') && !super_result && !super_only
86
+ return menu_item_proxy.can_handle_observation_request?(observation_request)
87
+ else
88
+ super_result
89
+ end
90
+ end
91
+
92
+ def handle_observation_request(observation_request, &block)
93
+ if can_handle_observation_request?(observation_request, super_only: true)
94
+ super
95
+ else
96
+ menu_item_proxy.handle_observation_request(observation_request, &block)
97
+ end
98
+ end
82
99
  end
83
100
  end
84
101
  end
@@ -14,7 +14,6 @@ module Glimmer
14
14
 
15
15
  WIDTH_MIN = 130
16
16
  HEIGHT_MIN = 0
17
- OBSERVED_MENU_ITEMS = ['about', 'preferences']
18
17
 
19
18
  attr_reader :opened_before
20
19
  alias opened_before? opened_before
@@ -47,7 +46,7 @@ module Glimmer
47
46
  Thread.new do
48
47
  sleep(0.25)
49
48
  async_exec do
50
- @swt_widget.setActive
49
+ @swt_widget.setActive unless @swt_widget.isDisposed
51
50
  end
52
51
  end
53
52
  end
@@ -128,30 +127,6 @@ module Glimmer
128
127
  end
129
128
  end
130
129
 
131
- def can_handle_observation_request?(observation_request)
132
- result = false
133
- if observation_request.start_with?('on_')
134
- event_name = observation_request.sub(/^on_/, '')
135
- result = OBSERVED_MENU_ITEMS.include?(event_name)
136
- end
137
- result || super
138
- end
139
-
140
- def handle_observation_request(observation_request, &block)
141
- if observation_request.start_with?('on_')
142
- event_name = observation_request.sub(/^on_/, '')
143
- if OBSERVED_MENU_ITEMS.include?(event_name)
144
- if OS.mac?
145
- system_menu = DisplayProxy.instance.swt_display.getSystemMenu
146
- menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
147
- menu_item.addListener(SWTProxy[:Selection], &block)
148
- end
149
- else
150
- super
151
- end
152
- end
153
- end
154
-
155
130
  def add_observer(observer, property_name)
156
131
  case property_name.to_s
157
132
  when 'visible?' #TODO see if you must handle non-? version and/or move elsewhere
@@ -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
@@ -3,22 +3,118 @@ require 'glimmer/swt/widget_proxy'
3
3
  module Glimmer
4
4
  module SWT
5
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
+
6
19
  # Performs depth first search for tree items matching block condition
7
- # Returns a Java TreeItem array to easily set as selection on org.eclipse.swt.Tree when needed
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
8
22
  def depth_first_search(&condition)
9
23
  found = []
10
24
  recursive_depth_first_search(swt_widget.getItems.first, found, &condition)
11
25
  found.to_java(TreeItem)
12
26
  end
27
+
28
+ # Returns all tree items including descendants
29
+ def all_tree_items
30
+ depth_first_search
31
+ end
13
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
+
14
101
  private
15
102
 
16
103
  def recursive_depth_first_search(tree_item, found, &condition)
104
+ return if tree_item.nil?
17
105
  found << tree_item if condition.nil? || condition.call(tree_item)
18
106
  tree_item.getItems.each do |child_tree_item|
19
107
  recursive_depth_first_search(child_tree_item, found, &condition)
20
108
  end
21
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
22
118
  end
23
119
  end
24
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
  }