Skip to content

Commit

Permalink
Version 2.7.8 changes (data-binding improvements):
Browse files Browse the repository at this point in the history
- Allow passing `BindExpression` only 1 argument (e.g. presenter.todos) or 1 argument + 1 hash (e.g. presenter.todos, on_read: -> {})
- `ObserveExpression` always uses `ModelBinding` for arguments to leverage its advanced features, like nested/computed/indexed/keyed data-binding
- In Opal, `ModelBinding` converters/hooks do not require an argument anymore (e.g. can invoke `after_write: -> { do_something }` without block args)
- Fix issue whereby observing `model, :collection` was not firing on collection changes, but observing `model.collection` was firing on collection changes (now both fire on collection changes)
  • Loading branch information
AndyObtiva committed Jul 1, 2024
1 parent a87278f commit bc90b88
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 36 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
Related Change Logs:
- [glimmer-dsl-swt/CHANGELOG.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/CHANGELOG.md)

### 2.7.8

- Allow passing `BindExpression` only 1 argument (e.g. presenter.todos) or 1 argument + 1 hash (e.g. presenter.todos, on_read: -> {})
- `ObserveExpression` always uses `ModelBinding` for arguments to leverage its advanced features, like nested/computed/indexed/keyed data-binding
- In Opal, `ModelBinding` converters/hooks do not require an argument anymore (e.g. can invoke `after_write: -> { do_something }` without block args)
- Fix issue whereby observing `model, :collection` was not firing on collection changes, but observing `model.collection` was firing on collection changes (now both fire on collection changes)

### 2.7.7

- Relax `array_include_methods` gem dependency to '>= 1.4.0', '< 1.6.0'
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ gem 'facets', '>= 3.1.0', '< 4.0.0', require: false
group :development do
gem 'rspec-mocks', '~> 3.5.0'
gem 'rspec', '~> 3.5.0'
gem 'puts_debuggerer', '~> 0.13', require: false
gem 'puts_debuggerer', '>= 1.0.1', require: false
gem 'rake', '>= 10.1.0', '< 14.0.0'
gem 'jeweler', '>= 2.0.0', '< 3.0.0'
gem 'rdoc', '>= 6.2.1', '< 7.0.0'
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 style="position: relative; top: 20px;" />](https://rubygems.org/gems/glimmer) Glimmer 2.7.7
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 style="position: relative; top: 20px;" />](https://rubygems.org/gems/glimmer) Glimmer 2.7.8
## DSL Framework for Ruby GUI and More
[![Gem Version](https://badge.fury.io/rb/glimmer.svg)](http://badge.fury.io/rb/glimmer)
[![rspec](https://github.com/AndyObtiva/glimmer/workflows/rspec/badge.svg)](https://github.com/AndyObtiva/glimmer/actions?query=workflow%3Arspec)
Expand Down Expand Up @@ -268,7 +268,7 @@ end
### Setup

Follow these steps to author a [Glimmer](https://rubygems.org/gems/glimmer) DSL:
- Add `gem 'glimmer', '~> 2.7.7'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.7.7` and add `require 'glimmer'`
- Add `gem 'glimmer', '~> 2.7.8'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.7.8` and add `require 'glimmer'`
- Create `glimmer/dsl/[dsl_name]/dsl.rb`, which requires and adds all dynamic expressions for the [dsl_name] Glimmer DSL module as per the code shown in the previous section (or [Official DSLs](#official-dsls) as examples)
- Create `glimmer/dsl/[dsl_name]/[expresion_name]_expresion.rb` for every [expresion_name] expression needed, whether dynamic or static

Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ unless jeweler_required.nil?
gem.homepage = "http://github.com/AndyObtiva/glimmer"
gem.license = "MIT"
gem.summary = %Q{Glimmer (DSL Framework for Ruby GUI and More)}
gem.description = %Q{Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and a Data-Binding Library (including Observer Design Pattern, 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 LibUI (Prerequisite-Free Ruby Desktop Development GUI Library and Winner of Fukuoka Ruby Award Competition 2022 Special Award), Glimmer DSL for Tk (Ruby Tk Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library), Glimmer DSL for WX (wxWidgets Ruby Desktop Development GUI Library), Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library), Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.}
gem.description = %Q{Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and a Data-Binding Library (including Observer Design Pattern, Observable Model, Observable Array, and Observable Hash). Used in Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library and Winner of Fukuoka Ruby Award Competition 2022 Special Award), Glimmer DSL for Tk (Ruby Tk Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library), Glimmer DSL for WX (wxWidgets Ruby Desktop Development GUI Library), Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library), Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.}
gem.email = "andy.am@gmail.com"
gem.authors = ["AndyMaleh"]
# gem.executables = ['glimmer', 'girb'] # moved to glimmer-dsl-swt for now
Expand Down
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ Related TODO files:

## Next

- Observe an array or nested arrays for all children changes on a specific property (e.g. observe(@game, 'tetris_blocks[][].color') ; returns |new_color, tetris_block| / observe(@game.players, '[].name') ; returns |name, player|)
- Observe multiple attributes (e.g. observe(@game, [:width, :height]) returns |value, attribute_name|)
- Fix issue with computed data-binding when combined with nested/indexed data-binding (it looks up computed attributes on root object instead of nested object, it seems)
- Support nested computed attributes (e.g. computed_by: {address1: [:street, :city, :state, :zip]})
- Consider the idea of having Observer#observe accept an optional block to do observation without implementing `call` (kinda like when using the `observe` keyword in the Glimmer DSL).
- Observe an array for all children changes on a specific property (e.g. observe(@game, 'blocks[][].color') ; returns |new_color, block|)
- Ensure removing observers from hash in ObservableModel when removed from observable
- Avoid `< Struct.new` in specs (tests)
- Add built-in support to Glimmer::DSL::Engine to memoize/cache expressions similar to how that is supported for StaticExpression (but allowing an outside keyword and non-static expression to be used)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.7.7
2.7.8
32 changes: 16 additions & 16 deletions glimmer.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
# stub: glimmer 2.7.7 ruby lib
# stub: glimmer 2.7.8 ruby lib

Gem::Specification.new do |s|
s.name = "glimmer".freeze
s.version = "2.7.7".freeze
s.version = "2.7.8"

s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["AndyMaleh".freeze]
s.date = "2024-01-10"
s.date = "2024-07-01"
s.description = "Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and a Data-Binding Library (including Observer Design Pattern, 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 LibUI (Prerequisite-Free Ruby Desktop Development GUI Library and Winner of Fukuoka Ruby Award Competition 2022 Special Award), Glimmer DSL for Tk (Ruby Tk Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library), Glimmer DSL for WX (wxWidgets Ruby Desktop Development GUI Library), Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library), Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
s.email = "andy.am@gmail.com".freeze
s.extra_rdoc_files = [
Expand Down Expand Up @@ -53,22 +53,22 @@ Gem::Specification.new do |s|
]
s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
s.licenses = ["MIT".freeze]
s.rubygems_version = "3.5.3".freeze
s.rubygems_version = "3.4.10".freeze
s.summary = "Glimmer (DSL Framework for Ruby GUI and More)".freeze

s.specification_version = 4

s.add_runtime_dependency(%q<array_include_methods>.freeze, [">= 1.4.0".freeze, "< 1.6.0".freeze])
s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0".freeze, "< 4.0.0".freeze])
s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0".freeze])
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0".freeze])
s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13".freeze])
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0".freeze, "< 14.0.0".freeze])
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0".freeze, "< 3.0.0".freeze])
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1".freeze, "< 7.0.0".freeze])
s.add_development_dependency(%q<coveralls>.freeze, [">= 0".freeze])
s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1".freeze])
s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0".freeze])
s.add_development_dependency(%q<rake-tui>.freeze, ["> 0".freeze])
s.add_runtime_dependency(%q<array_include_methods>.freeze, [">= 1.4.0", "< 1.6.0"])
s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 1.0.1"])
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
s.add_development_dependency(%q<rake-tui>.freeze, ["> 0"])
end

9 changes: 3 additions & 6 deletions lib/glimmer/data_binding/model_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ def nested_property_observers_for(observer)
end

def add_observer(observer, extra_options = {})
# TODO couldn't we have a scenario where it is both computed? and nested_property? at the same time?
# or computed and not nested at the same time (else statement)?
if computed?
add_computed_observers(observer)
elsif nested_property?
Expand Down Expand Up @@ -252,12 +254,7 @@ def apply_processor(processor, value)

def invoke_proc_with_exact_parameters(proc_object, *args)
return if proc_object.nil?
if RUBY_ENGINE == 'opal'
# opal doesn't support proc_object.parameters.size properly it seems
args = Concurrent::Array.new(args[0...1])
else
args = Concurrent::Array.new(args[0...proc_object.parameters.size])
end
args = Concurrent::Array.new(args[0...proc_object.parameters.size])
proc_object.call(*args)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/glimmer/data_binding/observable_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def add_observer(observer, property_name, options = {})
initialize_observer_options(options)
return observer if has_observer?(observer, property_name)
property_observer_list(property_name) << observer
ensure_array_object_observer(property_name, send(property_name), nil, options)
add_property_writer_observers(property_name, options)
open_struct_loaded = !!::OpenStruct rescue false
add_key_writer_observer(property_name, options) if is_a?(Struct) || (open_struct_loaded && is_a?(OpenStruct))
Expand Down Expand Up @@ -117,7 +118,6 @@ def add_property_writer_observers(property_name, options)
begin
property_writer_name = attribute_writer_type.to_s.gsub('attribute', property_name.to_s)
method(property_writer_name)
ensure_array_object_observer(property_name, send(property_name), nil, options)
begin
method("__original__#{property_writer_name}")
rescue
Expand Down
12 changes: 10 additions & 2 deletions lib/glimmer/dsl/bind_expression.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ def can_interpret?(parent, keyword, *args, &block)
(
keyword == 'bind' and
(
(
(args.size == 1)
) ||
(
(args.size == 2) and
textual?(args[1])
) ||
(
(args.size == 2) and
(args[1].is_a?(Hash))
) ||
(
(args.size == 3) and
Expand All @@ -43,11 +50,12 @@ def can_interpret?(parent, keyword, *args, &block)
)
)
end


def interpret(parent, keyword, *args, &block)
binding_options = args[2] || {}
binding_options = args.last.is_a?(Hash) ? args.pop : {}
binding_options[:on_read] = binding_options.delete(:on_read) || binding_options.delete('on_read') || block
DataBinding::ModelBinding.new(args[0], args[1].to_s, binding_options)
DataBinding::ModelBinding.new(*args, binding_options)
end
end
end
Expand Down
6 changes: 1 addition & 5 deletions lib/glimmer/dsl/observe_expression.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ def can_interpret?(parent, keyword, *args, &block)

def interpret(parent, keyword, *args, &block)
observer = DataBinding::Observer.proc(&block)
if args[1].to_s.match(REGEX_NESTED_OR_INDEXED_PROPERTY)
observer_registration = observer.observe(DataBinding::ModelBinding.new(*args))
else
observer_registration = observer.observe(*args)
end
observer_registration = observer.observe(DataBinding::ModelBinding.new(*args))
observer_registration
end
end
Expand Down

0 comments on commit bc90b88

Please sign in to comment.