glimmer 0.4.8 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)