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.
- 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)
|