glimmer 0.9.0 → 0.9.5

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.
@@ -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: