glimmer 2.4.0 → 2.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/glimmer.gemspec CHANGED
@@ -1,89 +1,90 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
- # stub: glimmer 2.4.0 ruby lib
6
-
7
- Gem::Specification.new do |s|
8
- s.name = "glimmer".freeze
9
- s.version = "2.4.0"
10
-
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib".freeze]
13
- s.authors = ["AndyMaleh".freeze]
14
- s.date = "2021-10-15"
15
- s.description = "Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and an Observable / Observer / Data-Binding Library (including Observable Model, Observable Array, and Observable Hash). Used in Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), Glimmer DSL for Tk (Ruby Desktop Development GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
16
- s.email = "andy.am@gmail.com".freeze
17
- s.extra_rdoc_files = [
18
- "CHANGELOG.md",
19
- "LICENSE.txt",
20
- "README.md"
21
- ]
22
- s.files = [
23
- "CHANGELOG.md",
24
- "CONTRIBUTING.md",
25
- "LICENSE.txt",
26
- "PROCESS.md",
27
- "README.md",
28
- "VERSION",
29
- "glimmer.gemspec",
30
- "lib/glimmer.rb",
31
- "lib/glimmer/config.rb",
32
- "lib/glimmer/data_binding/model_binding.rb",
33
- "lib/glimmer/data_binding/observable.rb",
34
- "lib/glimmer/data_binding/observable_array.rb",
35
- "lib/glimmer/data_binding/observable_hash.rb",
36
- "lib/glimmer/data_binding/observable_model.rb",
37
- "lib/glimmer/data_binding/observer.rb",
38
- "lib/glimmer/data_binding/shine.rb",
39
- "lib/glimmer/dsl/bind_expression.rb",
40
- "lib/glimmer/dsl/engine.rb",
41
- "lib/glimmer/dsl/expression.rb",
42
- "lib/glimmer/dsl/expression_handler.rb",
43
- "lib/glimmer/dsl/observe_expression.rb",
44
- "lib/glimmer/dsl/parent_expression.rb",
45
- "lib/glimmer/dsl/static_expression.rb",
46
- "lib/glimmer/dsl/top_level_expression.rb",
47
- "lib/glimmer/error.rb",
48
- "lib/glimmer/ext/module.rb",
49
- "lib/glimmer/invalid_keyword_error.rb",
50
- "lib/glimmer/shim/concurrent.rb"
51
- ]
52
- s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
53
- s.licenses = ["MIT".freeze]
54
- s.rubygems_version = "3.2.22".freeze
55
- s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
56
-
57
- if s.respond_to? :specification_version then
58
- s.specification_version = 4
59
- end
60
-
61
- if s.respond_to? :add_runtime_dependency then
62
- s.add_runtime_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
63
- s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
64
- s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
65
- s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
66
- s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
67
- s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
68
- s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
69
- s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
70
- s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
71
- s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
72
- s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
73
- s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
74
- else
75
- s.add_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
76
- s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
77
- s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
78
- s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
79
- s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
80
- s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
81
- s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
82
- s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
83
- s.add_dependency(%q<coveralls>.freeze, [">= 0"])
84
- s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
85
- s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
86
- s.add_dependency(%q<rake-tui>.freeze, [">= 0"])
87
- end
88
- end
89
-
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: glimmer 2.5.3 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "glimmer".freeze
9
+ s.version = "2.5.3"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["AndyMaleh".freeze]
14
+ s.date = "2021-12-07"
15
+ s.description = "Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and an Observable / Observer / Data-Binding Library (including Observable Model, Observable Array, and Observable Hash). Used in Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), Glimmer DSL for Tk (Ruby Desktop Development GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
16
+ s.email = "andy.am@gmail.com".freeze
17
+ s.extra_rdoc_files = [
18
+ "CHANGELOG.md",
19
+ "LICENSE.txt",
20
+ "README.md"
21
+ ]
22
+ s.files = [
23
+ "CHANGELOG.md",
24
+ "CONTRIBUTING.md",
25
+ "LICENSE.txt",
26
+ "PROCESS.md",
27
+ "README.md",
28
+ "VERSION",
29
+ "glimmer.gemspec",
30
+ "lib/glimmer.rb",
31
+ "lib/glimmer/config.rb",
32
+ "lib/glimmer/data_binding/model_binding.rb",
33
+ "lib/glimmer/data_binding/observable.rb",
34
+ "lib/glimmer/data_binding/observable_array.rb",
35
+ "lib/glimmer/data_binding/observable_hash.rb",
36
+ "lib/glimmer/data_binding/observable_hashable.rb",
37
+ "lib/glimmer/data_binding/observable_model.rb",
38
+ "lib/glimmer/data_binding/observer.rb",
39
+ "lib/glimmer/data_binding/shine.rb",
40
+ "lib/glimmer/dsl/bind_expression.rb",
41
+ "lib/glimmer/dsl/engine.rb",
42
+ "lib/glimmer/dsl/expression.rb",
43
+ "lib/glimmer/dsl/expression_handler.rb",
44
+ "lib/glimmer/dsl/observe_expression.rb",
45
+ "lib/glimmer/dsl/parent_expression.rb",
46
+ "lib/glimmer/dsl/static_expression.rb",
47
+ "lib/glimmer/dsl/top_level_expression.rb",
48
+ "lib/glimmer/error.rb",
49
+ "lib/glimmer/ext/module.rb",
50
+ "lib/glimmer/invalid_keyword_error.rb",
51
+ "lib/glimmer/shim/concurrent.rb"
52
+ ]
53
+ s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
54
+ s.licenses = ["MIT".freeze]
55
+ s.rubygems_version = "3.2.22".freeze
56
+ s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
57
+
58
+ if s.respond_to? :specification_version then
59
+ s.specification_version = 4
60
+ end
61
+
62
+ if s.respond_to? :add_runtime_dependency then
63
+ s.add_runtime_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
64
+ s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
65
+ s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
66
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
67
+ s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
68
+ s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
69
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
70
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
71
+ s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
72
+ s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
73
+ s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
74
+ s.add_development_dependency(%q<rake-tui>.freeze, ["> 0"])
75
+ else
76
+ s.add_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
77
+ s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
78
+ s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
79
+ s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
80
+ s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
81
+ s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
82
+ s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
83
+ s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
84
+ s.add_dependency(%q<coveralls>.freeze, [">= 0"])
85
+ s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
86
+ s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
87
+ s.add_dependency(%q<rake-tui>.freeze, ["> 0"])
88
+ end
89
+ end
90
+
@@ -30,9 +30,9 @@ module Glimmer
30
30
 
31
31
  attr_reader :binding_options, :property_name_expression
32
32
 
33
- def initialize(base_model, property_name_expression, binding_options = nil)
34
- @base_model = base_model
35
- @property_name_expression = property_name_expression
33
+ def initialize(*args)
34
+ binding_options = args.pop if args.size > 1 && args.last.is_a?(Hash)
35
+ @base_model, @property_name_expression = args
36
36
  @binding_options = binding_options || Concurrent::Hash.new
37
37
  if computed?
38
38
  @computed_model_bindings = Concurrent::Array.new(computed_by.map do |computed_by_property_expression|
@@ -91,7 +91,7 @@ module Glimmer
91
91
  end
92
92
 
93
93
  def nested_property?
94
- property_name_expression.match(/[.\[]/)
94
+ property_name_expression.to_s.match(/[.\[]/)
95
95
  end
96
96
 
97
97
  def computed?
@@ -137,7 +137,7 @@ module Glimmer
137
137
  apply_processor(@binding_options[:after_read], converted_value)
138
138
  end
139
139
  end
140
- observer_registration = model_binding_observer.observe(model, property_name, observation_options)
140
+ observer_registration = model_binding_observer.observe(*[model, property_name, observation_options].compact)
141
141
  my_registration = observer.registration_for(self)
142
142
  observer.add_dependent(my_registration => observer_registration)
143
143
  end
@@ -206,7 +206,7 @@ module Glimmer
206
206
  def call(value, *extra_args)
207
207
  return if model.nil?
208
208
  converted_value = value
209
- invoke_property_writer(model, "#{property_name}=", converted_value) unless converted_value == evaluate_property
209
+ invoke_property_writer(model, model.is_a?(Hash) ? property_name : "#{property_name}=", converted_value) unless converted_value == evaluate_property || property_name.nil?
210
210
  end
211
211
 
212
212
  def evaluate_property
@@ -263,11 +263,18 @@ module Glimmer
263
263
  property_argument = property_argument.to_i if property_argument.match(/\d+/)
264
264
  object.send(property_method, property_argument)
265
265
  else
266
- object.send(property_expression)
266
+ if property_expression.nil?
267
+ object
268
+ elsif object.is_a?(Hash)
269
+ object[property_expression]
270
+ else
271
+ object.send(property_expression)
272
+ end
267
273
  end
268
274
  end
269
275
 
270
276
  def invoke_property_writer(object, property_expression, value)
277
+ return if property_expression.nil?
271
278
  raise "Cannot invoke `#{property_expression}` because ModelBinding#binding_options[:read_only]=true" if @binding_options[:read_only]
272
279
  apply_processor(@binding_options[:before_write], value)
273
280
  converted_value = convert_on_write(value)
@@ -277,7 +284,11 @@ module Glimmer
277
284
  property_argument = property_argument.to_i if property_argument.match(/\d+/)
278
285
  object.send(property_method, property_argument, converted_value)
279
286
  else
280
- object.send(property_expression, converted_value)
287
+ if object.is_a?(Hash)
288
+ object[property_expression] = converted_value
289
+ else
290
+ object.send(property_expression, converted_value)
291
+ end
281
292
  end
282
293
  apply_processor(@binding_options[:after_write], converted_value)
283
294
  end
@@ -50,15 +50,19 @@ module Glimmer
50
50
  element_properties = args
51
51
  element_properties = element_properties.flatten.compact.uniq
52
52
  return observer if has_observer?(observer) && has_observer_element_properties?(observer, element_properties)
53
- property_observer_list << observer
54
- observer_element_properties[observer] = element_properties_for(observer) + Concurrent::Set.new(element_properties)
53
+ property_observer_list[observer] = options
54
+ observer_element_properties[observer] = Concurrent::Set.new(Concurrent::Array.new(element_properties_for(observer).to_a) + Concurrent::Array.new(element_properties)) # converting to Array as a workaround to jruby-9.3.2.0 issue TODO remove this workaround when no longer needed
55
+ if !options.empty? && options[:recursive].is_a?(Integer)
56
+ options = options.clone
57
+ options[:recursive] = options[:recursive] - 1
58
+ end
55
59
  each { |element| add_element_observer(element, observer, options) }
56
60
  observer
57
61
  end
58
62
 
59
- def add_element_observers(element, options = {})
60
- property_observer_list.each do |observer|
61
- add_element_observer(element, observer, options)
63
+ def add_element_observers(element, general_options = {})
64
+ property_observer_list.each do |observer, options|
65
+ add_element_observer(element, observer, options.merge(general_options))
62
66
  end
63
67
  end
64
68
 
@@ -66,14 +70,16 @@ module Glimmer
66
70
  element_properties_for(observer).each do |property|
67
71
  observer.observe(element, property, options)
68
72
  end
69
- ensure_array_object_observer(element, options) if options[:recursive] && element.is_a?(Array)
73
+ if element.is_a?(Array) && (options[:recursive] == true || (options[:recursive].is_a?(Integer) && options[:recursive] >= 0))
74
+ ensure_array_object_observer(element, options)
75
+ end
70
76
  end
71
77
 
72
78
  def ensure_array_object_observer(object, options)
73
79
  return unless object&.is_a?(Array)
74
80
  array_object_observer = array_object_observer_for(object)
75
81
  array_observer_registration = array_object_observer.observe(object, options)
76
- property_observer_list.each do |observer|
82
+ property_observer_list.each do |observer, options|
77
83
  my_registration = observer.registration_for(self)
78
84
  observer.add_dependent(my_registration => array_observer_registration)
79
85
  end
@@ -91,7 +97,7 @@ module Glimmer
91
97
  element_properties = element_properties.flatten.compact.uniq
92
98
  if !element_properties.empty?
93
99
  old_element_properties = element_properties_for(observer)
94
- observer_element_properties[observer] = element_properties_for(observer) - Concurrent::Set.new(element_properties)
100
+ observer_element_properties[observer] = Concurrent::Set.new(Concurrent::Array.new(element_properties_for(observer).to_a) - Concurrent::Array.new(element_properties)) # TODO remove this workaround when no longer needed (it is for jruby-9.3.2.0 issue)
95
101
  each { |element| element_properties.each { |property| observer.unobserve(element, property) } }
96
102
  end
97
103
  if element_properties_for(observer).empty?
@@ -103,7 +109,7 @@ module Glimmer
103
109
  end
104
110
 
105
111
  def remove_element_observers(element)
106
- property_observer_list.each do |observer|
112
+ property_observer_list.each do |observer, options|
107
113
  remove_element_observer(element, observer)
108
114
  end
109
115
  end
@@ -114,15 +120,15 @@ module Glimmer
114
120
  end
115
121
  if element.is_a?(ObservableArray)
116
122
  array_object_observer_for(element).unobserve(element)
117
- element.property_observer_list.select {|o| o.respond_to?(:observable_array) && o.observable_array == self}.each do |o|
118
- o.deregister_all_observables
123
+ element.property_observer_list.select {|obs, opt| obs.respond_to?(:observable_array) && obs.observable_array == self}.each do |o|
124
+ o.deregister_all_observables if o.respond_to?(:deregister_all_observables)
119
125
  @array_object_observers.reject! {|k, v| v == o}
120
126
  end
121
127
  end
122
128
  end
123
129
 
124
130
  def has_observer?(observer)
125
- property_observer_list.include?(observer)
131
+ property_observer_list.keys.include?(observer)
126
132
  end
127
133
 
128
134
  def has_observer_element_properties?(observer, element_properties)
@@ -130,7 +136,7 @@ module Glimmer
130
136
  end
131
137
 
132
138
  def property_observer_list
133
- @property_observer_list ||= Concurrent::Set.new
139
+ @property_observer_list ||= Concurrent::Hash.new
134
140
  end
135
141
 
136
142
  def observer_element_properties
@@ -142,7 +148,7 @@ module Glimmer
142
148
  end
143
149
 
144
150
  def notify_observers
145
- property_observer_list.to_a.each { |o| o.call(self) }
151
+ property_observer_list.to_a.each { |obs, opt| obs.call(self) }
146
152
  end
147
153
 
148
154
  def <<(element)
@@ -366,7 +372,7 @@ module Glimmer
366
372
 
367
373
  def unregister_dependent_observers(old_value)
368
374
  return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
369
- property_observer_list.each { |observer| observer.unregister_dependents_with_observable(observer.registration_for(self), old_value) }
375
+ property_observer_list.each { |observer, options| observer.unregister_dependents_with_observable(observer.registration_for(self), old_value) }
370
376
  end
371
377
  alias deregister_dependent_observers unregister_dependent_observers
372
378
  end
@@ -19,13 +19,13 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- require 'glimmer/data_binding/observable'
22
+ require 'glimmer/data_binding/observable_hashable'
23
23
  require 'glimmer/data_binding/observer'
24
24
 
25
25
  module Glimmer
26
26
  module DataBinding
27
27
  module ObservableHash
28
- include Observable
28
+ include ObservableHashable
29
29
 
30
30
  class Notifier
31
31
  include Observer
@@ -40,28 +40,6 @@ module Glimmer
40
40
  end
41
41
  end
42
42
 
43
- OBSERVED_STORE_METHOD = lambda do |key, value|
44
- if key_observer_list(key).empty?
45
- if all_key_observer_list.empty?
46
- self.send('__original__store', key, value)
47
- else
48
- old_value = self[key]
49
- unregister_dependent_observers(nil, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer
50
- self.send('__original__store', key, value)
51
- notify_observers(key)
52
- ensure_array_object_observer(nil, value, old_value)
53
- ensure_hash_object_observer(nil, value, old_value)
54
- end
55
- else
56
- old_value = self[key]
57
- unregister_dependent_observers(key, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer
58
- self.send('__original__store', key, value)
59
- notify_observers(key)
60
- ensure_array_object_observer(key, value, old_value)
61
- ensure_hash_object_observer(key, value, old_value)
62
- end
63
- end
64
-
65
43
  def add_observer(observer, key = nil, options = {})
66
44
  if key.is_a?(Hash)
67
45
  options = key
@@ -106,7 +84,7 @@ module Glimmer
106
84
  end
107
85
 
108
86
  def key_observer_hash
109
- @key_observers ||= Hash.new
87
+ @key_observers ||= Concurrent::Hash.new
110
88
  end
111
89
 
112
90
  def key_observer_list(key)
@@ -123,24 +101,6 @@ module Glimmer
123
101
  (key_observer_list(key).to_a - all_key_observer_list.to_a).each { |observer| observer.call(self[key], key) }
124
102
  end
125
103
 
126
- def add_key_writer_observer(key = nil, options)
127
- ensure_array_object_observer(key, self[key], nil, options)
128
- ensure_hash_object_observer(key, self[key], nil, options)
129
- begin
130
- method('__original__store')
131
- rescue
132
- define_singleton_method('__original__store', store_method)
133
- define_singleton_method('[]=', &OBSERVED_STORE_METHOD)
134
- end
135
- rescue => e
136
- #ignore writing if no key writer exists
137
- Glimmer::Config.logger.debug {"No need to observe store method: '[]='\n#{e.message}\n#{e.backtrace.join("\n")}"}
138
- end
139
-
140
- def store_method
141
- self.class.instance_method('[]=') rescue self.method('[]=')
142
- end
143
-
144
104
  def unregister_dependent_observers(key, old_value)
145
105
  # TODO look into optimizing this
146
106
  return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray) || old_value.is_a?(ObservableHash)
@@ -166,24 +126,6 @@ module Glimmer
166
126
  @array_object_observers[key]
167
127
  end
168
128
 
169
- def ensure_hash_object_observer(key, object, old_object = nil, options = {})
170
- options ||= {}
171
- return unless object&.is_a?(Hash)
172
- hash_object_observer = hash_object_observer_for(key)
173
- hash_observer_registration = hash_object_observer.observe(object, options)
174
- key_observer_list(key).each do |observer|
175
- my_registration = observer.registration_for(self, key) # TODO eliminate repetition
176
- observer.add_dependent(my_registration => hash_observer_registration)
177
- end
178
- hash_object_observer_for(key).unregister(old_object) if old_object.is_a?(ObservableHash)
179
- end
180
-
181
- def hash_object_observer_for(key)
182
- @hash_object_observers ||= Concurrent::Hash.new
183
- @hash_object_observers[key] = ObservableModel::Notifier.new(self, key) unless @hash_object_observers.has_key?(key)
184
- @hash_object_observers[key]
185
- end
186
-
187
129
  def delete(key, &block)
188
130
  old_value = self[key]
189
131
  unless old_value.nil?
@@ -0,0 +1,75 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/data_binding/observable'
23
+
24
+ module Glimmer
25
+ module DataBinding
26
+ # Represents a Hash-like object with attributes writable via :[]= store method like Hash, Struct, and OpenStruct
27
+ # Expects including class to have the following methods:
28
+ # - key_observer_list
29
+ # - all_key_observer_list
30
+ # - unregister_dependent_observer
31
+ # - ensure_array_object_observer
32
+ module ObservableHashable
33
+ include Observable
34
+
35
+ OBSERVED_STORE_METHOD = lambda do |options|
36
+ lambda do |key, value|
37
+ if key_observer_list(key).empty?
38
+ if all_key_observer_list.empty?
39
+ self.send('__original__store', key, value)
40
+ else
41
+ old_value = self[key]
42
+ unregister_dependent_observers(nil, old_value) # remove dependent observers previously installed in ensure_array_object_observer
43
+ self.send('__original__store', key, value)
44
+ notify_observers(key)
45
+ ensure_array_object_observer(nil, value, old_value, options)
46
+ end
47
+ else
48
+ old_value = self[key]
49
+ unregister_dependent_observers(key, old_value) # remove dependent observers previously installed in ensure_array_object_observer
50
+ self.send('__original__store', key, value)
51
+ notify_observers(key)
52
+ ensure_array_object_observer(key, value, old_value, options)
53
+ end
54
+ end
55
+ end
56
+
57
+ def add_key_writer_observer(key = nil, options)
58
+ ensure_array_object_observer(key, self[key], nil, options)
59
+ begin
60
+ method('__original__store')
61
+ rescue
62
+ define_singleton_method('__original__store', store_method)
63
+ define_singleton_method('[]=', &OBSERVED_STORE_METHOD.call(options))
64
+ end
65
+ rescue => e
66
+ #ignore writing if no key writer exists
67
+ Glimmer::Config.logger.debug {"No need to observe store method: '[]='\n#{e.message}\n#{e.backtrace.join("\n")}"}
68
+ end
69
+
70
+ def store_method
71
+ self.class.instance_method('[]=') rescue self.method('[]=')
72
+ end
73
+ end
74
+ end
75
+ end