glimmer 2.5.3 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f5103731be03f760a5835564ba6f3be84d2861b9a9c0c6f82fb854070ae3075
4
- data.tar.gz: fce2ab6404b29c93cb068a7e779c32c3a2d4f6abc209468c536acb1413e8cd39
3
+ metadata.gz: 2ffd3369029bb8e3b291c4885ff034ec303595578341e947e21071d86bb90ad0
4
+ data.tar.gz: ba20e80562daf4dd96512e1c4dd4ff0dc3fb015a7039712c80805d2b211b95db
5
5
  SHA512:
6
- metadata.gz: 67bb9d8b80194ec1004c137bc9d5b87525428b64c94063e512a3bb9291f67694440974c496785184d0b62f0d3abac62de6a662ecdff102df17009edb7bac1dd3
7
- data.tar.gz: 767ffd76f607076b4fce5edb70f130da7d777453ca1d94a79e39f5be3c1596b28b11dc29c6e3e98c9f4d2a1133e9ff70678c52cb18805b6e898c8d0d6ec02266
6
+ metadata.gz: a5f25a4abf5eaa792ee955145cfb94449831d7b2da3479152d1d4bd2872eec053b3e9c730e3c94713a0a552a00215239bb6a907a191c3e29aea2e5ed2a307c7c
7
+ data.tar.gz: 5356bc6024b81b3524793fe7feb2b1d858a830af308ee002da5445cd172c04839a104a0e28cdff8c095045268a05b363cdea60fbdc052647aeab5c16f40979cf
data/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  Related Change Logs:
4
4
  - [glimmer-dsl-swt/CHANGELOG.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/CHANGELOG.md)
5
5
 
6
+ ### 2.7.0
7
+
8
+ - Support Hash keyed properties via `ModelBinding` (e.g. property as `some_hash_attribute[:some_key]`, `some_hash_attribute['some_key']`, `some_hash_attribute["some_key"]`)
9
+
10
+ ### 2.6.0
11
+
12
+ - If a static expression cannot handle keyword, it is tried with available dynamic expressions instead of erroring out.
13
+
14
+ ### 2.5.5
15
+
16
+ - Support observing an array object index directly (e.g. `ModelBinding.new(array, '[0]')` as opposed to `ModelBinding.new(self, 'array[0]')`)
17
+ - Extract Shine data-binding expression from Glimmer DSL for SWT to Glimmer as a reusable class: `Glimmer::DSL::ShineDataBindingExpression`
18
+ - Avoid compacting model with property in `ModelBinding` yet only compact property/args and keep model as is get a better error message in the case of a `nil` model
19
+ - Document data-binding options like on_read, after_read, etc...
20
+
21
+ ### 2.5.4
22
+
23
+ - `Glimmer::DataBinding::ObservableModel` support for observing model attributes with specified `:attribute_writer_type` option (default: `:attribute=`), which can be a single symbol or an array (e.g. `attribute_writer_type: [:attribute=, :set_attribute]`). Glimmer automatches attribute name and automatically generates observer notification attribute writer methods.
24
+
6
25
  ### 2.5.3
7
26
 
8
27
  - Provide `Observer#observe` option to tolerate not being able to extend an object for observation by silently not observing such object
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007-2021 Andy Maleh
1
+ Copyright (c) 2007-2022 Andy Maleh
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/PROCESS.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  --
15
15
 
16
- Copyright (c) 2020-2021 Andy Maleh
16
+ Copyright (c) 2020-2022 Andy Maleh
17
17
 
18
18
  Permission is hereby granted, free of charge, to any person obtaining
19
19
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,12 +1,11 @@
1
- # [<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 - DSL Framework for Ruby GUI and More
1
+ # [<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.0
2
+ ## DSL Framework for Ruby GUI and More
2
3
  [![Gem Version](https://badge.fury.io/rb/glimmer.svg)](http://badge.fury.io/rb/glimmer)
3
4
  [![rspec](https://github.com/AndyObtiva/glimmer/workflows/rspec/badge.svg)](https://github.com/AndyObtiva/glimmer/actions?query=workflow%3Arspec)
4
5
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer?branch=master)
5
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/38fbc278022862794414/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer/maintainability)
6
7
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
7
8
 
8
- **[Contributors Wanted! (Submit a Glimmer App Sample to Get Started)](#contributing)**
9
-
10
9
  **(The Original Glimmer Library Handling the World’s Ruby GUI Needs Since 2007. Beware of Imitators!)**
11
10
 
12
11
  [**Glimmer**](https://rubygems.org/gems/glimmer) started out as a [GUI Library](https://github.com/AndyObtiva/glimmer-dsl-swt) and grew into a full-fledged [DSL Framework](#dsl-engine) with support for multiple GUI DSLs. Glimmer's namesake is referring to the Glimmer of Ruby in Graphical User Interfaces (contrary to [popular myth](http://blog.headius.com/2007/11/tab-sweep.html) perpetrated by [Charles Nutter](http://blog.headius.com/2007/11/tab-sweep.html), Glimmer has nothing to do with the ill-fated Whitney Houston movie, which does not in fact share the same name)
@@ -16,7 +15,7 @@ Featured in JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do) an
16
15
 
17
16
  [**Glimmer**](https://rubygems.org/gems/glimmer) is a DSL (Domain-Specific Language) Framework that consists of two things:
18
17
  - [DSL Engine](#dsl-engine): enables building internal DSLs embedded in Ruby (e.g. for GUI, XML, or CSS).
19
- - [Data-Binding Library](#data-binding-library): enables synchronizing GUI with Model Attributes bidirectionally **(now with [Shine](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#shine) syntax support in v2)**.
18
+ - [Data-Binding Library](#data-binding-library): enables synchronizing GUI with Model Attributes bidirectionally **(now with [Shine](#shine-data-binding-syntax) syntax support in v2)**.
20
19
 
21
20
  [**Glimmer**](https://rubygems.org/gems/glimmer) is ***the cream of the crop*** when it comes to building DSLs in Ruby:
22
21
  - Supports building the tersest most concise domain specific language syntax in Ruby.
@@ -27,16 +26,21 @@ Featured in JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do) an
27
26
  - Multiple DSLs may be [mixed](#multi-dsl-support) together safely to achieve maximum expressability, composability, and productivity.
28
27
  - DSLs are fully configurable, so you may activate and deactivate DSLs as per your current needs only.
29
28
 
30
- Start by checking out Glimmer's original GUI DSL, which got extracted into its own gem: [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)
31
-
32
- [**Glimmer**](https://rubygems.org/gems/glimmer) supports the following DSLs:
33
- - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
34
- - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
35
- - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
36
- - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
37
- - [glimmer-dsl-gtk](https://github.com/AndyObtiva/glimmer-dsl-gtk): Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)
38
- - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
39
- - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
29
+ Start by checking out [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt), Glimmer's original GUI DSL (for [JRuby](https://www.jruby.org/)), which got extracted into its own gem; and [Glimmer DSL for LibUI](https://github.com/AndyObtiva/glimmer-dsl-libui), Glimmer's CRuby GUI DSL, which has no prerequisites beyond installing the Ruby gem.
30
+
31
+ **[Glimmer](https://rubygems.org/gems/glimmer) DSL Comparison Table:**
32
+ DSL | Platforms | Native? | Vector Graphics? | Pros | Cons | Prereqs
33
+ ----|-----------|---------|------------------|------|------|--------
34
+ [Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)](https://github.com/AndyObtiva/glimmer-dsl-swt) | Mac / Windows / Linux | Yes | Yes (Canvas Shape DSL) | Very Mature / Scaffolding / Native Executable Packaging / Custom Widgets | Slow JRuby Startup Time / Heavy Memory Footprint | Java / JRuby
35
+ [Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)](https://github.com/AndyObtiva/glimmer-dsl-opal) | All Web Browsers | No | Yes (Canvas Shape DSL) | Simpler than All JavaScript Technologies / Auto-Webify Desktop Apps | Setup Process / Incomplete Alpha | Rails
36
+ [Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-libui) | Mac / Windows / Linux | Yes | Yes (Area API) | Very Simple Setup / Fast Startup Time / Light Memory Footprint | LibUI is an Incomplete Mid-Alpha Only | None Other Than MRI Ruby
37
+ [Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-tk) | Mac / Windows / Linux | Some Native-Themed Widgets (Not Truly Native) | Yes (Canvas) | Fast Startup Time / Light Memory Footprint | Complicated setup / Widgets Do Not Look Truly Native, Espcially on Linux | ActiveTcl / MRI Ruby
38
+ [Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-gtk) | Mac / Windows / Linux | Only on Linux | Yes (Cairo) | Complete Access to GNOME Features on Linux | Not Native on Mac and Windows | None Other Than MRI Ruby on Linux / Brew Packages on Mac / MSYS & MING Toolchains on Windows / MRI Ruby
39
+ [Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-fx) | Mac (requires XQuartz) / Windows / Linux | No | Yes (Canvas) | No Prerequisites on Windows | Widgets Do Not Look Native / Mac Usage Obtrusively Starts XQuartz | None Other Than MRI Ruby on Windows / XQuarts on Mac / MRI Ruby
40
+ [Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-jfx) | Mac / Windows / Linux | No | Yes (javafx.scene.shape and javafx.scene.canvas) | Rich in Custom Widgets | Slow JRuby Startup Time / Heavy Memory Footprint / Widgets Do Not Look Native | Java / JRuby / JavaFX SDK
41
+ [Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-swing) | Mac / Windows / Linux | No | Yes (Java2D) | Very Mature | Slow JRuby Startup Time / Heavy Memory Footprint / Widgets Do Not Look Native | Java / JRuby
42
+ [Glimmer DSL for XML (& HTML)](https://github.com/AndyObtiva/glimmer-dsl-xml) | All Web Browsers | No | Yes (SVG) | Programmable / Lighter-weight Than Actual XML | XML Elements Are Sometimes Not Well-Named (Many Types of Input) | None
43
+ [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css) | All Web Browsers | No | Yes | Programmable | CSS Is Over-Engineered / Too Many Features To Learn | None
40
44
 
41
45
  ## Table of Contents
42
46
 
@@ -48,10 +52,14 @@ Start by checking out Glimmer's original GUI DSL, which got extracted into its o
48
52
  - [Official DSLs](#official-dsls)
49
53
  - [Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)](#glimmer-dsl-for-swt-jruby-desktop-development-gui-framework)
50
54
  - [Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)](#glimmer-dsl-for-opal-pure-ruby-web-gui-and-auto-webifier-of-desktop-apps)
51
- - [Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](#glimmer-dsl-for-tk-mri-ruby-desktop-development-gui-library)
52
55
  - [Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)](#glimmer-dsl-for-libui-prerequisite-free-ruby-desktop-development-gui-library)
56
+ - [Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](#glimmer-dsl-for-tk-mri-ruby-desktop-development-gui-library)
53
57
  - [Glimmer DSL for XML (& HTML)](#glimmer-dsl-for-xml--html)
54
58
  - [Glimmer DSL for CSS](#glimmer-dsl-for-css)
59
+ - [Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-gtk)
60
+ - [Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-fx)
61
+ - [Glimmer DSL for JFX (JRuby JavaFX Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-jfx)
62
+ - [Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library)](https://github.com/AndyObtiva/glimmer-dsl-swing)
55
63
  - [Data-Binding Library](#data-binding-library)
56
64
  - [Glimmer Process](#glimmer-process)
57
65
  - [Resources](#resources)
@@ -72,7 +80,8 @@ Glimmer is fundamentally a DSL Engine that can support any number of DSLs like t
72
80
  Glimmer DSL syntax consists mainly of:
73
81
  - **keywords** (e.g. `table` for a table widget)
74
82
  - **style/args** (e.g. :multi as in `table(:multi)` for a multi-line selection table widget)
75
- - **content (nested attributes/keywords)** (e.g. `{ table_column { text 'Name'} }` as in `table(:multi) { table_column { text 'Name'} }` for a multi-line selection table widget with a table column having header text property `'Name'` as content)
83
+ - **content (nested properties/keywords/listeners)** (e.g. `{ table_column { text 'Name'} }` as in `table(:multi) { table_column { text 'Name'} }` for a multi-line selection table widget with a table column having header text property `'Name'` as content)
84
+ - **methods** (e.g. `shell.show` opens a window)
76
85
 
77
86
  Here is a Hello, World! example from [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt):
78
87
 
@@ -99,7 +108,7 @@ The Glimmer DSL Engine's architecture is based on the following Design Patterns
99
108
  - **Stack Data Structure**: to handle processing parent/child nesting of DSL keyword expressions in the correct order
100
109
  - **Proxy Design Pattern**: to shield consumers of GUI libraries built with Glimmer from low-level GUI widget details
101
110
 
102
- Glimmer's use of the **Interpreter Design Pattern** in processing DSLs is also known as the **Virtual Machine Architectural Style**. After all, DSL expressions are virtual machine opcodes that process nested keywords stored in a stack. I built Glimmer's original DSL back in 2007 without knowing the **Virtual Machine Architectural Style** (except perhaps as an esoteric technology powering Java), but stumbled upon it anyways through following the Gang of Four Design Patterns mentioned above, chiefly the **Interpreter Design Pattern**.
111
+ Glimmer's use of the **Interpreter Design Pattern** in processing DSLs is also known as the **Virtual Machine Architectural Style**. After all, DSL expressions are virtual machine opcodes that process nested keywords stored in a stack. I built Glimmer's original DSL back in 2007 without knowing the **Virtual Machine Architectural Style** (except perhaps as an esoteric technology powering Java), but stumbled upon it anyways through following the Gang of Four Design Patterns mentioned above, chiefly the **Interpreter Design Pattern** and the **Chain of Responsibility Design Pattern**.
103
112
 
104
113
  Every keyword in a Glimmer DSL is represented by a DSL expression that is processed by an `Expression` subclass selected from a chain of expressions (interpreters) pre-configured in a DSL chain of responsibility via `Glimmer::DSL::Engine.add_dynamic_expressions(DSLNameModule, expression_names_array)`.
105
114
 
@@ -177,9 +186,11 @@ module Glimmer
177
186
  end
178
187
  ```
179
188
 
180
- An extra convenience expression module is included called `BindExpression`. It builds a `Glimmer::DataBinding::ModelBinding` object for [data-binding](#data-binding) purposes.
181
- Another convenience expression module is `ObserveExpression`, which enables a one-way `observe` operation.
182
- You may learn more about both by looking at how [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) uses them.
189
+ Extra convenience expression mixins/superclasses for use via inclusion/subclassing in Glimmer GUI libraries:
190
+ - `Glimmer::DSL::BindExpression`: enables usage of `bind` data-binding keyword to build a `Glimmer::DataBinding::ModelBinding` object for [data-binding](#data-binding) purposes.
191
+ - `Glimmer::DSL::ShineDataBindingExpression`: enables [Shine data-binding syntax](#shine-data-binding-syntax) via `Glimmer::DataBinding::Shine`, a facade for the `bind` keyword, hiding it with the `<=>` operator for bidirectional (two-way) data-binding and the `<=` operator for unidirectional (one-way) data-binding.
192
+ - `Glimmer::DSL::ObserveExpression`: enables a one-way `observe` operation.
193
+ You may learn more about them by looking at how [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) uses them.
183
194
 
184
195
  DSL expressions go into the `glimmer/dsl/{dsl_name}` namespace directory.
185
196
 
@@ -230,7 +241,7 @@ end
230
241
  ### Setup
231
242
 
232
243
  Follow these steps to author a [Glimmer](https://rubygems.org/gems/glimmer) DSL:
233
- - Add `gem 'glimmer', '~> 2.5.3'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.5.3` and add `require 'glimmer'`
244
+ - Add `gem 'glimmer', '~> 2.7.0'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.7.0` and add `require 'glimmer'`
234
245
  - 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)
235
246
  - Create `glimmer/dsl/[dsl_name]/[expresion_name]_expresion.rb` for every [expresion_name] expression needed, whether dynamic or static
236
247
 
@@ -754,146 +765,6 @@ You should see "Apple Calculator Theme"
754
765
 
755
766
  [![Glimmer Calculator Opal Apple Calculator Theme](https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/master/glimmer-cs-calculator-screenshot-opal-apple.png)](http://glimmer-cs-calculator-server.herokuapp.com/welcomes/apple)
756
767
 
757
- #### Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
758
-
759
- [Tcl/Tk](https://www.tcl.tk/) has evolved into a practical desktop GUI toolkit due to gaining truely native looking widgets on Mac, Windows, and Linux in [Tk version 8.5](https://www.tcl.tk/software/tcltk/8.5.html#:~:text=Highlights%20of%20Tk%208.5&text=Font%20rendering%3A%20Now%20uses%20anti,and%20window%20layout%2C%20and%20more.).
760
-
761
- Additionally, [Ruby](https://www.ruby-lang.org/en/) 3.0 Ractor (formerly known as [Guilds](https://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/)) supports truly parallel multi-threading, making both [MRI](https://github.com/ruby/ruby) and [Tk](https://www.tcl.tk/) finally viable for support in [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library) as an alternative to [JRuby on SWT](https://github.com/AndyObtiva/glimmer-dsl-swt).
762
-
763
- The trade-off is that while [SWT](https://www.eclipse.org/swt/) provides a plethora of high quality reusable widgets for the Enterprise (such as [Nebula](https://www.eclipse.org/nebula/)), [Tk](https://www.tcl.tk/) enables very fast app startup time and a small memory footprint via [MRI Ruby](https://www.ruby-lang.org/en/).
764
-
765
- [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk) aims to provide a DSL similar to the [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) to enable more productive desktop development in Ruby with:
766
- - Declarative DSL syntax that visually maps to the GUI widget hierarchy
767
- - Convention over configuration via smart defaults and automation of low-level details
768
- - Requiring the least amount of syntax possible to build GUI
769
- - Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
770
- - Custom Widget support
771
- - Scaffolding for new custom widgets, apps, and gems
772
- - Native-Executable packaging on Mac, Windows, and Linux
773
-
774
- To get started, visit the [Glimmer DSL for Tk project page](https://github.com/AndyObtiva/glimmer-dsl-tk#pre-requisites) for instructions on installing the [glimmer-dsl-tk gem](https://rubygems.org/gems/glimmer-dsl-tk).
775
-
776
- ##### Glimmer DSL for Tk Samples
777
-
778
- ###### Hello, World!
779
-
780
- Glimmer code (from [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_world.rb)):
781
-
782
- ```ruby
783
- include Glimmer
784
-
785
- root {
786
- label {
787
- text 'Hello, World!'
788
- }
789
- }.open
790
- ```
791
-
792
- Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
793
-
794
- ```
795
- ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_world.rb'"
796
- ```
797
-
798
- Glimmer app:
799
-
800
- ![glimmer dsl tk screenshot sample hello world](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-world.png)
801
-
802
- ###### Hello, Notebook!
803
-
804
- Glimmer code (from [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_tab.rb)):
805
-
806
- ```ruby
807
- include Glimmer
808
-
809
- root {
810
- title 'Hello, Notebook!'
811
-
812
- notebook {
813
- frame(text: 'English') {
814
- label {
815
- text 'Hello, World!'
816
- }
817
- }
818
-
819
- frame(text: 'French') {
820
- label {
821
- text 'Bonjour, Univers!'
822
- }
823
- }
824
- }
825
- }.open
826
- ```
827
-
828
- Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
829
-
830
- ```
831
- ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_notebook.rb'"
832
- ```
833
-
834
- Glimmer app:
835
-
836
- ![glimmer dsl tk screenshot sample hello notebook English](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-notebook-english.png)
837
- ![glimmer dsl tk screenshot sample hello notebook French](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-notebook-french.png)
838
-
839
- ###### Hello, Combobox!
840
-
841
- Glimmer code (from [samples/hello/hello_combobox.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_combobox.rb)):
842
-
843
- ```ruby
844
- require 'glimmer-dsl-tk'
845
-
846
- class Person
847
- attr_accessor :country, :country_options
848
-
849
- def initialize
850
- self.country_options=["", "Canada", "US", "Mexico"]
851
- self.country = "Canada"
852
- end
853
-
854
- def reset_country
855
- self.country = "Canada"
856
- end
857
- end
858
-
859
- class HelloCombobox
860
- include Glimmer
861
-
862
- def launch
863
- person = Person.new
864
-
865
- root {
866
- title 'Hello, Combobox!'
867
-
868
- combobox {
869
- readonly true # this applies to text editing only (item selection still triggers a write to model)
870
- text <=> [person, :country]
871
- }
872
-
873
- button {
874
- text "Reset Selection"
875
- command {
876
- person.reset_country
877
- }
878
- }
879
- }.open
880
- end
881
- end
882
-
883
- HelloCombobox.new.launch
884
- ```
885
-
886
- Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
887
-
888
- ```
889
- ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combobox.rb'"
890
- ```
891
-
892
- Glimmer app:
893
-
894
- ![glimmer dsl tk screenshot sample hello combobox](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-combobox.png)
895
- ![glimmer dsl tk screenshot sample hello combobox dropdown](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-combobox-dropdown.png)
896
-
897
768
  #### Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
898
769
 
899
770
  [Glimmer DSL for LibUI](https://github.com/AndyObtiva/glimmer-dsl-libui) is a prerequisite-free Ruby desktop development GUI library. No need to pre-install any prerequisites. Just install the gem and have platform-independent native GUI that just works!
@@ -1099,6 +970,144 @@ Linux
1099
970
 
1100
971
  ![glimmer-dsl-libui-linux-area-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-area-gallery.png)
1101
972
 
973
+ #### Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
974
+
975
+ [Tcl/Tk](https://www.tcl.tk/) has recently improved by gaining native looking themed widgets on Mac, Windows, and Linux in [Tk version 8.5](https://www.tcl.tk/software/tcltk/8.5.html#:~:text=Highlights%20of%20Tk%208.5&text=Font%20rendering%3A%20Now%20uses%20anti,and%20window%20layout%2C%20and%20more.). Additionally, [Ruby](https://www.ruby-lang.org/en/) 3.0 Ractor (formerly known as [Guilds](https://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/)) supports truly parallel multi-threading, making both [MRI](https://github.com/ruby/ruby) and [Tk](https://www.tcl.tk/) finally viable for support in [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library) as an alternative to [JRuby on SWT](https://github.com/AndyObtiva/glimmer-dsl-swt).
976
+
977
+ The trade-off is that while [SWT](https://www.eclipse.org/swt/) provides a plethora of high quality reusable widgets for the Enterprise (such as [Nebula](https://www.eclipse.org/nebula/)), [Tk](https://www.tcl.tk/) enables very fast app startup time and a small memory footprint via [MRI Ruby](https://www.ruby-lang.org/en/).
978
+
979
+ [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk) aims to provide a DSL similar to the [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) to enable more productive desktop development in Ruby with:
980
+ - Declarative DSL syntax that visually maps to the GUI widget hierarchy
981
+ - Convention over configuration via smart defaults and automation of low-level details
982
+ - Requiring the least amount of syntax possible to build GUI
983
+ - Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
984
+ - Custom Widget support
985
+ - Scaffolding for new custom widgets, apps, and gems
986
+ - Native-Executable packaging on Mac, Windows, and Linux
987
+
988
+ To get started, visit the [Glimmer DSL for Tk project page](https://github.com/AndyObtiva/glimmer-dsl-tk#pre-requisites) for instructions on installing the [glimmer-dsl-tk gem](https://rubygems.org/gems/glimmer-dsl-tk).
989
+
990
+ ##### Glimmer DSL for Tk Samples
991
+
992
+ ###### Hello, World!
993
+
994
+ Glimmer code (from [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_world.rb)):
995
+
996
+ ```ruby
997
+ include Glimmer
998
+
999
+ root {
1000
+ label {
1001
+ text 'Hello, World!'
1002
+ }
1003
+ }.open
1004
+ ```
1005
+
1006
+ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
1007
+
1008
+ ```
1009
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_world.rb'"
1010
+ ```
1011
+
1012
+ Glimmer app:
1013
+
1014
+ ![glimmer dsl tk screenshot sample hello world](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-world.png)
1015
+
1016
+ ###### Hello, Notebook!
1017
+
1018
+ Glimmer code (from [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_tab.rb)):
1019
+
1020
+ ```ruby
1021
+ include Glimmer
1022
+
1023
+ root {
1024
+ title 'Hello, Notebook!'
1025
+
1026
+ notebook {
1027
+ frame(text: 'English') {
1028
+ label {
1029
+ text 'Hello, World!'
1030
+ }
1031
+ }
1032
+
1033
+ frame(text: 'French') {
1034
+ label {
1035
+ text 'Bonjour, Univers!'
1036
+ }
1037
+ }
1038
+ }
1039
+ }.open
1040
+ ```
1041
+
1042
+ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
1043
+
1044
+ ```
1045
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_notebook.rb'"
1046
+ ```
1047
+
1048
+ Glimmer app:
1049
+
1050
+ ![glimmer dsl tk screenshot sample hello notebook English](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-notebook-english.png)
1051
+ ![glimmer dsl tk screenshot sample hello notebook French](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-notebook-french.png)
1052
+
1053
+ ###### Hello, Combobox!
1054
+
1055
+ Glimmer code (from [samples/hello/hello_combobox.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_combobox.rb)):
1056
+
1057
+ ```ruby
1058
+ require 'glimmer-dsl-tk'
1059
+
1060
+ class Person
1061
+ attr_accessor :country, :country_options
1062
+
1063
+ def initialize
1064
+ self.country_options=["", "Canada", "US", "Mexico"]
1065
+ self.country = "Canada"
1066
+ end
1067
+
1068
+ def reset_country
1069
+ self.country = "Canada"
1070
+ end
1071
+ end
1072
+
1073
+ class HelloCombobox
1074
+ include Glimmer
1075
+
1076
+ def launch
1077
+ person = Person.new
1078
+
1079
+ root {
1080
+ title 'Hello, Combobox!'
1081
+
1082
+ combobox {
1083
+ readonly true # this applies to text editing only (item selection still triggers a write to model)
1084
+ text <=> [person, :country]
1085
+ }
1086
+
1087
+ button {
1088
+ text "Reset Selection"
1089
+ command {
1090
+ person.reset_country
1091
+ }
1092
+ }
1093
+ }.open
1094
+ end
1095
+ end
1096
+
1097
+ HelloCombobox.new.launch
1098
+ ```
1099
+
1100
+ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
1101
+
1102
+ ```
1103
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combobox.rb'"
1104
+ ```
1105
+
1106
+ Glimmer app:
1107
+
1108
+ ![glimmer dsl tk screenshot sample hello combobox](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-combobox.png)
1109
+ ![glimmer dsl tk screenshot sample hello combobox dropdown](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-combobox-dropdown.png)
1110
+
1102
1111
  #### Glimmer DSL for XML (& HTML)
1103
1112
 
1104
1113
  [Glimmer DSL for XML](https://github.com/AndyObtiva/glimmer-dsl-xml) provides Ruby syntax for building XML (eXtensible Markup Language) documents.
@@ -1180,6 +1189,10 @@ body{font-size:1.1em;background:white}body > h1{background-color:red;font-size:2
1180
1189
 
1181
1190
  Data-Binding enables mapping GUI properties (like text and color) to Model attributes (like name and age) for bidirectional or unidirectional synchronization and conversion as needed.
1182
1191
 
1192
+ Data-binding supports utilizing the [MVP (Model View Presenter)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter) flavor of [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) by observing both the View and a Presenter for changes and updating the opposite side upon encountering them. This enables writing more decoupled cleaner code that keeps View code and Model code disentangled and highly maintainable.
1193
+
1194
+ ![MVP](https://www.researchgate.net/profile/Gilles-Perrouin/publication/320249584/figure/fig8/AS:668260987068418@1536337243385/Model-view-presenter-architecture.png)
1195
+
1183
1196
  Glimmer enhances observed models automatically (including array operations like `<<`, `delete`, and `reject!`) on first observation. As such, you get automatic observable support, including nested and computed observations. No need to change your model code to data-bind it to the view or add repetitive boilerplate modules. View data-binding is truly decoupled from model logic by being able to observe any model attribute (Ruby attribute reader/writer combo or Ruby attribute reader alone for read-only data-binding when needed)
1184
1197
 
1185
1198
  This relies mainly on the Observer Design Pattern and the MVP (Model-View-Presenter) Architectural Pattern (a variation on MVC)
@@ -1187,11 +1200,11 @@ This relies mainly on the Observer Design Pattern and the MVP (Model-View-Presen
1187
1200
  These are the main classes concerning data-binding:
1188
1201
  - `Glimmer::DataBinding::Observer`: Provides general observer support including unique registration and deregistration for cleanup and prevention of memory leaks. Main methods concerned are: `call`, `register` (alias: `observe`), and `unregister` (alias: `unobserve` or `deregister`). Passing the option `ignore_frozen: true` at the end of the args of `register` (alias: `observe`) method results in silently ignoring any passed frozen observable without raising an error (it raises an error otherwise for frozen/immutable objects).
1189
1202
  - `Glimmer::DataBinding::Observable`: General super-module for all observables. Main methods concerned are: `add_observer` and `remove_observer`
1190
- - `Glimmer::DataBinding::ObservableModel`: Mixin module for any observable model (`Object`, `Struct` or `OpenStruct`) with observable attributes (observes attribute writers and `Struct`/`OpenStruct` `:[]=` method). In addition to `Observable` methods, it has a `notify_observers` method to be called when changes occur. It automatically enhances all attribute setters (ending with `=`) to notify observers on changes. Also, it automatically handles observing array attributes using `ObservableArray` appropriately so they would notify observers upon array mutation changes.
1203
+ - `Glimmer::DataBinding::ObservableModel`: Mixin module for any observable model (`Object`, `Struct` or `OpenStruct`) with observable attributes (observes attribute writers and `Struct`/`OpenStruct` `:[]=` method). In addition to `Observable` methods, it has a `notify_observers` method to be called when changes occur. It automatically enhances all attribute setters (ending with `=`) to notify observers on changes. Also, it automatically handles observing array attributes using `ObservableArray` appropriately so they would notify observers upon array mutation changes. `:attribute_writer_type` option can be specified (default: `:attribute=`) to observe different attribute styles (e.g. `attribute_writer_type: [:attribute=, :set_attribute]`).
1191
1204
  - `Glimmer::DataBinding::ObservableArray`: Mixin module for any observable array collection that automatically handles notifying observers upon performing array mutation operations (e.g. `push`, `select!`, or `delete`) recursively (meaning if an array contained arrays and they changed, observers are notified). Accepts `recursive: true` option in `add_observer` method to recursively observe nested arrays all the way down. Alternatively, pass `recursive: [integer]` to limit recursion in `Array` observation to a specific number of levels beyond the first level (which is always included).
1192
1205
  - `Glimmer::DataBinding::ObservableHash`: Mixin module for any observable hash that automatically handles notifying observers upon performing hash mutation operations (e.g. `hash[key]=value`, `select!`, `merge!`). Also, it automatically handles observing array values using `ObservableArray` appropriately so they would notify observers upon array mutation changes.
1193
1206
  - `Glimmer::DataBinding::ModelBinding`: a higher-level abstraction that relies on all the other observer/observable classes to support basic data-binding, nested data-binding, and computed data-binding
1194
- - `Glimmer::DataBinding::Shine`: enables highly intuitive and visually expressive syntax to perform bidirectional (two-way) data-binding with `<=>` and unidirectional (one-way) data-binding with `<=`
1207
+ - `Glimmer::DataBinding::Shine`: enables [highly intuitive and visually expressive syntax](#shine-data-binding-syntax) to perform bidirectional (two-way) data-binding with `<=>` and unidirectional (one-way) data-binding with `<=`
1195
1208
 
1196
1209
  To do simple observation of models, arrays, or hashes, you can use the `Glimmer::DataBinding::Observer::proc` method, which builds an observer from a block. When invoking the `#observe` method on it, it automatically enhances the object argument being observed into an `Observable` (whether `ObservableModel`, `ObservableArray`, or `ObervableHash`).
1197
1210
 
@@ -1227,7 +1240,7 @@ Glimmer::DataBinding::Observer.proc do |new_value, changed_key|
1227
1240
  end.observe(hash)
1228
1241
  ```
1229
1242
 
1230
- If you would like to observe nested model attribute changes and/or indexed array changes (specifying a nested array index/indices), you can use the more advanced `Glimmer::DataBinding::ModelBinding` class instead.
1243
+ If you would like to observe nested model attribute changes, you can use the more advanced `Glimmer::DataBinding::ModelBinding` class instead.
1231
1244
 
1232
1245
  Example of observing nested model attributes:
1233
1246
 
@@ -1237,7 +1250,7 @@ ModelBinding.new(model, "address1.street").add_observer do |new_address1_street_
1237
1250
  end
1238
1251
  ```
1239
1252
 
1240
- Example of observing indexed array changes (combined with a nested model attribute):
1253
+ Example of observing indexed array changes (specifying an array index) (combined with a nested model attribute):
1241
1254
 
1242
1255
  ```ruby
1243
1256
  ModelBinding.new(model, "employees[5].name").add_observer do |new_employee_6_name|
@@ -1253,12 +1266,65 @@ ModelBinding.new(model, "grid[5][7]").add_observer do |new_grid_cell_value|
1253
1266
  end
1254
1267
  ```
1255
1268
 
1256
- Note that if an observed model attribute or hash key is an array, it is automatically observed for array changes, not just attribute/key-value changes.
1269
+ Example of observing keyed hash changes (specifying a hash key as `Symbol` or single/double-quoted `String`) (combined with a nested model attribute):
1270
+
1271
+ ```ruby
1272
+ ModelBinding.new(model, "employees[:manager].name").add_observer do |new_employee_6_name|
1273
+ # Do some work with new manager employee's name
1274
+ end
1275
+ ```
1276
+
1277
+ Data-bound `ModelBinding` attribute can be:
1278
+ - **Direct:** `Symbol` representing attribute reader/writer (e.g. `[person, :name`])
1279
+ - **Nested:** `String` representing nested attribute path (e.g. `[company, 'address.street']`). That results in "nested data-binding"
1280
+ - **Indexed:** `String` containing array attribute index (e.g. `[customer, 'addresses[0].street']`). That results in "indexed data-binding"
1281
+ - **Keyed:** `String` containing hash attribute key (e.g. `[customer, 'addresses[:main].street']`). That results in "keyed data-binding"
1282
+
1283
+ Data-binding options include:
1284
+ - `before_read {|value| ...}`: performs an operation before reading data from Model to update View.
1285
+ - `on_read {|value| ...}`: converts value read from Model to update the View.
1286
+ - `after_read {|converted_value| ...}`: performs an operation after read from Model to update View.
1287
+ - `before_write {|value| ...}`: performs an operation before writing data to Model from View.
1288
+ - `on_write {|value| ...}`: converts value read from View to update the Model.
1289
+ - `after_write {|converted_value| ...}`: performs an operation after writing to Model from View.
1290
+ - `computed_by attribute` or `computed_by [attribute1, attribute2, ...]`: indicates model attribute is computed from specified attribute(s), thus updated when they are updated. That is known as "computed data-binding".
1291
+
1292
+ Note that if an observed model attribute or hash key is an `Array`, it is automatically observed for `Array` changes (e.g. via mutation methods `<<`, `delete`, `map!`), not just attribute/key-value changes.
1257
1293
 
1258
1294
  All of the features above make Glimmer's data-binding library one of the most sophisticated and advanced in the industry since it automates everything instead of requiring endless manual configuration, thus resulting in some of the tersest most declarative syntax for using observers and data-binding.
1259
1295
 
1260
1296
  You may learn more by looking into [data-binding specs](/Users/andy/code/glimmer/spec/lib/glimmer/data_binding) as well as [Data-Binding](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#data-binding) and [Observer](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#observer) usage in [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)
1261
1297
 
1298
+ ### Shine Data-Binding Syntax
1299
+
1300
+ The Shine data-binding syntax is a highly intuitive and visually expressive way of data-binding that enables performing bidirectional (two-way) data-binding with the `<=>` operator and unidirectional (one-way) data-binding with the `<=` operator.
1301
+
1302
+ It is facilitated by the combination of the `Glimmer::DSL::ShineDataBindingExpression` and `Glimmer::DataBinding::Shine` classes, which depend on `Glimmer::DSL::BindExpression` and `Glimmer::DataBinding::ModelBinding`.
1303
+
1304
+ Below are some examples of Shine usage in GUI DSLs:
1305
+
1306
+ `text <=> [contact, :first_name]`
1307
+
1308
+ This example bidirectionally binds the text property of a widget like label to the first name of a contact model.
1309
+
1310
+ `text <=> [contact, 'address.street']`
1311
+
1312
+ This example binds the text property of a widget like label to the nested street of the address of a contact. This is called nested property data binding.
1313
+
1314
+ `text <=> [contact, 'address.street', on_read: :upcase, on_write: :downcase]`
1315
+
1316
+ This example adds on the one above it by specifying converters on read and write of the model property, like in the case of a text widget. The text widget will then displays the street upper case and the model will store it lower case. When specifying converters, read and write operations must be symmetric.
1317
+
1318
+ `enabled <= [user, :logged_in]`
1319
+
1320
+ This example unidirectionally binds the enabled property of a widget like button to the logged in status of a user.
1321
+
1322
+ `enabled <= [user, :logged_in, on_read: :!]`
1323
+
1324
+ This example unidirectionally binds the enabled property of a widget like entry to the negated logged in status of a user. Note that when using a single on read converter with unidirectional data-binding, there is no need for a symmetric on_write converter as well since writing is never done with unidirectional (one-way) data-binding.
1325
+
1326
+ [Learn more about Shine data-binding syntax from its usage in Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#shine)
1327
+
1262
1328
  ## Glimmer Process
1263
1329
 
1264
1330
  [Glimmer Process](PROCESS.md) is the lightweight software development process used for building Glimmer libraries and Glimmer apps, which goes beyond Agile, rendering all Agile processes obsolete. [Glimmer Process](PROCESS.md) is simply made up of 7 guidelines to pick and choose as necessary until software development needs are satisfied.
@@ -1267,6 +1333,7 @@ Learn more by reading the [GPG](PROCESS.md) (Glimmer Process Guidelines)
1267
1333
 
1268
1334
  ## Resources
1269
1335
 
1336
+ * [Glimmer DSL for SWT Video Tutorials](https://andymaleh.blogspot.com/search/label/Tutorial+SWT)
1270
1337
  * [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
1271
1338
  * [JRuby Cookbook by Justin Edelson & Henry Liu](http://shop.oreilly.com/product/9780596519650.do)
1272
1339
  * [MountainWest RubyConf 2011 Video](https://confreaks.tv/videos/mwrc2011-whatever-happened-to-desktop-development-in-ruby)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.5.3
1
+ 2.7.0
data/glimmer.gemspec CHANGED
@@ -1,90 +1,91 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
- # stub: glimmer 2.5.3 ruby lib
6
-
7
- Gem::Specification.new do |s|
8
- s.name = "glimmer".freeze
9
- s.version = "2.5.3"
10
-
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib".freeze]
13
- s.authors = ["AndyMaleh".freeze]
14
- s.date = "2021-12-07"
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 (including 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 Tk (Ruby Desktop Development GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
16
- s.email = "andy.am@gmail.com".freeze
17
- s.extra_rdoc_files = [
18
- "CHANGELOG.md",
19
- "LICENSE.txt",
20
- "README.md"
21
- ]
22
- s.files = [
23
- "CHANGELOG.md",
24
- "CONTRIBUTING.md",
25
- "LICENSE.txt",
26
- "PROCESS.md",
27
- "README.md",
28
- "VERSION",
29
- "glimmer.gemspec",
30
- "lib/glimmer.rb",
31
- "lib/glimmer/config.rb",
32
- "lib/glimmer/data_binding/model_binding.rb",
33
- "lib/glimmer/data_binding/observable.rb",
34
- "lib/glimmer/data_binding/observable_array.rb",
35
- "lib/glimmer/data_binding/observable_hash.rb",
36
- "lib/glimmer/data_binding/observable_hashable.rb",
37
- "lib/glimmer/data_binding/observable_model.rb",
38
- "lib/glimmer/data_binding/observer.rb",
39
- "lib/glimmer/data_binding/shine.rb",
40
- "lib/glimmer/dsl/bind_expression.rb",
41
- "lib/glimmer/dsl/engine.rb",
42
- "lib/glimmer/dsl/expression.rb",
43
- "lib/glimmer/dsl/expression_handler.rb",
44
- "lib/glimmer/dsl/observe_expression.rb",
45
- "lib/glimmer/dsl/parent_expression.rb",
46
- "lib/glimmer/dsl/static_expression.rb",
47
- "lib/glimmer/dsl/top_level_expression.rb",
48
- "lib/glimmer/error.rb",
49
- "lib/glimmer/ext/module.rb",
50
- "lib/glimmer/invalid_keyword_error.rb",
51
- "lib/glimmer/shim/concurrent.rb"
52
- ]
53
- s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
54
- s.licenses = ["MIT".freeze]
55
- s.rubygems_version = "3.2.22".freeze
56
- s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
57
-
58
- if s.respond_to? :specification_version then
59
- s.specification_version = 4
60
- end
61
-
62
- if s.respond_to? :add_runtime_dependency then
63
- s.add_runtime_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
64
- s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
65
- s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
66
- s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
67
- s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
68
- s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
69
- s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
70
- s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
71
- s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
72
- s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
73
- s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
74
- s.add_development_dependency(%q<rake-tui>.freeze, ["> 0"])
75
- else
76
- s.add_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
77
- s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
78
- s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
79
- s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
80
- s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
81
- s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
82
- s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
83
- s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
84
- s.add_dependency(%q<coveralls>.freeze, [">= 0"])
85
- s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
86
- s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
87
- s.add_dependency(%q<rake-tui>.freeze, ["> 0"])
88
- end
89
- end
90
-
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: glimmer 2.7.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "glimmer".freeze
9
+ s.version = "2.7.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["AndyMaleh".freeze]
14
+ s.date = "2022-02-20"
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 (including 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 Tk (Ruby Desktop Development GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
16
+ s.email = "andy.am@gmail.com".freeze
17
+ s.extra_rdoc_files = [
18
+ "CHANGELOG.md",
19
+ "LICENSE.txt",
20
+ "README.md"
21
+ ]
22
+ s.files = [
23
+ "CHANGELOG.md",
24
+ "CONTRIBUTING.md",
25
+ "LICENSE.txt",
26
+ "PROCESS.md",
27
+ "README.md",
28
+ "VERSION",
29
+ "glimmer.gemspec",
30
+ "lib/glimmer.rb",
31
+ "lib/glimmer/config.rb",
32
+ "lib/glimmer/data_binding/model_binding.rb",
33
+ "lib/glimmer/data_binding/observable.rb",
34
+ "lib/glimmer/data_binding/observable_array.rb",
35
+ "lib/glimmer/data_binding/observable_hash.rb",
36
+ "lib/glimmer/data_binding/observable_hashable.rb",
37
+ "lib/glimmer/data_binding/observable_model.rb",
38
+ "lib/glimmer/data_binding/observer.rb",
39
+ "lib/glimmer/data_binding/shine.rb",
40
+ "lib/glimmer/dsl/bind_expression.rb",
41
+ "lib/glimmer/dsl/engine.rb",
42
+ "lib/glimmer/dsl/expression.rb",
43
+ "lib/glimmer/dsl/expression_handler.rb",
44
+ "lib/glimmer/dsl/observe_expression.rb",
45
+ "lib/glimmer/dsl/parent_expression.rb",
46
+ "lib/glimmer/dsl/shine_data_binding_expression.rb",
47
+ "lib/glimmer/dsl/static_expression.rb",
48
+ "lib/glimmer/dsl/top_level_expression.rb",
49
+ "lib/glimmer/error.rb",
50
+ "lib/glimmer/ext/module.rb",
51
+ "lib/glimmer/invalid_keyword_error.rb",
52
+ "lib/glimmer/shim/concurrent.rb"
53
+ ]
54
+ s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
55
+ s.licenses = ["MIT".freeze]
56
+ s.rubygems_version = "3.3.1".freeze
57
+ s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
58
+
59
+ if s.respond_to? :specification_version then
60
+ s.specification_version = 4
61
+ end
62
+
63
+ if s.respond_to? :add_runtime_dependency then
64
+ s.add_runtime_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
65
+ s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
66
+ s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
67
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
68
+ s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
69
+ s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
70
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
71
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
72
+ s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
73
+ s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
74
+ s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
75
+ s.add_development_dependency(%q<rake-tui>.freeze, ["> 0"])
76
+ else
77
+ s.add_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
78
+ s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
79
+ s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
80
+ s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
81
+ s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
82
+ s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
83
+ s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
84
+ s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
85
+ s.add_dependency(%q<coveralls>.freeze, [">= 0"])
86
+ s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
87
+ s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
88
+ s.add_dependency(%q<rake-tui>.freeze, ["> 0"])
89
+ end
90
+ end
91
+
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -27,6 +27,11 @@ module Glimmer
27
27
  class ModelBinding
28
28
  include Observable
29
29
  include Observer
30
+
31
+ ARRAY_INDEXED_PROPERTY_ARGUMENT_REGEX = /\d+/
32
+ HASH_SYMBOL_INDEXED_PROPERTY_ARGUMENT_REGEX = /:[^:]+/
33
+ HASH_SINGLE_QUOTE_INDEXED_PROPERTY_ARGUMENT_REGEX = /'[^']+'/
34
+ HASH_DOUBLE_QUOTE_INDEXED_PROPERTY_ARGUMENT_REGEX = /"[^"]+"/
30
35
 
31
36
  attr_reader :binding_options, :property_name_expression
32
37
 
@@ -75,7 +80,7 @@ module Glimmer
75
80
  # If there are any indexed property names, this returns indexes as properties.
76
81
  # e.g. property name expression "addresses[1].state" gives ['addresses', '[1]', 'state']
77
82
  def nested_property_names
78
- @nested_property_names ||= Concurrent::Array.new(property_name_expression.split(/\[|\./).map {|pne| pne.end_with?(']') ? "[#{pne}" : pne })
83
+ @nested_property_names ||= Concurrent::Array.new(property_name_expression.split(/\[|\./).map {|pne| pne.end_with?(']') ? "[#{pne}" : pne }.reject {|pne| pne.empty? })
79
84
  end
80
85
 
81
86
  # Final nested property name
@@ -85,7 +90,7 @@ module Glimmer
85
90
  end
86
91
 
87
92
  # Model representing nested property names
88
- # e.g. property name expression "address.state" gives [:address]
93
+ # e.g. property name expression "address.state" gives ['address']
89
94
  def model_property_names
90
95
  Concurrent::Array.new(nested_property_names[0...-1])
91
96
  end
@@ -137,7 +142,7 @@ module Glimmer
137
142
  apply_processor(@binding_options[:after_read], converted_value)
138
143
  end
139
144
  end
140
- observer_registration = model_binding_observer.observe(*[model, property_name, observation_options].compact)
145
+ observer_registration = model_binding_observer.observe(*([model] + [property_name, observation_options].compact))
141
146
  my_registration = observer.registration_for(self)
142
147
  observer.add_dependent(my_registration => observer_registration)
143
148
  end
@@ -206,7 +211,7 @@ module Glimmer
206
211
  def call(value, *extra_args)
207
212
  return if model.nil?
208
213
  converted_value = value
209
- invoke_property_writer(model, model.is_a?(Hash) ? property_name : "#{property_name}=", converted_value) unless converted_value == evaluate_property || property_name.nil?
214
+ invoke_property_writer(model, model.is_a?(Hash) && !property_indexed?(property_name) ? property_name : "#{property_name}=", converted_value) unless converted_value == evaluate_property || property_name.nil?
210
215
  end
211
216
 
212
217
  def evaluate_property
@@ -260,7 +265,7 @@ module Glimmer
260
265
  if property_indexed?(property_expression)
261
266
  property_method = '[]'
262
267
  property_argument = property_expression[1...-1]
263
- property_argument = property_argument.to_i if property_argument.match(/\d+/)
268
+ property_argument = indexed_property_argument(property_argument)
264
269
  object.send(property_method, property_argument)
265
270
  else
266
271
  if property_expression.nil?
@@ -281,7 +286,7 @@ module Glimmer
281
286
  if property_indexed?(property_expression)
282
287
  property_method = '[]='
283
288
  property_argument = property_expression[1...-2]
284
- property_argument = property_argument.to_i if property_argument.match(/\d+/)
289
+ property_argument = indexed_property_argument(property_argument)
285
290
  object.send(property_method, property_argument, converted_value)
286
291
  else
287
292
  if object.is_a?(Hash)
@@ -292,6 +297,20 @@ module Glimmer
292
297
  end
293
298
  apply_processor(@binding_options[:after_write], converted_value)
294
299
  end
300
+
301
+ def indexed_property_argument(property_argument)
302
+ if property_argument.match(ARRAY_INDEXED_PROPERTY_ARGUMENT_REGEX)
303
+ property_argument.to_i
304
+ elsif property_argument.match(HASH_SYMBOL_INDEXED_PROPERTY_ARGUMENT_REGEX)
305
+ property_argument.sub(':', '').to_sym
306
+ elsif property_argument.match(HASH_SINGLE_QUOTE_INDEXED_PROPERTY_ARGUMENT_REGEX)
307
+ property_argument.gsub("'", '')
308
+ elsif property_argument.match(HASH_DOUBLE_QUOTE_INDEXED_PROPERTY_ARGUMENT_REGEX)
309
+ property_argument.gsub('"', '')
310
+ else
311
+ property_argument
312
+ end
313
+ end
295
314
  end
296
315
  end
297
316
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -40,8 +40,7 @@ module Glimmer
40
40
  end
41
41
  end
42
42
 
43
- PROPERTY_WRITER_FACTORY = lambda do |property_name, options|
44
- property_writer_name = "#{property_name}="
43
+ PROPERTY_WRITER_FACTORY = lambda do |property_name, property_writer_name, options|
45
44
  lambda do |value|
46
45
  old_value = self.send(property_name)
47
46
  unregister_dependent_observers(property_name, old_value) # remove dependent observers previously installed in ensure_array_object_observer
@@ -52,6 +51,7 @@ module Glimmer
52
51
  end
53
52
 
54
53
  def add_observer(observer, property_name, options = {})
54
+ initialize_observer_options(options)
55
55
  return observer if has_observer?(observer, property_name)
56
56
  property_observer_list(property_name) << observer
57
57
  add_property_writer_observers(property_name, options)
@@ -113,20 +113,24 @@ module Glimmer
113
113
  end
114
114
 
115
115
  def add_property_writer_observers(property_name, options)
116
- property_writer_name = "#{property_name}="
117
- method(property_writer_name)
118
- ensure_array_object_observer(property_name, send(property_name), nil, options)
119
- begin
120
- method("__original__#{property_writer_name}")
121
- rescue
122
- define_singleton_method("__original__#{property_writer_name}", property_writer_method(property_writer_name))
123
- # Note the limitation that the first observe call options apply to all subsequent observations meaning even if unobserve was called, options do not change from initial ones
124
- # It is good enough for now. If there is a need to address this in the future, this is where to start the work
125
- define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name, options))
116
+ options[:attribute_writer_type].each do |attribute_writer_type|
117
+ begin
118
+ property_writer_name = attribute_writer_type.to_s.gsub('attribute', property_name.to_s)
119
+ method(property_writer_name)
120
+ ensure_array_object_observer(property_name, send(property_name), nil, options)
121
+ begin
122
+ method("__original__#{property_writer_name}")
123
+ rescue
124
+ define_singleton_method("__original__#{property_writer_name}", property_writer_method(property_writer_name))
125
+ # Note the limitation that the first observe call options apply to all subsequent observations meaning even if unobserve was called, options do not change from initial ones
126
+ # It is good enough for now. If there is a need to address this in the future, this is where to start the work
127
+ define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name, property_writer_name, options))
128
+ end
129
+ rescue => e
130
+ #ignore writing if no property writer exists
131
+ Glimmer::Config.logger.debug {"No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"}
132
+ end
126
133
  end
127
- rescue => e
128
- #ignore writing if no property writer exists
129
- Glimmer::Config.logger.debug {"No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"}
130
134
  end
131
135
 
132
136
  def property_writer_method(property_writer_name)
@@ -157,6 +161,11 @@ module Glimmer
157
161
  @array_object_observers[property_name] = Notifier.new(self, property_name) unless @array_object_observers.has_key?(property_name)
158
162
  @array_object_observers[property_name]
159
163
  end
164
+
165
+ def initialize_observer_options(options)
166
+ options[:attribute_writer_type] ||= [:attribute=]
167
+ options[:attribute_writer_type] = [options[:attribute_writer_type]] if !options[:attribute_writer_type].is_a?(Array)
168
+ end
160
169
  end
161
170
  end
162
171
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -28,7 +28,7 @@ module Glimmer
28
28
  @parent = parent
29
29
  @parent_attribute = parent_attribute
30
30
  end
31
-
31
+
32
32
  def <=>(other)
33
33
  if other.is_a?(Array)
34
34
  args_clone = other.clone
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -59,7 +59,11 @@ module Glimmer
59
59
  static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
60
60
  static_expression_can_interpret = nil
61
61
  if static_expression.nil? || !(static_expression_can_interpret = static_expression.can_interpret?(Glimmer::DSL::Engine.parent, keyword, *args, &block))
62
- raise Error, "Invalid use of Glimmer keyword #{keyword} with args #{args} under parent #{Glimmer::DSL::Engine.parent.inspect} with DSL #{Glimmer::DSL::Engine.dsl.inspect} and static expression #{static_expression.inspect} having can_interpret? as #{static_expression_can_interpret.inspect}"
62
+ begin
63
+ Glimmer::DSL::Engine.interpret(keyword, *args, &block)
64
+ rescue => e
65
+ raise Error, "Invalid use of Glimmer keyword #{keyword} with args #{args} under parent #{Glimmer::DSL::Engine.parent.inspect} with DSL #{Glimmer::DSL::Engine.dsl.inspect} and static expression #{static_expression.inspect} having can_interpret? as #{static_expression_can_interpret.inspect} and no dynamic expressions to be able to handle either!"
66
+ end
63
67
  else
64
68
  Glimmer::Config.logger.info {"#{static_expression.class.name} will handle expression keyword #{keyword}"}
65
69
  Glimmer::DSL::Engine.interpret_expression(static_expression, keyword, *args, &block)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/dsl/expression'
23
+ require 'glimmer/data_binding/shine'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ class ShineDataBindingExpression < Expression
28
+ # Including class can override can_interpret? and call super to augment it
29
+ def can_interpret?(parent, keyword, *args, &block)
30
+ args.size == 0 and
31
+ block.nil?
32
+ end
33
+
34
+ def interpret(parent, keyword, *args, &block)
35
+ Glimmer::DataBinding::Shine.new(parent, keyword)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
data/lib/glimmer/error.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
data/lib/glimmer.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2007-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
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: 2.5.3
4
+ version: 2.7.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-12-07 00:00:00.000000000 Z
11
+ date: 2022-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: array_include_methods
@@ -241,6 +241,7 @@ files:
241
241
  - lib/glimmer/dsl/expression_handler.rb
242
242
  - lib/glimmer/dsl/observe_expression.rb
243
243
  - lib/glimmer/dsl/parent_expression.rb
244
+ - lib/glimmer/dsl/shine_data_binding_expression.rb
244
245
  - lib/glimmer/dsl/static_expression.rb
245
246
  - lib/glimmer/dsl/top_level_expression.rb
246
247
  - lib/glimmer/error.rb
@@ -266,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
267
  - !ruby/object:Gem::Version
267
268
  version: '0'
268
269
  requirements: []
269
- rubygems_version: 3.2.22
270
+ rubygems_version: 3.3.1
270
271
  signing_key:
271
272
  specification_version: 4
272
273
  summary: Glimmer - DSL Engine for Ruby GUI and More