glimmer 0.2.5 → 0.3.1

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