glimmer 1.0.11 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.11
1
+ 1.3.0
data/glimmer.gemspec CHANGED
@@ -2,19 +2,20 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: glimmer 1.0.11 ruby lib
5
+ # stub: glimmer 1.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer".freeze
9
- s.version = "1.0.11"
9
+ s.version = "1.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["AndyMaleh".freeze]
14
- s.date = "2021-01-27"
15
- s.description = "Glimmer is a Ruby DSL Framework consisting of a DSL Engine and an Observable/Observer/Data-Binding Library. Used in the Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), the Glimmer DSL for Tk (Ruby Desktop Development GUI Library), the Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), the Glimmer DSL for XML (& HTML), and the Glimmer DSL for CSS.".freeze
14
+ s.date = "2021-03-08"
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. Used in the Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), the Glimmer DSL for Tk (Ruby Desktop Development GUI Library), the Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), the Glimmer DSL for XML (& HTML), and the Glimmer DSL for CSS.".freeze
16
16
  s.email = "andy.am@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
18
+ "CHANGELOG.md",
18
19
  "LICENSE.txt",
19
20
  "README.md"
20
21
  ]
@@ -45,8 +46,8 @@ Gem::Specification.new do |s|
45
46
  ]
46
47
  s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
47
48
  s.licenses = ["MIT".freeze]
48
- s.rubygems_version = "3.1.4".freeze
49
- s.summary = "Glimmer Ruby DSL Engine".freeze
49
+ s.rubygems_version = "3.2.3".freeze
50
+ s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
50
51
 
51
52
  if s.respond_to? :specification_version then
52
53
  s.specification_version = 4
data/lib/glimmer.rb CHANGED
@@ -81,6 +81,7 @@ module Glimmer
81
81
  Glimmer.loop_reset!
82
82
  end
83
83
  Glimmer.loop_last_data = new_loop_data
84
+ Glimmer::Config.logger.info {">"*80}
84
85
  Glimmer::Config.logger.info {"Interpreting keyword: #{method_symbol}"}
85
86
  Glimmer::DSL::Engine.interpret(method_symbol, *args, &block)
86
87
  end
@@ -56,10 +56,10 @@ module Glimmer
56
56
  end
57
57
 
58
58
  def reset_logger!
59
- self.logger = Logger.new(STDOUT).tap do |logger|
59
+ self.logger = Logger.new($stdout).tap do |logger|
60
60
  logger.level = Logger::ERROR
61
61
  begin
62
- logger.level = ENV['GLIMMER_LOGGER_LEVEL'].strip.downcase if ENV['GLIMMER_LOGGER_LEVEL']
62
+ logger.level = ENV['GLIMMER_LOGGER_LEVEL']&.strip&.downcase
63
63
  rescue => e
64
64
  puts e.message
65
65
  end
@@ -49,9 +49,7 @@ module Glimmer
49
49
  def nested_models
50
50
  @nested_models = [base_model]
51
51
  model_property_names.reduce(base_model) do |reduced_model, nested_model_property_name|
52
- if reduced_model.nil?
53
- nil
54
- else
52
+ if !reduced_model.nil?
55
53
  invoke_property_reader(reduced_model, nested_model_property_name).tap do |new_reduced_model|
56
54
  @nested_models << new_reduced_model
57
55
  end
@@ -72,21 +70,6 @@ module Glimmer
72
70
  nested_property? ? nested_property_name : property_name_expression
73
71
  end
74
72
 
75
- def convert_on_read(value)
76
- apply_converter(@binding_options[:on_read], value)
77
- end
78
-
79
- def convert_on_write(value)
80
- apply_converter(@binding_options[:on_write], value)
81
- end
82
-
83
- def apply_converter(converter, value)
84
- return value if converter.nil?
85
- return value.send(converter) if (converter.is_a?(String) || converter.is_a?(Symbol)) && value.respond_to?(converter)
86
- return converter.call(value) if converter.respond_to?(:call, value)
87
- raise Glimmer::Error, "Unsupported bind converter: #{converter.inspect}"
88
- end
89
-
90
73
  # All nested property names
91
74
  # e.g. property name expression "address.state" gives ['address', 'state']
92
75
  # If there are any indexed property names, this returns indexes as properties.
@@ -127,7 +110,10 @@ module Glimmer
127
110
  property_name => Observer.proc do |new_value|
128
111
  # Ensure reattaching observers when a higher level nested property is updated (e.g. person.address changes reattaches person.address.street observer)
129
112
  add_observer(observer)
130
- observer.call(evaluate_property)
113
+ converted_value = evaluate_property
114
+ observer.call(converted_value).tap do
115
+ apply_processor(@binding_options[:after_read], converted_value)
116
+ end
131
117
  end
132
118
  )
133
119
  end
@@ -142,7 +128,10 @@ module Glimmer
142
128
  add_nested_observers(observer)
143
129
  else
144
130
  model_binding_observer = Observer.proc do |new_value|
145
- observer.call(evaluate_property)
131
+ converted_value = evaluate_property
132
+ observer.call(converted_value).tap do
133
+ apply_processor(@binding_options[:after_read], converted_value)
134
+ end
146
135
  end
147
136
  observer_registration = model_binding_observer.observe(model, property_name)
148
137
  my_registration = observer.registration_for(self)
@@ -167,7 +156,10 @@ module Glimmer
167
156
  @computed_observer_collection ||= Concurrent::Hash.new
168
157
  unless @computed_observer_collection.has_key?(observer)
169
158
  @computed_observer_collection[observer] = Observer.proc do |new_value|
170
- observer.call(evaluate_property)
159
+ converted_value = evaluate_property
160
+ observer.call(converted_value).tap do
161
+ apply_processor(@binding_options[:after_read], converted_value)
162
+ end
171
163
  end
172
164
  end
173
165
  @computed_observer_collection[observer]
@@ -215,9 +207,10 @@ module Glimmer
215
207
  def evaluate_property
216
208
  value = nil
217
209
  value = invoke_property_reader(model, property_name) unless model.nil?
210
+ apply_processor(@binding_options[:before_read], value)
218
211
  convert_on_read(value)
219
212
  end
220
-
213
+
221
214
  def evaluate_options_property
222
215
  model.send(options_property_name) unless model.nil?
223
216
  end
@@ -230,6 +223,29 @@ module Glimmer
230
223
  property_expression.to_s.start_with?('[')
231
224
  end
232
225
 
226
+ private
227
+
228
+ def convert_on_read(value)
229
+ apply_processor(@binding_options[:on_read], value)
230
+ end
231
+
232
+ def convert_on_write(value)
233
+ apply_processor(@binding_options[:on_write], value)
234
+ end
235
+
236
+ def apply_processor(processor, value)
237
+ return value if processor.nil?
238
+ return value.send(processor) if (processor.is_a?(String) || processor.is_a?(Symbol)) && value.respond_to?(processor)
239
+ return invoke_proc_with_exact_parameters(processor, value) if processor.respond_to?(:call)
240
+ raise Glimmer::Error, "Unsupported bind processor: #{processor.inspect}"
241
+ end
242
+
243
+ def invoke_proc_with_exact_parameters(proc_object, *args)
244
+ return if proc_object.nil?
245
+ args = args[0...proc_object.parameters.size]
246
+ proc_object.call(*args)
247
+ end
248
+
233
249
  def invoke_property_reader(object, property_expression)
234
250
  if property_indexed?(property_expression)
235
251
  property_method = '[]'
@@ -243,15 +259,17 @@ module Glimmer
243
259
 
244
260
  def invoke_property_writer(object, property_expression, value)
245
261
  raise "Cannot invoke `#{property_expression}` because ModelBinding#binding_options[:read_only]=true" if @binding_options[:read_only]
246
- value = convert_on_write(value)
262
+ apply_processor(@binding_options[:before_write], value)
263
+ converted_value = convert_on_write(value)
247
264
  if property_indexed?(property_expression)
248
265
  property_method = '[]='
249
266
  property_argument = property_expression[1...-2]
250
267
  property_argument = property_argument.to_i if property_argument.match(/\d+/)
251
- object.send(property_method, property_argument, value)
268
+ object.send(property_method, property_argument, converted_value)
252
269
  else
253
- object.send(property_expression, value)
270
+ object.send(property_expression, converted_value)
254
271
  end
272
+ apply_processor(@binding_options[:after_write], converted_value)
255
273
  end
256
274
  end
257
275
  end
@@ -37,7 +37,7 @@ module Glimmer
37
37
  STATIC_EXPRESSION_METHOD_FACTORY = lambda do |keyword|
38
38
  lambda do |*args, &block|
39
39
  if Glimmer::DSL::Engine.no_dsls?
40
- puts Glimmer::DSL::Engine::MESSAGE_NO_DSLS # TODO consider switching to an error log statement
40
+ Glimmer::Config.logger.error {Glimmer::DSL::Engine::MESSAGE_NO_DSLS}
41
41
  else
42
42
  retrieved_static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
43
43
  # TODO consider replacing Glimmer::DSL::Engine.static_expressions[keyword].keys - Glimmer::DSL::Engine.disabled_dsls with Glimmer::DSL::Engine.enabled_static_expression_dsls(keyword)
@@ -55,6 +55,7 @@ module Glimmer
55
55
  else
56
56
  raise Glimmer::Error, "Unsupported keyword: #{keyword}" unless static_expression_dsl || retrieved_static_expression
57
57
  Glimmer::DSL::Engine.dsl_stack.push(static_expression_dsl || Glimmer::DSL::Engine.dsl)
58
+ Glimmer::Config.logger.info {"Assuming DSL: #{Glimmer::DSL::Engine.dsl_stack.last}"}
58
59
  static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
59
60
  static_expression_can_interpret = nil
60
61
  if static_expression.nil? || !(static_expression_can_interpret = static_expression.can_interpret?(Glimmer::DSL::Engine.parent, keyword, *args, &block))
@@ -169,15 +170,20 @@ module Glimmer
169
170
  dynamic_expression_dsl = (dynamic_expression_chains_of_responsibility.keys - disabled_dsls).first if dsl.nil?
170
171
  # TODO consider pushing this code into interpret_expresion to provide hooks that work around it regardless of static vs dynamic
171
172
  dsl_stack.push(dynamic_expression_dsl || dsl)
173
+ Glimmer::Config.logger.info {"Assuming DSL: #{dsl_stack.last}"}
172
174
  expression = dynamic_expression_chains_of_responsibility[dsl].handle(parent, keyword, *args, &block)
173
175
  interpret_expression(expression, keyword, *args, &block)
174
176
  end
175
177
 
176
178
  def interpret_expression(expression, keyword, *args, &block)
177
- expression.interpret(parent, keyword, *args, &block).tap do |ui_object|
178
- add_content(ui_object, expression, &block)
179
- dsl_stack.pop
179
+ new_parent = nil
180
+ expression.around(parent, keyword, args, block) do
181
+ new_parent = expression.interpret(parent, keyword, *args, &block).tap do |new_parent|
182
+ add_content(new_parent, expression, keyword, *args, &block)
183
+ dsl_stack.pop
184
+ end
180
185
  end
186
+ new_parent
181
187
  end
182
188
 
183
189
  # Adds content block to parent UI object
@@ -185,12 +191,12 @@ module Glimmer
185
191
  # This allows evaluating parent UI object properties and children
186
192
  #
187
193
  # For example, a shell widget would get properties set and children added
188
- def add_content(parent, expression, &block)
194
+ def add_content(new_parent, expression, keyword, *args, &block)
189
195
  if block_given? && expression.is_a?(ParentExpression)
190
196
  dsl_stack.push(expression.class.dsl)
191
- parent_stack.push(parent)
197
+ parent_stack.push(new_parent)
192
198
  begin
193
- expression.add_content(parent, &block)
199
+ expression.add_content(new_parent, keyword, *args, &block)
194
200
  ensure
195
201
  parent_stack.pop
196
202
  dsl_stack.pop
@@ -47,13 +47,23 @@ module Glimmer
47
47
  raise Error, "#interpret must be implemented by an Expression subclass"
48
48
  end
49
49
 
50
- # Adds block content to specified parent UI object (Optional)
50
+ # Adds block content to newly interpreted parent object (Optional)
51
51
  #
52
52
  # Only expressions that receive a content block should implement
53
- def add_content(parent, &block)
53
+ def add_content(new_parent, keyword, *args, &block)
54
54
  # No Op by default
55
55
  end
56
-
56
+
57
+ # Executes code around the `interpret_and_add_content` block,
58
+ # which invokes `interpret` and `add_content` when called without args
59
+ # (parent, keyword, args, block are supplied automatically).
60
+ # Clients may invoke yield as an alternative to calling `interpret_and_add_content` directly.
61
+ # This method takes parent, keyword, args, block in case they are needed
62
+ # in its around logic.
63
+ def around(parent, keyword, args, block, &interpret_and_add_content)
64
+ interpret_and_add_content.call
65
+ end
66
+
57
67
  # Checks if object is a Symbol or a String
58
68
  def textual?(object)
59
69
  object.is_a?(Symbol) or object.is_a?(String)
@@ -25,8 +25,11 @@ module Glimmer
25
25
  module DSL
26
26
  # Mixin that represents expressions that always have a content block
27
27
  module ParentExpression
28
- def add_content(parent, &block)
29
- block.call(parent)
28
+ # Default implementation that simply invokes block content with newly interpreted parent object as an argument
29
+ #
30
+ # Only expressions that receive a content block should implement
31
+ def add_content(new_parent, keyword, *args, &block)
32
+ block.call(new_parent)
30
33
  end
31
34
  end
32
35
  end
@@ -50,7 +50,8 @@ module Glimmer
50
50
  end
51
51
  end
52
52
 
53
- # Subclasses may optionally implement
53
+ # Subclasses may optionally implement, but by default it only ensures that
54
+ # the keyword matches lower case static expression class name minus `Expression`
54
55
  def can_interpret?(parent, keyword, *args, &block)
55
56
  true
56
57
  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: 1.0.11
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-27 00:00:00.000000000 Z
11
+ date: 2021-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: array_include_methods
@@ -228,15 +228,17 @@ dependencies:
228
228
  - - ">="
229
229
  - !ruby/object:Gem::Version
230
230
  version: '0'
231
- description: Glimmer is a Ruby DSL Framework consisting of a DSL Engine and an Observable/Observer/Data-Binding
232
- Library. Used in the Glimmer DSL for SWT (JRuby Desktop Development GUI Framework),
233
- the Glimmer DSL for Tk (Ruby Desktop Development GUI Library), the Glimmer DSL for
234
- Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), the Glimmer DSL for
235
- XML (& HTML), and the Glimmer DSL for CSS.
231
+ description: Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of
232
+ a DSL Engine and an Observable/Observer/Data-Binding Library. Used in the Glimmer
233
+ DSL for SWT (JRuby Desktop Development GUI Framework), the Glimmer DSL for Tk (Ruby
234
+ Desktop Development GUI Library), the Glimmer DSL for Opal (Pure Ruby Web GUI and
235
+ Auto-Webifier of Desktop Apps), the Glimmer DSL for XML (& HTML), and the Glimmer
236
+ DSL for CSS.
236
237
  email: andy.am@gmail.com
237
238
  executables: []
238
239
  extensions: []
239
240
  extra_rdoc_files:
241
+ - CHANGELOG.md
240
242
  - LICENSE.txt
241
243
  - README.md
242
244
  files:
@@ -282,8 +284,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
282
284
  - !ruby/object:Gem::Version
283
285
  version: '0'
284
286
  requirements: []
285
- rubygems_version: 3.1.4
287
+ rubygems_version: 3.2.3
286
288
  signing_key:
287
289
  specification_version: 4
288
- summary: Glimmer Ruby DSL Engine
290
+ summary: Glimmer - DSL Engine for Ruby GUI and More
289
291
  test_files: []