glimmer-dsl-swt 0.1.1 → 0.2.2

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.
@@ -1,108 +0,0 @@
1
- require 'glimmer'
2
-
3
- require_relative 'observable'
4
- require_relative 'observer'
5
-
6
- module Glimmer
7
- module DataBinding
8
- # TODO prefix utility methods with double-underscore
9
- module ObservableModel
10
- include Observable
11
-
12
- class Notifier
13
- include Observer
14
- def initialize(observable_model, property_name)
15
- @observable_model = observable_model
16
- @property_name = property_name
17
- end
18
- def call(new_value=nil)
19
- @observable_model.notify_observers(@property_name)
20
- end
21
- end
22
-
23
- def add_observer(observer, property_name)
24
- return observer if has_observer?(observer, property_name)
25
- property_observer_list(property_name) << observer
26
- add_property_writer_observers(property_name)
27
- observer
28
- end
29
-
30
- def remove_observer(observer, property_name)
31
- property_observer_list(property_name).delete(observer)
32
- end
33
-
34
- def has_observer?(observer, property_name)
35
- property_observer_list(property_name).include?(observer)
36
- end
37
-
38
- def has_observer_for_any_property?(observer)
39
- property_observer_hash.values.map(&:to_a).sum.include?(observer)
40
- end
41
-
42
- def property_observer_hash
43
- @property_observers ||= Hash.new
44
- end
45
-
46
- def property_observer_list(property_name)
47
- property_observer_hash[property_name.to_sym] = Set.new unless property_observer_hash[property_name.to_sym]
48
- property_observer_hash[property_name.to_sym]
49
- end
50
-
51
- def notify_observers(property_name)
52
- property_observer_list(property_name).each {|observer| observer.call(send(property_name))}
53
- end
54
- #TODO upon updating values, make sure dependent observers are cleared (not added as dependents here)
55
-
56
- def add_property_writer_observers(property_name)
57
- property_writer_name = "#{property_name}="
58
- method(property_writer_name)
59
- ensure_array_object_observer(property_name, send(property_name))
60
- begin
61
- method("__original_#{property_writer_name}")
62
- rescue
63
- # TODO consider alias_method or define_method instead
64
- instance_eval "alias __original_#{property_writer_name} #{property_writer_name}"
65
- instance_eval <<-end_eval, __FILE__, __LINE__
66
- def #{property_writer_name}(value)
67
- old_value = self.#{property_name}
68
- unregister_dependent_observers('#{property_name}', old_value)
69
- self.__original_#{property_writer_name}(value)
70
- notify_observers('#{property_name}')
71
- ensure_array_object_observer('#{property_name}', value, old_value)
72
- end
73
- end_eval
74
- end
75
- rescue => e
76
- # ignore writing if no property writer exists
77
- Glimmer::Config.logger&.debug "No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"
78
- end
79
-
80
- def unregister_dependent_observers(property_name, old_value)
81
- # TODO look into optimizing this
82
- return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
83
- property_observer_list(property_name).each do |observer|
84
- observer.unregister_dependents_with_observable(observer.registration_for(self, property_name), old_value)
85
- end
86
- end
87
-
88
- def ensure_array_object_observer(property_name, object, old_object = nil)
89
- return unless object.is_a?(Array)
90
- array_object_observer = array_object_observer_for(property_name)
91
- array_observer_registration = array_object_observer.observe(object)
92
- property_observer_list(property_name).each do |observer|
93
- my_registration = observer.registration_for(self, property_name) # TODO eliminate repetition
94
- observer.add_dependent(my_registration => array_observer_registration)
95
- end
96
- array_object_observer_for(property_name).unregister(old_object) if old_object.is_a?(ObservableArray)
97
- end
98
-
99
- def array_object_observer_for(property_name)
100
- @array_object_observers ||= {}
101
- unless @array_object_observers.has_key?(property_name)
102
- @array_object_observers[property_name] = ObservableModel::Notifier.new(self, property_name)
103
- end
104
- @array_object_observers[property_name]
105
- end
106
- end
107
- end
108
- end
@@ -1,124 +0,0 @@
1
- require 'glimmer/error'
2
-
3
- module Glimmer
4
- module DataBinding
5
- # Mixin representing Observer trait from Observer Design Pattern
6
- # Allows classes to include without interfering with their
7
- # inheritance hierarchy.
8
- #
9
- # Includes a default implementation that can receive an observer block
10
- # Example: Observer.proc {|new_value| puts new_value}
11
- # Subclasses may override
12
- module Observer
13
- # Observer Proc default implementation that takes an observer block to process updates
14
- # via call method
15
- class Proc
16
- include Observer
17
-
18
- def initialize(&observer_block)
19
- @observer_block = observer_block
20
- end
21
-
22
- # Called by observables once updates occur sending in the new_value if any
23
- def call(new_value=nil)
24
- @observer_block.call(new_value)
25
- end
26
- end
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
-
35
- class << self
36
- def proc(&observer_block)
37
- Proc.new(&observer_block)
38
- end
39
- end
40
-
41
- def registrations
42
- @registrations ||= Set.new
43
- end
44
-
45
- def registration_for(observable, property = nil)
46
- Registration.new(observer: self, observable: observable, property: property)
47
- end
48
-
49
- # mapping of registrations to dependents
50
- # {[observable, property] => [[dependent, dependent_observable, dependent_property], ...]}
51
- def dependents
52
- @dependents ||= Hash.new
53
- end
54
-
55
- def dependents_for(registration)
56
- dependents[registration] ||= Set.new
57
- end
58
-
59
- # registers observer in an observable on a property (optional)
60
- # observer maintains registration list to unregister later
61
- def register(observable, property = nil)
62
- unless observable.is_a?(Observable)
63
- # TODO refactor code to be more smart/polymorphic/automated and honor open/closed principle
64
- if observable.is_a?(Array)
65
- observable.extend(ObservableArray)
66
- else
67
- observable.extend(ObservableModel)
68
- end
69
- end
70
- observable.add_observer(*[self, property].compact)
71
- registration_for(observable, property).tap do |registration|
72
- self.registrations << registration
73
- end
74
- end
75
- alias observe register
76
-
77
- def unregister(observable, property = nil)
78
- # TODO optimize performance in the future via indexing and/or making a registration official object/class
79
- observable.remove_observer(*[self, property].compact)
80
- registration = registration_for(observable, property)
81
- dependents_for(registration).each do |dependent|
82
- dependent.unregister
83
- remove_dependent(registration => dependent)
84
- end
85
- registrations.delete(registration)
86
- end
87
- alias unobserve unregister
88
-
89
- def unregister_dependents_with_observable(registration, dependent_observable)
90
- thedependents = dependents_for(registration).select do |thedependent|
91
- thedependent.observable == dependent_observable
92
- end
93
- thedependents.each do |thedependent|
94
- thedependent.unregister
95
- end
96
- end
97
-
98
- # cleans up all registrations in observables
99
- def unregister_all_observables
100
- registrations.each do |registration|
101
- registration.unregister
102
- end
103
- end
104
- alias unobserve_all_observables unregister_all_observables
105
-
106
- # add dependent observer to unregister when unregistering observer
107
- def add_dependent(parent_to_dependent_hash)
108
- registration = parent_to_dependent_hash.keys.first
109
- dependent = parent_to_dependent_hash.values.first
110
- dependents_for(registration) << dependent
111
- end
112
-
113
- def remove_dependent(parent_to_dependent_hash)
114
- registration = parent_to_dependent_hash.keys.first
115
- dependent = parent_to_dependent_hash.values.first
116
- dependents_for(registration).delete(dependent)
117
- end
118
-
119
- def call(new_value)
120
- raise Error, 'Not implemented!'
121
- end
122
- end
123
- end
124
- end