glimmer 1.0.11 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +427 -353
- data/VERSION +1 -1
- data/glimmer.gemspec +7 -6
- data/lib/glimmer.rb +1 -0
- data/lib/glimmer/config.rb +2 -2
- data/lib/glimmer/data_binding/model_binding.rb +43 -25
- data/lib/glimmer/dsl/engine.rb +13 -7
- data/lib/glimmer/dsl/expression.rb +13 -3
- data/lib/glimmer/dsl/parent_expression.rb +5 -2
- data/lib/glimmer/dsl/static_expression.rb +2 -1
- metadata +11 -9
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
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
|
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
|
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-
|
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.
|
49
|
-
s.summary = "Glimmer
|
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
|
data/lib/glimmer/config.rb
CHANGED
@@ -56,10 +56,10 @@ module Glimmer
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def reset_logger!
|
59
|
-
self.logger = Logger.new(
|
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']
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
268
|
+
object.send(property_method, property_argument, converted_value)
|
252
269
|
else
|
253
|
-
object.send(property_expression,
|
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
|
data/lib/glimmer/dsl/engine.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
178
|
-
|
179
|
-
|
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(
|
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(
|
197
|
+
parent_stack.push(new_parent)
|
192
198
|
begin
|
193
|
-
expression.add_content(
|
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
|
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(
|
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
|
-
|
29
|
-
|
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
|
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-
|
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
|
232
|
-
Library. Used in the Glimmer
|
233
|
-
|
234
|
-
|
235
|
-
XML (& HTML), and the Glimmer
|
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.
|
287
|
+
rubygems_version: 3.2.3
|
286
288
|
signing_key:
|
287
289
|
specification_version: 4
|
288
|
-
summary: Glimmer
|
290
|
+
summary: Glimmer - DSL Engine for Ruby GUI and More
|
289
291
|
test_files: []
|