glimmer 0.2.5 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea0f249121119690fd3553adc211844541485690b633198bf5a186ea227e878b
4
- data.tar.gz: b598dc0df0a28745eadfdc917cda0dda117f773c2b507e7563915c87fc4a3bb6
3
+ metadata.gz: cc35b055fcf86d7c93b264b409424039c63c0361f0a7b587e9db0f2071e7809e
4
+ data.tar.gz: 3ab0eec08e13367c717ee74a984fea0ee49bbd309fd2fd3348fb40e70b156b2c
5
5
  SHA512:
6
- metadata.gz: 9282de0acba5317c726d5ccb93f1bd3261ff3a8a4937eb0d12bb9dd96d656a887968f661530111ef661a060aed06a18de44dd8f42831c11ae73c0760d61d7ca2
7
- data.tar.gz: 93095774ad6692645730284c959742eb7399b2504671d5160856694f7592f694712b68e32540dc86aa9af786dbdf21d8b0d6ac7f93ed3ec475df32c35e249bd7
6
+ metadata.gz: '059e99839505e645cc41cd13d0adc2f04680643dd7d45d6b6ecb0e9e2fec7823f330f0962756f745ba9ca564c945fb97480e988d21efd732fb3ec36185c8dc89'
7
+ data.tar.gz: eb9f191f5aa31e9d716b787bb1b54d0792fb2aaaf080f8f37b7dd17e0ada300192986910b8fe3bcf777a1da7382cf5bd8dd3c6d59bccf63703fbcb95b3fa7bc9
data/README.markdown CHANGED
@@ -66,14 +66,14 @@ Please follow these instructions to make the `glimmer` command available on your
66
66
 
67
67
  Run this command to install directly:
68
68
  ```
69
- jgem install glimmer -v 0.2.5
69
+ jgem install glimmer -v 0.3.1
70
70
  ```
71
71
 
72
72
  ### Option 2: Bundler
73
73
 
74
74
  Add the following to `Gemfile`:
75
75
  ```
76
- gem 'glimmer', '~> 0.2.5'
76
+ gem 'glimmer', '~> 0.3.1'
77
77
  ```
78
78
 
79
79
  And, then run:
@@ -22,12 +22,12 @@ class ComboSelectionDataBindingCommandHandler
22
22
  widget_binding = WidgetBinding.new(parent, "items")
23
23
  widget_binding.update(model_binding.evaluate_options_property)
24
24
  model = model_binding.base_model
25
- model.extend ObservableModel unless model.is_a?(ObservableModel)
26
- model.add_observer(model_binding.options_property_name, widget_binding)
25
+ model.extend(ObservableModel) unless model.is_a?(ObservableModel)
26
+ widget_binding.observe(model, model_binding.options_property_name)
27
27
 
28
28
  widget_binding = WidgetBinding.new(parent, "text")
29
29
  widget_binding.update(model_binding.evaluate_property)
30
- model.add_observer(model_binding.property_name_expression, widget_binding)
30
+ widget_binding.observe(model, model_binding.property_name_expression)
31
31
 
32
32
  add_contents(parent) {
33
33
  on_widget_selected {
@@ -58,7 +58,7 @@ class DataBindingCommandHandler
58
58
  widget_binding_parameters = [parent, command_symbol.to_s]
59
59
  widget_binding = WidgetBinding.new(*widget_binding_parameters)
60
60
  widget_binding.update(model_binding.evaluate_property)
61
- model_binding.add_observer(widget_binding)
61
+ widget_binding.observe(model_binding)
62
62
  widget_data_binder_map = @@widget_data_binders[parent.widget.class]
63
63
  widget_data_binder = widget_data_binder_map[command_symbol.to_s.to_sym] if widget_data_binder_map
64
64
  widget_data_binder.call(parent, model_binding) if widget_data_binder
@@ -23,14 +23,16 @@ class ListSelectionDataBindingCommandHandler
23
23
  widget_binding = WidgetBinding.new(parent, "items")
24
24
  widget_binding.update(model_binding.evaluate_options_property)
25
25
  model = model_binding.base_model
26
- model.extend ObservableModel unless model.is_a?(ObservableModel)
27
- model.add_observer(model_binding.options_property_name, widget_binding)
26
+ model.extend(ObservableModel) unless model.is_a?(ObservableModel)
27
+ #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
28
+ widget_binding.observe(model, model_binding.options_property_name)
28
29
 
29
30
  property_type = :string
30
31
  property_type = :array if parent.has_style?(:multi)
31
32
  list_selection_binding = ListSelectionBinding.new(parent, property_type)
32
33
  list_selection_binding.update(model_binding.evaluate_property)
33
- model.add_observer(model_binding.property_name_expression, list_selection_binding)
34
+ #TODO check if nested data binding works for list widget and other widgets that need custom data binding
35
+ list_selection_binding.observe(model, model_binding.property_name_expression)
34
36
 
35
37
  add_contents(parent) {
36
38
  on_widget_selected {
@@ -1,5 +1,6 @@
1
- # Observer that takes an updater block to process updates
1
+ require_relative 'observer'
2
2
 
3
+ # Observer that takes an updater block to process updates
3
4
  class BlockObserver
4
5
  include Observer
5
6
 
@@ -2,6 +2,7 @@ require File.dirname(__FILE__) + "/observer"
2
2
 
3
3
  # SWT List widget selection binding
4
4
  class ListSelectionBinding
5
+ include Glimmer
5
6
  include Observer
6
7
 
7
8
  attr_reader :widget
@@ -25,6 +26,11 @@ class ListSelectionBinding
25
26
  property_type = :string if property_type.nil? or property_type == :undefined
26
27
  @widget = widget
27
28
  @property_type = property_type
29
+ add_contents(@widget) {
30
+ on_widget_disposed { |dispose_event|
31
+ unregister_all_observables
32
+ }
33
+ }
28
34
  end
29
35
  def update(value)
30
36
  @@property_type_updaters[@property_type].call(@widget, value) unless evaluate_property == value
@@ -1,4 +1,5 @@
1
- require File.dirname(__FILE__) + "/observer"
1
+ require_relative 'observer'
2
+ require_relative 'block_observer'
2
3
 
3
4
  class ModelBinding
4
5
  include Observer
@@ -92,40 +93,77 @@ class ModelBinding
92
93
  )
93
94
  end
94
95
  end
96
+ # @nested_property_observers_collection[observer].keys.each_with_index do |property_name, i|
97
+ # previous_property_name = nested_property_names[i-1]
98
+ # previous_observer = @nested_property_observers_collection[observer][previous_property_name]
99
+ # nested_property_observer = @nested_property_observers_collection[observer][property_name]
100
+ # previous_observer.add_dependent(nested_property_observer) unless previous_observer.nil?
101
+ # end
102
+ # TODO remove this brainstorming
103
+ # person.addresses[1].streets[2].number
104
+ # person.addresses[1] = ...
95
105
  @nested_property_observers_collection[observer]
96
106
  end
97
107
  def add_observer(observer)
98
108
  if computed?
99
109
  add_computed_observers(observer)
110
+ elsif nested_property?
111
+ add_nested_observers(observer)
100
112
  else
101
- add_direct_observer(observer)
113
+ model.extend(ObservableModel) unless model.is_a?(ObservableModel)
114
+ observer.observe(model, property_name)
115
+ observer.add_dependent([self, nil] => [observer, model, property_name])
102
116
  end
103
117
  end
104
- def add_computed_observers(observer)
105
- computed_observer = BlockObserver.new do |changed_value|
106
- observer.update(evaluate_property)
118
+ def remove_observer(observer)
119
+ if computed?
120
+ @computed_model_bindings.each do |computed_model_binding|
121
+ computed_observer_for(observer).unobserve(computed_model_binding)
122
+ end
123
+ @computed_observer_collection[observer] = nil
124
+ elsif nested_property?
125
+ nested_property_observers_for(observer).clear
126
+ else
127
+ model.extend(ObservableModel) unless model.is_a?(ObservableModel)
128
+ observer.unobserve(model, property_name)
107
129
  end
130
+ end
131
+ def computed_observer_for(observer)
132
+ @computed_observer_collection ||= {}
133
+ unless @computed_observer_collection.has_key?(observer)
134
+ @computed_observer_collection[observer] = BlockObserver.new do |changed_value|
135
+ observer.update(evaluate_property)
136
+ end
137
+ end
138
+ @computed_observer_collection[observer]
139
+ end
140
+ def add_computed_observers(observer)
108
141
  @computed_model_bindings.each do |computed_model_binding|
109
- computed_model_binding.add_observer(computed_observer)
142
+ computed_observer_for(observer).observe(computed_model_binding)
143
+ observer.add_dependent([self, nil] => [computed_observer_for(observer), computed_model_binding, nil])
110
144
  end
111
145
  end
112
- def add_direct_observer(observer)
113
- if nested_property?
114
- nested_property_observers = nested_property_observers_for(observer)
115
- nested_models.zip(nested_property_names).each do |model, property_name|
116
- unless model.nil?
117
- if property_indexed?(property_name)
118
- model.extend ObservableArray unless model.is_a?(ObservableArray)
119
- model.add_array_observer(nested_property_observers[property_name]) unless model.has_array_observer?(nested_property_observers[property_name])
120
- else
121
- model.extend ObservableModel unless model.is_a?(ObservableModel)
122
- model.add_observer(property_name, nested_property_observers[property_name]) unless model.has_observer?(property_name, nested_property_observers[property_name])
123
- end
146
+ def add_nested_observers(observer)
147
+ nested_property_observers = nested_property_observers_for(observer)
148
+ nested_models.zip(nested_property_names).each_with_index do |zip, i|
149
+ model, property_name = zip
150
+ nested_property_observer = nested_property_observers[property_name]
151
+ previous_index = i - 1
152
+ parent_model = previous_index.negative? ? self : nested_models[previous_index]
153
+ parent_property_name = previous_index.negative? ? nil : nested_property_names[previous_index]
154
+ parent_observer = previous_index.negative? ? observer : nested_property_observers[parent_property_name]
155
+ parent_property_name = nil if parent_property_name.to_s.start_with?('[')
156
+ unless model.nil?
157
+ if property_indexed?(property_name)
158
+ model.extend(ObservableArray) unless model.is_a?(ObservableArray)
159
+ nested_property_observer.observe(model) unless model.has_observer?(nested_property_observer)
160
+ parent_observer.add_dependent([parent_model, parent_property_name] => [nested_property_observer, model, nil])
161
+ else
162
+ model.extend(ObservableModel) unless model.is_a?(ObservableModel)
163
+ nested_property_observer.observe(model, property_name) unless model.has_observer?(nested_property_observer, property_name)
164
+ parent_observer.add_dependent([parent_model, parent_property_name] => [nested_property_observer, model, property_name])
124
165
  end
125
166
  end
126
- else
127
- model.extend ObservableModel unless model.is_a?(ObservableModel)
128
- model.add_observer(property_name, observer)
129
167
  end
130
168
  end
131
169
  def update(value)
@@ -137,7 +175,7 @@ class ModelBinding
137
175
  invoke_property_reader(model, property_name) unless model.nil?
138
176
  end
139
177
  def evaluate_options_property
140
- model.send(property_name + "_options") unless model.nil?
178
+ model.send(options_property_name) unless model.nil?
141
179
  end
142
180
  def options_property_name
143
181
  self.property_name + "_options"
@@ -0,0 +1,9 @@
1
+ module Observable
2
+ def add_observer(observer, property_or_properties=nil)
3
+ raise 'Not implemented!'
4
+ end
5
+
6
+ def remove_observer(observer, property_or_properties=nil)
7
+ raise 'Not implemented!'
8
+ end
9
+ end
@@ -1,27 +1,39 @@
1
1
  require 'set'
2
+
3
+ require_relative 'observable'
4
+
5
+ # TODO prefix utility methods with double-underscore
2
6
  module ObservableArray
7
+ include Observable
3
8
 
4
- def add_observer(element_properties, observer)
9
+ def add_observer(observer, element_properties=nil)
5
10
  property_observer_list << observer
6
- each do |element|
7
- [element_properties].flatten.each do |property|
11
+ [element_properties].flatten.compact.each do |property|
12
+ each do |element|
8
13
  element.extend(ObservableModel) unless element.is_a?(ObservableModel)
9
- element.add_observer(property, observer)
14
+ observer.observe(element, property)
10
15
  end
11
16
  end
17
+ observer
12
18
  end
13
19
 
14
- def add_array_observer(observer)
15
- property_observer_list << observer
20
+ def remove_observer(observer, element_properties=nil)
21
+ property_observer_list.delete(observer)
22
+ [element_properties].flatten.compact.each do |property|
23
+ each do |element|
24
+ element.extend(ObservableModel) unless element.is_a?(ObservableModel)
25
+ observer.unobserve(element, property)
26
+ end
27
+ end
28
+ observer
16
29
  end
17
30
 
18
- def has_array_observer?(observer)
31
+ def has_observer?(observer)
19
32
  property_observer_list.include?(observer)
20
33
  end
21
34
 
22
35
  def property_observer_list
23
- @property_observer_list = Set.new unless @property_observer_list
24
- @property_observer_list
36
+ @property_observer_list ||= Set.new
25
37
  end
26
38
 
27
39
  def notify_observers
@@ -29,37 +41,63 @@ module ObservableArray
29
41
  end
30
42
 
31
43
  def self.extend_object(array)
32
- array.instance_eval("alias __original_add__ <<")
44
+ array.instance_eval("alias __original_add <<")
33
45
  array.instance_eval <<-end_eval, __FILE__, __LINE__
34
46
  def <<(value)
35
- self.__original_add__(value)
47
+ self.__original_add(value)
36
48
  notify_observers
37
49
  end
38
50
  end_eval
39
51
 
40
- array.instance_eval("alias __original_set_value__ []=")
52
+ array.instance_eval("alias __original_set_value []=")
41
53
  array.instance_eval <<-end_eval, __FILE__, __LINE__
42
54
  def []=(index, value)
43
- self.__original_set_value__(index, value)
55
+ old_value = self[index]
56
+ unregister_dependent_observers(old_value)
57
+ self.__original_set_value(index, value)
44
58
  notify_observers
45
59
  end
46
60
  end_eval
47
61
 
48
- notify_observers_on_invokation(array, "delete")
49
- notify_observers_on_invokation(array, "delete_at")
50
- notify_observers_on_invokation(array, "clear")
62
+ array.instance_eval("alias __original_delete delete")
63
+ array.instance_eval <<-end_eval, __FILE__, __LINE__
64
+ def delete(value)
65
+ unregister_dependent_observers(value)
66
+ self.__original_delete(value)
67
+ notify_observers
68
+ end
69
+ end_eval
51
70
 
52
- super
53
- end
71
+ array.instance_eval("alias __original_delete_at delete_at")
72
+ array.instance_eval <<-end_eval, __FILE__, __LINE__
73
+ def delete_at(index)
74
+ old_value = self[index]
75
+ unregister_dependent_observers(old_value)
76
+ self.__original_delete_at(index)
77
+ notify_observers
78
+ end
79
+ end_eval
54
80
 
55
- def self.notify_observers_on_invokation(model, method)
56
- model.instance_eval "alias __original_#{method}__ #{method}\n"
57
- model.instance_eval <<-end_eval, __FILE__, __LINE__
58
- def #{method}(*args, &block)
59
- self.__original_#{method}__(*args, &block)
81
+ array.instance_eval("alias __original_clear clear")
82
+ array.instance_eval <<-end_eval, __FILE__, __LINE__
83
+ def clear
84
+ each do |old_value|
85
+ unregister_dependent_observers(old_value)
86
+ end
87
+ self.__original_clear
60
88
  notify_observers
61
89
  end
62
90
  end_eval
91
+
92
+ super
93
+ end
94
+
95
+ def unregister_dependent_observers(old_value)
96
+ # TODO look into optimizing this
97
+ return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
98
+ property_observer_list.each do |observer|
99
+ observer.unregister_dependents_with_observable([self, nil], old_value)
100
+ end
63
101
  end
64
102
 
65
103
  end
@@ -1,19 +1,42 @@
1
1
  require 'set'
2
2
 
3
- require File.dirname(__FILE__) + "/block_observer"
3
+ require_relative 'observable'
4
+ require_relative 'observer'
4
5
 
6
+ # TODO prefix utility methods with double-underscore
5
7
  module ObservableModel
8
+ include Observable
6
9
 
7
- # Takes observer as an object or a block updater
8
- def add_observer(property_name, observer = nil, &updater)
9
- observer ||= BlockObserver.new(&updater)
10
+ class Updater
11
+ include Observer
12
+ def initialize(observable_model, property_name)
13
+ @observable_model = observable_model
14
+ @property_name = property_name
15
+ end
16
+ def update(changed_value=nil)
17
+ @observable_model.notify_observers(@property_name)
18
+ end
19
+ end
20
+
21
+ def add_observer(observer, property_name)
22
+ return observer if has_observer?(observer, property_name)
10
23
  property_observer_list(property_name) << observer
24
+ add_property_writer_observers(property_name)
25
+ observer
11
26
  end
12
27
 
13
- def has_observer?(property_name, observer)
28
+ def remove_observer(observer, property_name)
29
+ property_observer_list(property_name).delete(observer)
30
+ end
31
+
32
+ def has_observer?(observer, property_name)
14
33
  property_observer_list(property_name).include?(observer)
15
34
  end
16
35
 
36
+ def has_observer_for_any_property?(observer)
37
+ property_observer_hash.values.map(&:to_a).sum.include?(observer)
38
+ end
39
+
17
40
  def property_observer_hash
18
41
  @property_observers = Hash.new unless @property_observers
19
42
  @property_observers
@@ -27,45 +50,51 @@ module ObservableModel
27
50
  def notify_observers(property_name)
28
51
  property_observer_list(property_name).each {|observer| observer.update(send(property_name))}
29
52
  end
53
+ #TODO upon updating values, make sure dependent observers are cleared (not added as dependents here)
30
54
 
31
- class Updater
32
- def initialize(property_name, observable_model)
33
- @property_name = property_name
34
- @observable_model = observable_model
55
+ def add_property_writer_observers(property_name)
56
+ property_writer_name = "#{property_name}="
57
+ ensure_array_object_observer(property_name, send(property_name))
58
+ begin
59
+ method("__original_#{property_writer_name}")
60
+ rescue
61
+ instance_eval "alias __original_#{property_writer_name} #{property_writer_name}"
62
+ instance_eval <<-end_eval, __FILE__, __LINE__
63
+ def #{property_writer_name}(value)
64
+ old_value = self.#{property_name}
65
+ unregister_dependent_observers('#{property_name}', old_value)
66
+ self.__original_#{property_writer_name}(value)
67
+ notify_observers('#{property_name}')
68
+ ensure_array_object_observer('#{property_name}', value, old_value)
69
+ end
70
+ end_eval
35
71
  end
36
- def update
37
- @observable_model.notify_observers(@property_name)
72
+ end
73
+
74
+ def unregister_dependent_observers(property_name, old_value)
75
+ # TODO look into optimizing this
76
+ return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
77
+ property_observer_list(property_name).each do |observer|
78
+ observer.unregister_dependents_with_observable([self, property_name], old_value)
38
79
  end
39
80
  end
40
81
 
41
- def self.extend_object(model)
42
- super
43
- model.methods.each do |method|
44
- self.add_method_observers(model, method)
82
+ def ensure_array_object_observer(property_name, object, old_object = nil)
83
+ return unless object.is_a?(Array)
84
+ object.extend(ObservableArray) unless object.is_a?(ObservableArray)
85
+ array_object_observer = array_object_observer_for(property_name)
86
+ array_object_observer.observe(object)
87
+ property_observer_list(property_name).each do |observer|
88
+ observer.add_dependent([self, property_name] => [array_object_observer, object, nil])
45
89
  end
90
+ array_object_observer_for(property_name).unregister(old_object) if old_object.is_a?(ObservableArray)
46
91
  end
47
92
 
48
- def self.add_method_observers(model, method)
49
- setter_method_pattern = /^(\w+=)$/
50
- if (method.match(setter_method_pattern))
51
- getter_method = method[0, method.length - 1]
52
- getter_value = model.send(getter_method)
53
- if (getter_value.is_a?(Array) and
54
- !getter_value.is_a?(ObservableArray))
55
- getter_value.extend(ObservableArray)
56
- getter_value.add_observer([], Updater.new(getter_method, model))
57
- end
58
- model.instance_eval "alias original_#{method} #{method}\n"
59
- model.instance_eval <<-end_eval, __FILE__, __LINE__
60
- def #{method}(value)
61
- self.original_#{method}(value)
62
- notify_observers('#{getter_method}')
63
- if (value.is_a?(Array) and !value.is_a?(ObservableArray))
64
- value.extend(ObservableArray)
65
- value.add_observer([], ObservableModel::Updater.new('#{getter_method}', self))
66
- end
67
- end
68
- end_eval
93
+ def array_object_observer_for(property_name)
94
+ @array_object_observers ||= {}
95
+ unless @array_object_observers.has_key?(property_name)
96
+ @array_object_observers[property_name] = ObservableModel::Updater.new(self, property_name)
69
97
  end
98
+ @array_object_observers[property_name]
70
99
  end
71
100
  end
@@ -1,8 +1,79 @@
1
+ require 'set'
2
+
1
3
  # Mixin representing Observer trait from Observer Design Pattern
2
4
  # Allows classes to include without interfering with their
3
5
  # inheritance hierarchy.
4
-
5
6
  module Observer
7
+ def registrations
8
+ @registrations ||= Set.new
9
+ end
10
+
11
+ def registrations_for(observable, property = nil)
12
+ registrations.select {|o, p| o == observable && p == property}
13
+ end
14
+
15
+ # mapping of registrations to dependents
16
+ # {[observable, property] => [[dependent, dependent_observable, dependent_property], ...]}
17
+ def dependents
18
+ @dependents ||= Hash.new
19
+ end
20
+
21
+ def dependents_for(registration)
22
+ dependents[registration] ||= Set.new
23
+ end
24
+
25
+ # registers observer in an observable on a property (optional)
26
+ # observer maintains registration list to unregister later
27
+ def register(observable, property = nil)
28
+ observable.add_observer(*[self, property].compact)
29
+ [observable, property].tap do |registration|
30
+ self.registrations << registration
31
+ end
32
+ end
33
+ alias observe register
34
+
35
+ def unregister(observable, property = nil)
36
+ observable.remove_observer(*[self, property].compact)
37
+ registration = [observable, property]
38
+ dependents_for(registration).each do |dependent|
39
+ dependent_observer, dependent_observable, dependent_property = dependent
40
+ dependent_observer.unregister(dependent_observable, dependent_property)
41
+ remove_dependent(registration => dependent)
42
+ end
43
+ registrations.delete(registration)
44
+ end
45
+ alias unobserve unregister
46
+
47
+ def unregister_dependents_with_observable(registration, dependent_observable)
48
+ thedependents = dependents_for(registration).select do |d_observer, d_observable, d_property|
49
+ d_observable == dependent_observable
50
+ end
51
+ thedependents.each do |d_observer, d_observable, d_property|
52
+ d_observer.unregister(d_observable, d_property)
53
+ end
54
+ end
55
+
56
+ # cleans up all registrations in observables
57
+ def unregister_all_observables
58
+ registrations.each do |observable, property|
59
+ unregister(observable, property)
60
+ end
61
+ end
62
+ alias unobserve_all_observables unregister_all_observables
63
+
64
+ # add dependent observer to unregister when unregistering observer
65
+ def add_dependent(parent_to_dependent_hash)
66
+ observable, property = registration = parent_to_dependent_hash.keys.first
67
+ dependent_observer, dependent_observable, dependent_property = dependent = parent_to_dependent_hash.values.first
68
+ dependents_for(registration) << dependent
69
+ end
70
+
71
+ def remove_dependent(parent_to_dependent_hash)
72
+ observable, property = registration = parent_to_dependent_hash.keys.first
73
+ dependent_observer, dependent_observable, dependent_property = dependent = parent_to_dependent_hash.values.first
74
+ dependents_for(registration).delete(dependent)
75
+ end
76
+
6
77
  def update(changed_value)
7
78
  raise 'Not implemented!'
8
79
  end
@@ -5,9 +5,9 @@ class RWidget
5
5
  require File.dirname(__FILE__) + "/r_widget_packages"
6
6
 
7
7
  include Parent
8
-
8
+
9
9
  attr_reader :widget
10
-
10
+
11
11
  #TODO externalize
12
12
  @@default_styles = {
13
13
  "text" => SWT::BORDER,
@@ -16,11 +16,11 @@ class RWidget
16
16
  "list" => SWT::BORDER | SWT::V_SCROLL,
17
17
  "button" => SWT::PUSH,
18
18
  }
19
-
19
+
20
20
  #TODO externalize
21
21
  @@default_initializers = {
22
22
  "composite" => Proc.new {|composite| composite.setLayout(GridLayout.new) },
23
- "table" => Proc.new do |table|
23
+ "table" => Proc.new do |table|
24
24
  table.setHeaderVisible(true)
25
25
  table.setLinesVisible(true)
26
26
  end,
@@ -33,7 +33,7 @@ class RWidget
33
33
  @widget = underscored_widget_name.swt_widget.new(parent, style(underscored_widget_name, styles))
34
34
  @@default_initializers[underscored_widget_name].call(@widget) if @@default_initializers[underscored_widget_name]
35
35
  end
36
-
36
+
37
37
  def has_attribute?(attribute_name, *args)
38
38
  @widget.respond_to?(attribute_setter(attribute_name), args)
39
39
  end
@@ -66,10 +66,10 @@ class RWidget
66
66
  end
67
67
  return false
68
68
  end
69
-
69
+
70
70
  def can_add_listener?(underscored_listener_name)
71
71
  listener_method_name = underscored_listener_name.camelcase(:lower)
72
- @widget.getClass.getMethods.each do |widget_method|
72
+ @widget.getClass.getMethods.each do |widget_method|
73
73
  if widget_method.getName.match(/add.*Listener/)
74
74
  widget_method.getParameterTypes.each do |listener_type|
75
75
  listener_type.getMethods.each do |listener_method|
@@ -82,10 +82,10 @@ class RWidget
82
82
  end
83
83
  return false
84
84
  end
85
-
86
- def add_listener(underscored_listener_name, &block)
85
+
86
+ def add_listener(underscored_listener_name, &block)
87
87
  listener_method_name = underscored_listener_name.camelcase(:lower)
88
- @widget.getClass.getMethods.each do |widget_method|
88
+ @widget.getClass.getMethods.each do |widget_method|
89
89
  if widget_method.getName.match(/add.*Listener/)
90
90
  widget_method.getParameterTypes.each do |listener_type|
91
91
  listener_type.getMethods.each do |listener_method|
@@ -109,11 +109,11 @@ class RWidget
109
109
  end
110
110
  end
111
111
  end
112
-
112
+
113
113
  def process_block(block)
114
114
  block.call(@widget)
115
115
  end
116
-
116
+
117
117
  def async_exec(&block)
118
118
  @widget.getDisplay.asyncExec(RRunnable.new(&block))
119
119
  end
@@ -121,7 +121,7 @@ class RWidget
121
121
  def sync_exec(&block)
122
122
  @widget.getDisplay.syncExec(RRunnable.new(&block))
123
123
  end
124
-
124
+
125
125
  def has_style?(style)
126
126
  (widget.style & style.swt_constant) == style.swt_constant
127
127
  end
@@ -144,10 +144,10 @@ class RWidget
144
144
 
145
145
  def swt_styles(styles)
146
146
  styles.map(&:swt_constant)
147
- end
148
-
147
+ end
148
+
149
149
  def attribute_setter(attribute_name)
150
150
  "set#{attribute_name.to_s.camelcase(:upper)}"
151
151
  end
152
152
 
153
- end
153
+ end
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + "/observable_model"
3
3
  require File.dirname(__FILE__) + "/observer"
4
4
 
5
5
  class TableItemsBinding
6
+ include Glimmer
6
7
  include Observer
7
8
  include_package 'org.eclipse.swt'
8
9
  include_package 'org.eclipse.swt.widgets'
@@ -14,12 +15,17 @@ class TableItemsBinding
14
15
  update(@model_binding.evaluate_property)
15
16
  model = model_binding.base_model
16
17
  model.extend(ObservableModel) unless model.is_a?(ObservableModel)
17
- model.add_observer(model_binding.property_name_expression, self)
18
+ observe(model, model_binding.property_name_expression)
19
+ add_contents(@table) {
20
+ on_widget_disposed { |dispose_event|
21
+ unregister_all_observables
22
+ }
23
+ }
18
24
  end
19
25
  def update(model_collection=nil)
20
26
  if model_collection and model_collection.is_a?(Array)
21
27
  model_collection.extend(ObservableArray) unless model_collection.is_a?(ObservableArray)
22
- model_collection.add_observer(@column_properties, self)
28
+ observe(model_collection, @column_properties)
23
29
  @model_collection = model_collection
24
30
  end
25
31
  populate_table(@model_collection, @table, @column_properties)
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + "/observable_model"
3
3
  require File.dirname(__FILE__) + "/observer"
4
4
 
5
5
  class TreeItemsBinding
6
+ include Glimmer
6
7
  include Observer
7
8
  include_package 'org.eclipse.swt'
8
9
  include_package 'org.eclipse.swt.widgets'
@@ -14,13 +15,18 @@ class TreeItemsBinding
14
15
  update(@model_binding.evaluate_property)
15
16
  model = model_binding.base_model
16
17
  model.extend(ObservableModel) unless model.is_a?(ObservableModel)
17
- model.add_observer(model_binding.property_name_expression, self)
18
+ observe(model, model_binding.property_name_expression)
19
+ add_contents(@tree) {
20
+ on_widget_disposed { |dispose_event|
21
+ unregister_all_observables
22
+ }
23
+ }
18
24
  end
19
25
  def update(model_tree_root_node=nil)
20
26
  if model_tree_root_node and model_tree_root_node.respond_to?(@tree_properties[:children])
21
27
  model_tree_root_node.extend(ObservableModel) unless model_tree_root_node.is_a?(ObservableModel)
22
- model_tree_root_node.add_observer(@tree_properties[:text], self)
23
- model_tree_root_node.add_observer(@tree_properties[:children], self)
28
+ observe(model_tree_root_node, @tree_properties[:text])
29
+ observe(model_tree_root_node, @tree_properties[:children])
24
30
  @model_tree_root_node = model_tree_root_node
25
31
  end
26
32
  populate_tree(@model_tree_root_node, @tree, @tree_properties)
@@ -34,7 +40,7 @@ class TreeItemsBinding
34
40
  table_item.setText((model_tree_node && model_tree_node.send(tree_properties[:text])).to_s)
35
41
  [model_tree_node && model_tree_node.send(tree_properties[:children])].flatten.to_a.compact.each do |child|
36
42
  child.extend(ObservableModel) unless child.is_a?(ObservableModel)
37
- child.add_observer(@tree_properties[:text], self)
43
+ observe(child, @tree_properties[:text])
38
44
  populate_tree_node(child, table_item, tree_properties)
39
45
  end
40
46
  end
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + "/observer"
2
2
 
3
3
  class WidgetBinding
4
+ include Glimmer
4
5
  include Observer
5
6
 
6
7
  attr_reader :widget, :property
@@ -13,6 +14,11 @@ class WidgetBinding
13
14
  @widget = model
14
15
  @property = property
15
16
  @translator = translator || proc {|value| value}
17
+ add_contents(@widget) {
18
+ on_widget_disposed { |dispose_event|
19
+ unregister_all_observables
20
+ }
21
+ }
16
22
  end
17
23
  def update(value)
18
24
  converted_value = translated_value = @translator.call(value)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-08 00:00:00.000000000 Z
11
+ date: 2020-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +162,7 @@ files:
162
162
  - lib/command_handlers/models/block_observer.rb
163
163
  - lib/command_handlers/models/list_selection_binding.rb
164
164
  - lib/command_handlers/models/model_binding.rb
165
+ - lib/command_handlers/models/observable.rb
165
166
  - lib/command_handlers/models/observable_array.rb
166
167
  - lib/command_handlers/models/observable_model.rb
167
168
  - lib/command_handlers/models/observer.rb