glimmer 0.9.0 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,127 @@
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
125
+
126
+ require 'glimmer/data_binding/observable_model'
127
+ require 'glimmer/data_binding/observable_array'
@@ -11,6 +11,8 @@ module Glimmer
11
11
  # When DSL engine interprets an expression, it attempts to handle
12
12
  # with ordered expression array specified via `.expressions=` method.
13
13
  class Engine
14
+ MESSAGE_NO_DSLS = "Glimmer has no DSLs configured. Add glimmer-dsl-swt gem or visit https://github.com/AndyObtiva/glimmer#multi-dsl-support for more details.\n"
15
+
14
16
  class << self
15
17
  def dsl=(dsl_name)
16
18
  dsl_name = dsl_name&.to_sym
@@ -56,6 +58,10 @@ module Glimmer
56
58
  dsl_stack.clear
57
59
  disabled_dsls.clear
58
60
  end
61
+
62
+ def no_dsls?
63
+ static_expressions.empty? && dynamic_expression_chains_of_responsibility.empty?
64
+ end
59
65
 
60
66
  # Dynamic expression chains of responsibility indexed by dsl
61
67
  def dynamic_expression_chains_of_responsibility
@@ -65,6 +71,16 @@ module Glimmer
65
71
  # Static expressions indexed by keyword and dsl
66
72
  def static_expressions
67
73
  @static_expressions ||= {}
74
+ end
75
+
76
+ # Sets dynamic expression chains of responsibility. Useful for internal testing
77
+ def dynamic_expression_chains_of_responsibility=(chains)
78
+ @dynamic_expression_chains_of_responsibility = chains
79
+ end
80
+
81
+ # Sets static expressions. Useful for internal testing
82
+ def static_expressions=(expressions)
83
+ @static_expressions = expressions
68
84
  end
69
85
 
70
86
  # Sets an ordered array of DSL expressions to support
@@ -94,15 +110,16 @@ module Glimmer
94
110
  static_expressions[keyword] ||= {}
95
111
  static_expressions[keyword][static_expression_dsl] = static_expression
96
112
  Glimmer.send(:define_method, keyword) do |*args, &block|
97
- begin
98
- retrieved_static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
113
+ if Glimmer::DSL::Engine.no_dsls?
114
+ puts Glimmer::DSL::Engine::MESSAGE_NO_DSLS
115
+ else
116
+ retrieved_static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
99
117
  static_expression_dsl = (Glimmer::DSL::Engine.static_expressions[keyword].keys - Glimmer::DSL::Engine.disabled_dsls).first if retrieved_static_expression.nil?
100
118
  interpretation = nil
101
119
  if retrieved_static_expression.nil? && Glimmer::DSL::Engine.dsl && (static_expression_dsl.nil? || !Glimmer::DSL::Engine.static_expressions[keyword][static_expression_dsl].is_a?(TopLevelExpression))
102
120
  begin
103
121
  interpretation = Glimmer::DSL::Engine.interpret(keyword, *args, &block)
104
122
  rescue => e
105
- Glimmer::DSL::Engine.reset
106
123
  raise e if static_expression_dsl.nil? || !Glimmer::DSL::Engine.static_expressions[keyword][static_expression_dsl].is_a?(TopLevelExpression)
107
124
  end
108
125
  end
@@ -122,11 +139,7 @@ module Glimmer
122
139
  end
123
140
  end
124
141
  end
125
- rescue StandardError => e
126
- # Glimmer::DSL::Engine.dsl_stack.pop
127
- Glimmer::DSL::Engine.reset
128
- raise e
129
- end
142
+ end
130
143
  end
131
144
  end
132
145
 
@@ -140,6 +153,10 @@ module Glimmer
140
153
 
141
154
  # Interprets Glimmer dynamic DSL expression consisting of keyword, args, and block (e.g. shell(:no_resize) { ... })
142
155
  def interpret(keyword, *args, &block)
156
+ if no_dsls?
157
+ puts MESSAGE_NO_DSLS
158
+ return
159
+ end
143
160
  keyword = keyword.to_s
144
161
  dynamic_expression_dsl = (dynamic_expression_chains_of_responsibility.keys - disabled_dsls).first if dsl.nil?
145
162
  dsl_stack.push(dynamic_expression_dsl || dsl)
@@ -148,10 +165,6 @@ module Glimmer
148
165
  add_content(ui_object, expression, &block)
149
166
  dsl_stack.pop
150
167
  end
151
- rescue StandardError => e
152
- # dsl_stack.pop
153
- reset
154
- raise e
155
168
  end
156
169
 
157
170
  # Adds content block to parent UI object
@@ -163,9 +176,12 @@ module Glimmer
163
176
  if block_given? && expression.is_a?(ParentExpression)
164
177
  dsl_stack.push(expression.class.dsl)
165
178
  parent_stack.push(parent)
166
- expression.add_content(parent, &block)
167
- parent_stack.pop
168
- dsl_stack.pop
179
+ begin
180
+ expression.add_content(parent, &block)
181
+ ensure
182
+ parent_stack.pop
183
+ dsl_stack.pop
184
+ end
169
185
  end
170
186
  end
171
187
 
@@ -0,0 +1,5 @@
1
+ module Glimmer
2
+ # Represents Glimmer errors that occur due to excluded keywords passing through method_missing
3
+ class ExcludedKeywordError < RuntimeError
4
+ end
5
+ end
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.9.0
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-14 00:00:00.000000000 Z
11
+ date: 2020-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -132,6 +132,48 @@ dependencies:
132
132
  - - "<"
133
133
  - !ruby/object:Gem::Version
134
134
  version: 7.0.0
135
+ - !ruby/object:Gem::Dependency
136
+ requirement: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '='
139
+ - !ruby/object:Gem::Version
140
+ version: 0.8.23
141
+ name: coveralls
142
+ type: :development
143
+ prerelease: false
144
+ version_requirements: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - '='
147
+ - !ruby/object:Gem::Version
148
+ version: 0.8.23
149
+ - !ruby/object:Gem::Dependency
150
+ requirement: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - "~>"
153
+ - !ruby/object:Gem::Version
154
+ version: 0.16.1
155
+ name: simplecov
156
+ type: :development
157
+ prerelease: false
158
+ version_requirements: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - "~>"
161
+ - !ruby/object:Gem::Version
162
+ version: 0.16.1
163
+ - !ruby/object:Gem::Dependency
164
+ requirement: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - "~>"
167
+ - !ruby/object:Gem::Version
168
+ version: 0.7.0
169
+ name: simplecov-lcov
170
+ type: :development
171
+ prerelease: false
172
+ version_requirements: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - "~>"
175
+ - !ruby/object:Gem::Version
176
+ version: 0.7.0
135
177
  description: Ruby Desktop Development GUI Library (JRuby on SWT)
136
178
  email: andy.am@gmail.com
137
179
  executables: []
@@ -145,6 +187,11 @@ files:
145
187
  - VERSION
146
188
  - lib/glimmer.rb
147
189
  - lib/glimmer/config.rb
190
+ - lib/glimmer/data_binding/model_binding.rb
191
+ - lib/glimmer/data_binding/observable.rb
192
+ - lib/glimmer/data_binding/observable_array.rb
193
+ - lib/glimmer/data_binding/observable_model.rb
194
+ - lib/glimmer/data_binding/observer.rb
148
195
  - lib/glimmer/dsl/engine.rb
149
196
  - lib/glimmer/dsl/expression.rb
150
197
  - lib/glimmer/dsl/expression_handler.rb
@@ -152,6 +199,7 @@ files:
152
199
  - lib/glimmer/dsl/static_expression.rb
153
200
  - lib/glimmer/dsl/top_level_expression.rb
154
201
  - lib/glimmer/error.rb
202
+ - lib/glimmer/excluded_keyword_error.rb
155
203
  - lib/glimmer/invalid_keyword_error.rb
156
204
  homepage: http://github.com/AndyObtiva/glimmer
157
205
  licenses: