glimmer 0.4.8 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +237 -94
- data/bin/girb_runner.rb +2 -0
- data/lib/glimmer.rb +1 -0
- data/lib/glimmer/command_handler.rb +5 -0
- data/lib/glimmer/command_handler_chain_link.rb +5 -4
- data/lib/glimmer/command_handlers.rb +2 -0
- data/lib/glimmer/swt/command_handlers/custom_widget_command_handler.rb +4 -2
- data/lib/glimmer/swt/command_handlers/data_binding_command_handler.rb +0 -1
- data/lib/glimmer/swt/command_handlers/observe_command_handler.rb +35 -0
- data/lib/glimmer/swt/command_handlers/property_command_handler.rb +4 -4
- data/lib/glimmer/swt/command_handlers/widget_listener_command_handler.rb +12 -9
- data/lib/glimmer/swt/custom_shell.rb +45 -0
- data/lib/glimmer/swt/custom_widget.rb +73 -9
- data/lib/glimmer/swt/g_display.rb +8 -0
- data/lib/glimmer/swt/g_font.rb +3 -7
- data/lib/glimmer/swt/g_layout.rb +1 -1
- data/lib/glimmer/swt/g_layout_data.rb +1 -1
- data/lib/glimmer/swt/g_shell.rb +57 -5
- data/lib/glimmer/swt/g_widget.rb +111 -28
- data/lib/glimmer/swt/list_selection_binding.rb +3 -5
- data/lib/glimmer/swt/model_binding.rb +10 -22
- data/lib/glimmer/swt/observable_array.rb +2 -2
- data/lib/glimmer/swt/observable_model.rb +4 -6
- data/lib/glimmer/swt/observer.rb +23 -25
- data/lib/glimmer/swt/table_items_binding.rb +3 -5
- data/lib/glimmer/swt/tree_items_binding.rb +3 -5
- data/lib/glimmer/swt/widget_binding.rb +3 -5
- data/lib/glimmer/swt_packages.rb +1 -0
- data/lib/glimmer/xml/node.rb +1 -1
- metadata +18 -2
data/lib/glimmer/swt/g_widget.rb
CHANGED
@@ -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
|
49
|
-
|
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
|
-
|
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
|
-
|
58
|
-
|
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
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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(
|
252
|
+
block.call(self)
|
217
253
|
end
|
218
254
|
|
219
255
|
def async_exec(&block)
|
220
|
-
|
256
|
+
GDisplay.instance.async_exec(&block)
|
221
257
|
end
|
222
258
|
|
223
259
|
def sync_exec(&block)
|
224
|
-
|
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 =
|
237
|
-
|
238
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
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.
|
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.
|
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
|
-
|
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(
|
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(
|
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.
|
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
|
data/lib/glimmer/swt/observer.rb
CHANGED
@@ -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
|
39
|
-
|
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
|
-
|
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 =
|
80
|
+
registration = registration_for(observable, property)
|
82
81
|
dependents_for(registration).each do |dependent|
|
83
|
-
|
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 |
|
93
|
-
|
90
|
+
thedependents = dependents_for(registration).select do |thedependent|
|
91
|
+
thedependent.observable == dependent_observable
|
94
92
|
end
|
95
|
-
thedependents.each do |
|
96
|
-
|
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 |
|
103
|
-
unregister
|
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
|
-
|
111
|
-
|
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
|
-
|
117
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
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)
|