glimmer 0.4.8 → 0.4.9

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.
@@ -14,7 +14,7 @@ module Glimmer
14
14
  include_package 'org.eclipse.swt.graphics'
15
15
  include_package 'org.eclipse.swt.browser'
16
16
 
17
- include Glimmer
17
+ include Glimmer # TODO consider removing when no longer needed
18
18
  include Parent
19
19
 
20
20
  attr_reader :widget
@@ -45,21 +45,41 @@ module Glimmer
45
45
  @@default_initializers[underscored_widget_name].call(@widget) if @@default_initializers[underscored_widget_name]
46
46
  end
47
47
 
48
- def has_style?(swt_style)
49
- pd(pd(@widget.getStyle) & swt_style) == pd(swt_style)
48
+ def widget_custom_attribute_mapping
49
+ @widget_custom_attribute_mapping ||= {
50
+ 'focus' => {
51
+ getter: {name: 'isFocusControl'},
52
+ setter: {name: 'setFocus', invoker: lambda { |widget, args| widget.setFocus if args.first }},
53
+ }
54
+ }
50
55
  end
51
56
 
52
57
  def has_attribute?(attribute_name, *args)
53
- @widget.respond_to?(attribute_setter(attribute_name), args)
58
+ widget_custom_attribute = widget_custom_attribute_mapping[attribute_name.to_s]
59
+ if widget_custom_attribute
60
+ @widget.respond_to?(widget_custom_attribute[:setter][:name])
61
+ else
62
+ @widget.respond_to?(attribute_setter(attribute_name), args)
63
+ end
54
64
  end
55
65
 
56
66
  def set_attribute(attribute_name, *args)
57
- apply_property_type_converters(attribute_name, args)
58
- @widget.send(attribute_setter(attribute_name), *args)
67
+ widget_custom_attribute = widget_custom_attribute_mapping[attribute_name.to_s]
68
+ if widget_custom_attribute
69
+ widget_custom_attribute[:setter][:invoker].call(@widget, args)
70
+ else
71
+ apply_property_type_converters(attribute_name, args)
72
+ @widget.send(attribute_setter(attribute_name), *args)
73
+ end
59
74
  end
60
75
 
61
76
  def get_attribute(attribute_name)
62
- @widget.send(attribute_getter(attribute_name))
77
+ widget_custom_attribute = widget_custom_attribute_mapping[attribute_name.to_s]
78
+ if widget_custom_attribute
79
+ @widget.send(widget_custom_attribute[:getter][:name])
80
+ else
81
+ @widget.send(attribute_getter(attribute_name))
82
+ end
63
83
  end
64
84
 
65
85
  def property_type_converters
@@ -75,6 +95,20 @@ module Glimmer
75
95
  :items => Proc.new { |value| value.to_java :string},
76
96
  :visible => Proc.new { |value| !!value},
77
97
  :background => color_converter,
98
+ :background_image => Proc.new do |value|
99
+ if value.is_a?(String)
100
+ image_data = ImageData.new(value)
101
+ # TODO in the future, look into unregistering this listener when no longer needed
102
+ on_event_Resize do |resize_event|
103
+ new_image_data = image_data.scaledTo(widget.getSize.x, widget.getSize.y)
104
+ widget.getBackgroundImage&.dispose
105
+ widget.setBackgroundImage(Image.new(widget.getDisplay, new_image_data))
106
+ end
107
+ Image.new(widget.getDisplay, image_data)
108
+ else
109
+ value
110
+ end
111
+ end,
78
112
  :foreground => color_converter,
79
113
  :font => Proc.new do |value|
80
114
  if value.is_a?(Hash)
@@ -89,6 +123,18 @@ module Glimmer
89
123
 
90
124
  def widget_property_listener_installers
91
125
  @widget_property_listener_installers ||= {
126
+ Java::OrgEclipseSwtWidgets::Control => {
127
+ :focus => Proc.new do |observer|
128
+ add_contents(self) {
129
+ on_focus_gained { |focus_event|
130
+ observer.call(true)
131
+ }
132
+ on_focus_lost { |focus_event|
133
+ observer.call(false)
134
+ }
135
+ }
136
+ end,
137
+ },
92
138
  Java::OrgEclipseSwtWidgets::Text => {
93
139
  :text => Proc.new do |observer|
94
140
  add_contents(self) {
@@ -153,21 +199,11 @@ module Glimmer
153
199
  nil
154
200
  end
155
201
 
156
- def widget_listener_exists?(underscored_listener_name)
157
- listener_method_name = underscored_listener_name.listener_method_name(:lower)
158
- @widget.getClass.getMethods.each do |widget_method|
159
- if widget_method.getName.match(/add.*Listener/)
160
- widget_method.getParameterTypes.each do |listener_type|
161
- listener_type.getMethods.each do |listener_method|
162
- if (listener_method.getName == listener_method_name)
163
- return true
164
- end
165
- end
166
- end
167
- end
168
- end
169
- return false
170
- end
202
+ # TODO refactor following methods to eliminate duplication
203
+ # perhaps consider relying on raising an exception to avoid checking first
204
+ # unless that gives obscure SWT errors
205
+ # Otherwise, consider caching results from can_add_lsitener and using them in
206
+ # add_listener knowing it will be called for sure afterwards
171
207
 
172
208
  def can_add_listener?(underscored_listener_name)
173
209
  listener_method_name = underscored_listener_name.camelcase(:lower)
@@ -213,15 +249,15 @@ module Glimmer
213
249
  end
214
250
 
215
251
  def process_block(block)
216
- block.call(@widget)
252
+ block.call(self)
217
253
  end
218
254
 
219
255
  def async_exec(&block)
220
- @widget.getDisplay.asyncExec(GRunnable.new(&block))
256
+ GDisplay.instance.async_exec(&block)
221
257
  end
222
258
 
223
259
  def sync_exec(&block)
224
- @widget.getDisplay.syncExec(GRunnable.new(&block))
260
+ GDisplay.instance.sync_exec(&block)
225
261
  end
226
262
 
227
263
  def has_style?(style)
@@ -232,16 +268,63 @@ module Glimmer
232
268
  @widget.dispose
233
269
  end
234
270
 
271
+ # TODO Consider renaming these methods as they are mainly used for data-binding
272
+
273
+ def can_add_observer?(property_name)
274
+ @widget.class.ancestors.map {|ancestor| widget_property_listener_installers[ancestor]}.compact.map(&:keys).flatten.map(&:to_s).include?(property_name.to_s)
275
+ end
276
+
235
277
  def add_observer(observer, property_name)
236
- property_listener_installers = widget_property_listener_installers[widget.class]
237
- widget_listener_installer = property_listener_installers[property_name.to_s.to_sym] if property_listener_installers
238
- widget_listener_installer.call(observer) if widget_listener_installer
278
+ property_listener_installers = @widget.class.ancestors.map {|ancestor| widget_property_listener_installers[ancestor]}.compact
279
+ widget_listener_installers = property_listener_installers.map{|installer| installer[property_name.to_s.to_sym]}.compact if !property_listener_installers.empty?
280
+ widget_listener_installers.each do |widget_listener_installer|
281
+ widget_listener_installer.call(observer)
282
+ end
239
283
  end
240
284
 
241
285
  def remove_observer(observer, property_name)
242
286
  # TODO consider implementing if remove_observer is needed (consumers can remove listener via SWT API)
243
287
  end
244
288
 
289
+ # TODO eliminate duplication in the following methods perhaps by relying on exceptions
290
+
291
+ def can_handle_observation_request?(observation_request)
292
+ observation_request = observation_request.to_s
293
+ if observation_request.start_with?('on_event_')
294
+ constant_name = observation_request.sub(/^on_event_/, '')
295
+ GSWT.has_constant?(constant_name)
296
+ elsif observation_request.start_with?('on_')
297
+ event = observation_request.sub(/^on_/, '')
298
+ can_add_listener?(event)
299
+ else
300
+ false
301
+ end
302
+ end
303
+
304
+ def handle_observation_request(observation_request, &block)
305
+ if observation_request.start_with?('on_event_')
306
+ constant_name = observation_request.sub(/^on_event_/, '')
307
+ @widget.addListener(GSWT[constant_name], &block)
308
+ elsif observation_request.start_with?('on_')
309
+ event = observation_request.sub(/^on_/, '')
310
+ add_listener(event, &block)
311
+ end
312
+ nil
313
+ end
314
+
315
+ def method_missing(method, *args, &block)
316
+ method_name = method.to_s
317
+ if can_handle_observation_request?(method_name)
318
+ handle_observation_request(method_name, &block)
319
+ else
320
+ super
321
+ end
322
+ end
323
+
324
+ def add_content(&block)
325
+ Glimmer.add_contents(self, &block)
326
+ end
327
+
245
328
  private
246
329
 
247
330
  def style(underscored_widget_name, styles)
@@ -30,11 +30,9 @@ module Glimmer
30
30
  property_type = :string if property_type.nil? or property_type == :undefined
31
31
  @widget = widget
32
32
  @property_type = property_type
33
- add_contents(@widget) {
34
- on_widget_disposed { |dispose_event|
35
- unregister_all_observables
36
- }
37
- }
33
+ @widget.on_widget_disposed do |dispose_event|
34
+ unregister_all_observables
35
+ end
38
36
  end
39
37
  def call(value)
40
38
  @@property_type_updaters[@property_type].call(@widget, value) unless evaluate_property == value
@@ -96,15 +96,6 @@ module Glimmer
96
96
  )
97
97
  end
98
98
  end
99
- # @nested_property_observers_collection[observer].keys.each_with_index do |property_name, i|
100
- # previous_property_name = nested_property_names[i-1]
101
- # previous_observer = @nested_property_observers_collection[observer][previous_property_name]
102
- # nested_property_observer = @nested_property_observers_collection[observer][property_name]
103
- # previous_observer.add_dependent(nested_property_observer) unless previous_observer.nil?
104
- # end
105
- # TODO remove this brainstorming
106
- # person.addresses[1].streets[2].number
107
- # person.addresses[1] = ...
108
99
  @nested_property_observers_collection[observer]
109
100
  end
110
101
  def add_observer(observer)
@@ -113,8 +104,9 @@ module Glimmer
113
104
  elsif nested_property?
114
105
  add_nested_observers(observer)
115
106
  else
116
- observer.observe(model, property_name)
117
- observer.add_dependent([self, nil] => [observer, model, property_name])
107
+ observer_registration = observer.observe(model, property_name)
108
+ my_registration = observer.registration_for(self)
109
+ observer.add_dependent(my_registration => observer_registration)
118
110
  end
119
111
  end
120
112
  def remove_observer(observer)
@@ -140,8 +132,9 @@ module Glimmer
140
132
  end
141
133
  def add_computed_observers(observer)
142
134
  @computed_model_bindings.each do |computed_model_binding|
143
- computed_observer_for(observer).observe(computed_model_binding)
144
- observer.add_dependent([self, nil] => [computed_observer_for(observer), computed_model_binding, nil])
135
+ observer_registration = computed_observer_for(observer).observe(computed_model_binding)
136
+ my_registration = observer.registration_for(self)
137
+ observer.add_dependent(my_registration => observer_registration)
145
138
  end
146
139
  end
147
140
  def add_nested_observers(observer)
@@ -157,17 +150,12 @@ module Glimmer
157
150
  unless model.nil?
158
151
  if property_indexed?(property_name)
159
152
  # TODO figure out a way to deal with this more uniformly
160
- nested_property_observer.observe(model)
161
- parent_observer.add_dependent([parent_model, parent_property_name] => [nested_property_observer, model, nil])
153
+ observer_registration = nested_property_observer.observe(model)
162
154
  else
163
- # pd property_name, announcer: '[NESTED]', header: true
164
- # pd model, announcer: '[NESTED]'
165
- # pd nested_property_observer, announcer: '[NESTED]'
166
- nested_property_observer.observe(model, property_name)
167
- # pd 'DONE ADDING OBSERVER', announcer: '[NESTED]'
168
- parent_observer.add_dependent([parent_model, parent_property_name] => [nested_property_observer, model, property_name])
169
- # pd 'DONE ADDING DEPENDENT', announcer: '[NESTED]'
155
+ observer_registration = nested_property_observer.observe(model, property_name)
170
156
  end
157
+ parent_registration = parent_observer.registration_for(parent_model, parent_property_name)
158
+ parent_observer.add_dependent(parent_registration => observer_registration)
171
159
  end
172
160
  end
173
161
  end
@@ -28,7 +28,7 @@ module Glimmer
28
28
  end
29
29
  observer
30
30
  end
31
-
31
+
32
32
  def has_observer?(observer)
33
33
  property_observer_list.include?(observer)
34
34
  end
@@ -97,7 +97,7 @@ module Glimmer
97
97
  # TODO look into optimizing this
98
98
  return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
99
99
  property_observer_list.each do |observer|
100
- observer.unregister_dependents_with_observable([self, nil], old_value)
100
+ observer.unregister_dependents_with_observable(observer.registration_for(self), old_value)
101
101
  end
102
102
  end
103
103
  end
@@ -21,9 +21,6 @@ module Glimmer
21
21
  end
22
22
 
23
23
  def add_observer(observer, property_name)
24
- # pd property_name, announcer: '[ADD_OBSERVER]'
25
- # pd observer, announcer: '[ADD_OBSERVER]'
26
- # pd has_observer?(observer, property_name)
27
24
  return observer if has_observer?(observer, property_name)
28
25
  property_observer_list(property_name) << observer
29
26
  add_property_writer_observers(property_name)
@@ -85,16 +82,17 @@ module Glimmer
85
82
  # TODO look into optimizing this
86
83
  return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
87
84
  property_observer_list(property_name).each do |observer|
88
- observer.unregister_dependents_with_observable([self, property_name], old_value)
85
+ observer.unregister_dependents_with_observable(observer.registration_for(self, property_name), old_value)
89
86
  end
90
87
  end
91
88
 
92
89
  def ensure_array_object_observer(property_name, object, old_object = nil)
93
90
  return unless object.is_a?(Array)
94
91
  array_object_observer = array_object_observer_for(property_name)
95
- array_object_observer.observe(object)
92
+ array_observer_registration = array_object_observer.observe(object)
96
93
  property_observer_list(property_name).each do |observer|
97
- observer.add_dependent([self, property_name] => [array_object_observer, object, nil])
94
+ my_registration = observer.registration_for(self, property_name) # TODO eliminate repetition
95
+ observer.add_dependent(my_registration => array_observer_registration)
98
96
  end
99
97
  array_object_observer_for(property_name).unregister(old_object) if old_object.is_a?(ObservableArray)
100
98
  end
@@ -25,6 +25,13 @@ module Glimmer
25
25
  end
26
26
  end
27
27
 
28
+ class Registration < Struct.new(:observer, :observable, :property, keyword_init: true)
29
+ def unregister
30
+ observer.unobserve(observable, property)
31
+ end
32
+ alias unobserve unregister
33
+ end
34
+
28
35
  class << self
29
36
  def proc(&observer_block)
30
37
  Proc.new(&observer_block)
@@ -35,8 +42,8 @@ module Glimmer
35
42
  @registrations ||= Set.new
36
43
  end
37
44
 
38
- def registrations_for(observable, property = nil)
39
- registrations.select {|o, p| o == observable && p == property}
45
+ def registration_for(observable, property = nil)
46
+ Registration.new(observer: self, observable: observable, property: property)
40
47
  end
41
48
 
42
49
  # mapping of registrations to dependents
@@ -52,36 +59,27 @@ module Glimmer
52
59
  # registers observer in an observable on a property (optional)
53
60
  # observer maintains registration list to unregister later
54
61
  def register(observable, property = nil)
55
- # pd property, announcer: '[OBSERVE]', header: true
56
- # pd observable, announcer: '[OBSERVE]'
57
- # pd self, announcer: '[OBSERVE]'
58
62
  unless observable.is_a?(Observable)
59
- # pd 'not an observable'
60
63
  # TODO refactor code to be more smart/polymorphic/automated and honor open/closed principle
61
64
  if observable.is_a?(Array)
62
- # pd 'array'
63
65
  observable.extend(ObservableArray)
64
66
  else
65
- # pd 'not array'
66
67
  observable.extend(ObservableModel)
67
68
  end
68
69
  end
69
- # pd 'adding observer', announcer: '[OBSERVE]'
70
- # pd [self, property], announcer: '[OBSERVE]'
71
70
  observable.add_observer(*[self, property].compact)
72
- # pd 'adding registration', announcer: '[OBSERVE]'
73
- [observable, property].tap do |registration|
71
+ registration_for(observable, property).tap do |registration|
74
72
  self.registrations << registration
75
73
  end
76
74
  end
77
75
  alias observe register
78
76
 
79
77
  def unregister(observable, property = nil)
78
+ # TODO optimize performance in the future via indexing and/or making a registration official object/class
80
79
  observable.remove_observer(*[self, property].compact)
81
- registration = [observable, property]
80
+ registration = registration_for(observable, property)
82
81
  dependents_for(registration).each do |dependent|
83
- dependent_observer, dependent_observable, dependent_property = dependent
84
- dependent_observer.unregister(dependent_observable, dependent_property)
82
+ dependent.unregister
85
83
  remove_dependent(registration => dependent)
86
84
  end
87
85
  registrations.delete(registration)
@@ -89,32 +87,32 @@ module Glimmer
89
87
  alias unobserve unregister
90
88
 
91
89
  def unregister_dependents_with_observable(registration, dependent_observable)
92
- thedependents = dependents_for(registration).select do |d_observer, d_observable, d_property|
93
- d_observable == dependent_observable
90
+ thedependents = dependents_for(registration).select do |thedependent|
91
+ thedependent.observable == dependent_observable
94
92
  end
95
- thedependents.each do |d_observer, d_observable, d_property|
96
- d_observer.unregister(d_observable, d_property)
93
+ thedependents.each do |thedependent|
94
+ thedependent.unregister
97
95
  end
98
96
  end
99
97
 
100
98
  # cleans up all registrations in observables
101
99
  def unregister_all_observables
102
- registrations.each do |observable, property|
103
- unregister(observable, property)
100
+ registrations.each do |registration|
101
+ registration.unregister
104
102
  end
105
103
  end
106
104
  alias unobserve_all_observables unregister_all_observables
107
105
 
108
106
  # add dependent observer to unregister when unregistering observer
109
107
  def add_dependent(parent_to_dependent_hash)
110
- observable, property = registration = parent_to_dependent_hash.keys.first
111
- dependent_observer, dependent_observable, dependent_property = dependent = parent_to_dependent_hash.values.first
108
+ registration = parent_to_dependent_hash.keys.first
109
+ dependent = parent_to_dependent_hash.values.first
112
110
  dependents_for(registration) << dependent
113
111
  end
114
112
 
115
113
  def remove_dependent(parent_to_dependent_hash)
116
- observable, property = registration = parent_to_dependent_hash.keys.first
117
- dependent_observer, dependent_observable, dependent_property = dependent = parent_to_dependent_hash.values.first
114
+ registration = parent_to_dependent_hash.keys.first
115
+ dependent = parent_to_dependent_hash.values.first
118
116
  dependents_for(registration).delete(dependent)
119
117
  end
120
118
 
@@ -19,11 +19,9 @@ module Glimmer
19
19
  call(@model_binding.evaluate_property)
20
20
  model = model_binding.base_model
21
21
  observe(model, model_binding.property_name_expression)
22
- add_contents(@table) {
23
- on_widget_disposed { |dispose_event|
24
- unregister_all_observables
25
- }
26
- }
22
+ @table.on_widget_disposed do |dispose_event|
23
+ unregister_all_observables
24
+ end
27
25
  end
28
26
  def call(model_collection=nil)
29
27
  if model_collection and model_collection.is_a?(Array)