glimmer 2.4.0 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +23 -0
 - data/README.md +229 -139
 - data/VERSION +1 -1
 - data/glimmer.gemspec +90 -89
 - data/lib/glimmer/data_binding/model_binding.rb +19 -8
 - data/lib/glimmer/data_binding/observable_array.rb +21 -15
 - data/lib/glimmer/data_binding/observable_hash.rb +3 -61
 - data/lib/glimmer/data_binding/observable_hashable.rb +75 -0
 - data/lib/glimmer/data_binding/observable_model.rb +27 -35
 - data/lib/glimmer/data_binding/observer.rb +16 -14
 - metadata +10 -8
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 3f5103731be03f760a5835564ba6f3be84d2861b9a9c0c6f82fb854070ae3075
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: fce2ab6404b29c93cb068a7e779c32c3a2d4f6abc209468c536acb1413e8cd39
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 67bb9d8b80194ec1004c137bc9d5b87525428b64c94063e512a3bb9291f67694440974c496785184d0b62f0d3abac62de6a662ecdff102df17009edb7bac1dd3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 767ffd76f607076b4fce5edb70f130da7d777453ca1d94a79e39f5be3c1596b28b11dc29c6e3e98c9f4d2a1133e9ff70678c52cb18805b6e898c8d0d6ec02266
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -3,6 +3,29 @@ 
     | 
|
| 
       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.5.3
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            - Provide `Observer#observe` option to tolerate not being able to extend an object for observation by silently not observing such object
         
     | 
| 
      
 9 
     | 
    
         
            +
            - Use `Concurrent::Hash` for `ObservableModel#property_observer_hash`
         
     | 
| 
      
 10 
     | 
    
         
            +
            - Use `Concurrent::Hash` for `ObservableHash#key_observer_hash`
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ### 2.5.1
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            - Fix issue with referencing `OpenStruct` without 'ostruct' library being required (it now checks if `OpenStruct` is loaded first and avoids referencing otherwise).
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ### 2.5.0
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            - Support observing `Struct`/`OpenStruct` changes via `:[]=` method in addition to attribute writers.
         
     | 
| 
      
 19 
     | 
    
         
            +
            - Support read-only direct observation of `Hash` object without key via `ModelBinding` (e.g. `ModelBinding.new(some_hash)`)
         
     | 
| 
      
 20 
     | 
    
         
            +
            - Support read-only direct observation of `Array` object without index via `ModelBinding` (e.g. `ModelBinding.new(some_array)`)
         
     | 
| 
      
 21 
     | 
    
         
            +
            - Support observing `Hash` attribute with `ModelBinding` (all keys or a single key)
         
     | 
| 
      
 22 
     | 
    
         
            +
            - Disable `#ensure_hash_object_observer` in ObservableModel/ObservableHash/ObservableArray since it has performance implications and is not necessary
         
     | 
| 
      
 23 
     | 
    
         
            +
            - Fix issue with `#ensure_array_object_observer` not receiving `recursive: true` option when updating value of an attribute in `ObservableArray`, `ObservableModel`, and `ObservableHash`
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ### 2.4.1
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            - Support `recursive: [integer]` option for ObservableArray#add_observer for finite recursion
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       6 
29 
     | 
    
         
             
            ### 2.4.0
         
     | 
| 
       7 
30 
     | 
    
         | 
| 
       8 
31 
     | 
    
         
             
            - Support passing arbitrary options to `Observer` `#observe` (`#register`) method (not just properties, like `recursive: true` for example)
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -16,7 +16,7 @@ Featured in JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do) an 
     | 
|
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
            [**Glimmer**](https://rubygems.org/gems/glimmer) is a DSL (Domain-Specific Language) Framework that consists of two things:
         
     | 
| 
       18 
18 
     | 
    
         
             
            - [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 syntax support in v2)**.
         
     | 
| 
      
 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)**.
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            [**Glimmer**](https://rubygems.org/gems/glimmer) is ***the cream of the crop*** when it comes to building DSLs in Ruby:
         
     | 
| 
       22 
22 
     | 
    
         
             
            - Supports building the tersest most concise domain specific language syntax in Ruby.
         
     | 
| 
         @@ -32,10 +32,11 @@ Start by checking out Glimmer's original GUI DSL, which got extracted into its o 
     | 
|
| 
       32 
32 
     | 
    
         
             
            [**Glimmer**](https://rubygems.org/gems/glimmer) supports the following DSLs:
         
     | 
| 
       33 
33 
     | 
    
         
             
            - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
         
     | 
| 
       34 
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-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
         
     | 
| 
       36 
     | 
    
         
            -
            - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
         
     | 
| 
       37 
35 
     | 
    
         
             
            - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
         
     | 
| 
       38 
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
         
     | 
| 
       39 
40 
     | 
    
         | 
| 
       40 
41 
     | 
    
         
             
            ## Table of Contents
         
     | 
| 
       41 
42 
     | 
    
         | 
| 
         @@ -47,10 +48,10 @@ Start by checking out Glimmer's original GUI DSL, which got extracted into its o 
     | 
|
| 
       47 
48 
     | 
    
         
             
                - [Official DSLs](#official-dsls)
         
     | 
| 
       48 
49 
     | 
    
         
             
                  - [Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)](#glimmer-dsl-for-swt-jruby-desktop-development-gui-framework)
         
     | 
| 
       49 
50 
     | 
    
         
             
                  - [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)
         
     | 
| 
       50 
     | 
    
         
            -
                  - [Glimmer DSL for XML (& HTML)](#glimmer-dsl-for-xml--html)
         
     | 
| 
       51 
     | 
    
         
            -
                  - [Glimmer DSL for CSS](#glimmer-dsl-for-css)
         
     | 
| 
       52 
51 
     | 
    
         
             
                  - [Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](#glimmer-dsl-for-tk-mri-ruby-desktop-development-gui-library)
         
     | 
| 
       53 
52 
     | 
    
         
             
                  - [Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)](#glimmer-dsl-for-libui-prerequisite-free-ruby-desktop-development-gui-library)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - [Glimmer DSL for XML (& HTML)](#glimmer-dsl-for-xml--html)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  - [Glimmer DSL for CSS](#glimmer-dsl-for-css)
         
     | 
| 
       54 
55 
     | 
    
         
             
              - [Data-Binding Library](#data-binding-library)
         
     | 
| 
       55 
56 
     | 
    
         
             
              - [Glimmer Process](#glimmer-process)
         
     | 
| 
       56 
57 
     | 
    
         
             
              - [Resources](#resources)
         
     | 
| 
         @@ -71,13 +72,32 @@ Glimmer is fundamentally a DSL Engine that can support any number of DSLs like t 
     | 
|
| 
       71 
72 
     | 
    
         
             
            Glimmer DSL syntax consists mainly of:
         
     | 
| 
       72 
73 
     | 
    
         
             
            - **keywords** (e.g. `table` for a table widget)
         
     | 
| 
       73 
74 
     | 
    
         
             
            - **style/args** (e.g. :multi as in `table(:multi)` for a multi-line selection table widget)
         
     | 
| 
       74 
     | 
    
         
            -
            - **content** (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)
         
     | 
| 
      
 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)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            Here is a Hello, World! example from [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt):
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 80 
     | 
    
         
            +
            include Glimmer
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            shell(:no_resize) { # keyword + style arg
         
     | 
| 
      
 83 
     | 
    
         
            +
              text "Glimmer" # attribute content
         
     | 
| 
      
 84 
     | 
    
         
            +
              
         
     | 
| 
      
 85 
     | 
    
         
            +
              label { # keyword content
         
     | 
| 
      
 86 
     | 
    
         
            +
                text "Hello, World!" # attribute content
         
     | 
| 
      
 87 
     | 
    
         
            +
              }
         
     | 
| 
      
 88 
     | 
    
         
            +
            }.open
         
     | 
| 
      
 89 
     | 
    
         
            +
            ```
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            That code renders the following GUI (Graphical User Interface):
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            
         
     | 
| 
       75 
94 
     | 
    
         | 
| 
       76 
95 
     | 
    
         
             
            The Glimmer DSL Engine's architecture is based on the following Design Patterns and Data Structures:
         
     | 
| 
       77 
96 
     | 
    
         
             
            - **Interpreter Design Pattern**: to define interpretable expressions of DSL keywords
         
     | 
| 
       78 
97 
     | 
    
         
             
            - **Chain of Responsibility Design Pattern / Queue Data Structure**: to chain expression handlers in order of importance for processing DSL keywords
         
     | 
| 
       79 
98 
     | 
    
         
             
            - **Adapter Design Pattern**: to adapt expressions into handlers in a chain of responsibility
         
     | 
| 
       80 
99 
     | 
    
         
             
            - **Stack Data Structure**: to handle processing parent/child nesting of DSL keyword expressions in the correct order
         
     | 
| 
      
 100 
     | 
    
         
            +
            - **Proxy Design Pattern**: to shield consumers of GUI libraries built with Glimmer from low-level GUI widget details
         
     | 
| 
       81 
101 
     | 
    
         | 
| 
       82 
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**.
         
     | 
| 
       83 
103 
     | 
    
         | 
| 
         @@ -210,7 +230,7 @@ end 
     | 
|
| 
       210 
230 
     | 
    
         
             
            ### Setup
         
     | 
| 
       211 
231 
     | 
    
         | 
| 
       212 
232 
     | 
    
         
             
            Follow these steps to author a [Glimmer](https://rubygems.org/gems/glimmer) DSL:
         
     | 
| 
       213 
     | 
    
         
            -
            - Add `gem 'glimmer', '~> 2. 
     | 
| 
      
 233 
     | 
    
         
            +
            - Add `gem 'glimmer', '~> 2.5.3'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.5.3` and add `require 'glimmer'`
         
     | 
| 
       214 
234 
     | 
    
         
             
            - 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)
         
     | 
| 
       215 
235 
     | 
    
         
             
            - Create `glimmer/dsl/[dsl_name]/[expresion_name]_expresion.rb` for every [expresion_name] expression needed, whether dynamic or static
         
     | 
| 
       216 
236 
     | 
    
         | 
| 
         @@ -734,83 +754,6 @@ You should see "Apple Calculator Theme" 
     | 
|
| 
       734 
754 
     | 
    
         | 
| 
       735 
755 
     | 
    
         
             
            [](http://glimmer-cs-calculator-server.herokuapp.com/welcomes/apple)
         
     | 
| 
       736 
756 
     | 
    
         | 
| 
       737 
     | 
    
         
            -
            #### Glimmer DSL for XML (& HTML)
         
     | 
| 
       738 
     | 
    
         
            -
             
     | 
| 
       739 
     | 
    
         
            -
            [Glimmer DSL for XML](https://github.com/AndyObtiva/glimmer-dsl-xml) provides Ruby syntax for building XML (eXtensible Markup Language) documents.
         
     | 
| 
       740 
     | 
    
         
            -
             
     | 
| 
       741 
     | 
    
         
            -
            Within the context of desktop development, Glimmer DSL for XML is useful in providing XML data for the [SWT Browser widget](https://github.com/AndyObtiva/glimmer/tree/master#browser-widget).
         
     | 
| 
       742 
     | 
    
         
            -
             
     | 
| 
       743 
     | 
    
         
            -
            ##### XML DSL
         
     | 
| 
       744 
     | 
    
         
            -
             
     | 
| 
       745 
     | 
    
         
            -
            Simply start with `html` keyword and add HTML inside its block using Glimmer DSL syntax.
         
     | 
| 
       746 
     | 
    
         
            -
            Once done, you may call `to_s`, `to_xml`, or `to_html` to get the formatted HTML output.
         
     | 
| 
       747 
     | 
    
         
            -
             
     | 
| 
       748 
     | 
    
         
            -
            Here are all the Glimmer XML DSL top-level keywords:
         
     | 
| 
       749 
     | 
    
         
            -
            - `html`
         
     | 
| 
       750 
     | 
    
         
            -
            - `tag`: enables custom tag creation for exceptional cases by passing tag name as '_name' attribute
         
     | 
| 
       751 
     | 
    
         
            -
            - `name_space`: enables namespacing html tags
         
     | 
| 
       752 
     | 
    
         
            -
             
     | 
| 
       753 
     | 
    
         
            -
            Element properties are typically passed as a key/value hash (e.g. `section(id: 'main', class: 'accordion')`) . However, for properties like "selected" or "checked", you must leave value `nil` or otherwise pass in front of the hash (e.g. `input(:checked, type: 'checkbox')` )
         
     | 
| 
       754 
     | 
    
         
            -
             
     | 
| 
       755 
     | 
    
         
            -
            Example (basic HTML):
         
     | 
| 
       756 
     | 
    
         
            -
             
     | 
| 
       757 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       758 
     | 
    
         
            -
            @xml = html {
         
     | 
| 
       759 
     | 
    
         
            -
              head {
         
     | 
| 
       760 
     | 
    
         
            -
                meta(name: "viewport", content: "width=device-width, initial-scale=2.0")
         
     | 
| 
       761 
     | 
    
         
            -
              }
         
     | 
| 
       762 
     | 
    
         
            -
              body {
         
     | 
| 
       763 
     | 
    
         
            -
                h1 { "Hello, World!" }
         
     | 
| 
       764 
     | 
    
         
            -
              }
         
     | 
| 
       765 
     | 
    
         
            -
            }
         
     | 
| 
       766 
     | 
    
         
            -
            puts @xml
         
     | 
| 
       767 
     | 
    
         
            -
            ```
         
     | 
| 
       768 
     | 
    
         
            -
             
     | 
| 
       769 
     | 
    
         
            -
            Output:
         
     | 
| 
       770 
     | 
    
         
            -
             
     | 
| 
       771 
     | 
    
         
            -
            ```
         
     | 
| 
       772 
     | 
    
         
            -
            <html><head><meta name="viewport" content="width=device-width, initial-scale=2.0" /></head><body><h1>Hello, World!</h1></body></html>
         
     | 
| 
       773 
     | 
    
         
            -
            ```
         
     | 
| 
       774 
     | 
    
         
            -
             
     | 
| 
       775 
     | 
    
         
            -
            #### Glimmer DSL for CSS
         
     | 
| 
       776 
     | 
    
         
            -
             
     | 
| 
       777 
     | 
    
         
            -
            [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css) provides Ruby syntax for building CSS (Cascading Style Sheets).
         
     | 
| 
       778 
     | 
    
         
            -
             
     | 
| 
       779 
     | 
    
         
            -
            Within the context of [Glimmer](https://github.com/AndyObtiva/glimmer) app development, Glimmer DSL for CSS is useful in providing CSS for the [SWT Browser widget](https://github.com/AndyObtiva/glimmer/tree/master#browser-widget).
         
     | 
| 
       780 
     | 
    
         
            -
             
     | 
| 
       781 
     | 
    
         
            -
            ##### CSS DSL
         
     | 
| 
       782 
     | 
    
         
            -
             
     | 
| 
       783 
     | 
    
         
            -
            Simply start with `css` keyword and add stylesheet rule sets inside its block using Glimmer DSL syntax.
         
     | 
| 
       784 
     | 
    
         
            -
            Once done, you may call `to_s` or `to_css` to get the formatted CSS output.
         
     | 
| 
       785 
     | 
    
         
            -
             
     | 
| 
       786 
     | 
    
         
            -
            `css` is the only top-level keyword in the Glimmer CSS DSL
         
     | 
| 
       787 
     | 
    
         
            -
             
     | 
| 
       788 
     | 
    
         
            -
            Selectors may be specified by `s` keyword or HTML element keyword directly (e.g. `body`)
         
     | 
| 
       789 
     | 
    
         
            -
            Rule property values may be specified by `pv` keyword or underscored property name directly (e.g. `font_size`)
         
     | 
| 
       790 
     | 
    
         
            -
             
     | 
| 
       791 
     | 
    
         
            -
            Example:
         
     | 
| 
       792 
     | 
    
         
            -
             
     | 
| 
       793 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       794 
     | 
    
         
            -
            @css = css {
         
     | 
| 
       795 
     | 
    
         
            -
              body {
         
     | 
| 
       796 
     | 
    
         
            -
                font_size '1.1em'
         
     | 
| 
       797 
     | 
    
         
            -
                pv 'background', 'white'
         
     | 
| 
       798 
     | 
    
         
            -
              }
         
     | 
| 
       799 
     | 
    
         
            -
              
         
     | 
| 
       800 
     | 
    
         
            -
              s('body > h1') {
         
     | 
| 
       801 
     | 
    
         
            -
                background_color :red
         
     | 
| 
       802 
     | 
    
         
            -
                pv 'font-size', '2em'
         
     | 
| 
       803 
     | 
    
         
            -
              }
         
     | 
| 
       804 
     | 
    
         
            -
            }
         
     | 
| 
       805 
     | 
    
         
            -
            puts @css
         
     | 
| 
       806 
     | 
    
         
            -
            ```
         
     | 
| 
       807 
     | 
    
         
            -
             
     | 
| 
       808 
     | 
    
         
            -
            Output:
         
     | 
| 
       809 
     | 
    
         
            -
             
     | 
| 
       810 
     | 
    
         
            -
            ```
         
     | 
| 
       811 
     | 
    
         
            -
            body{font-size:1.1em;background:white}body > h1{background-color:red;font-size:2em}
         
     | 
| 
       812 
     | 
    
         
            -
            ```
         
     | 
| 
       813 
     | 
    
         
            -
             
     | 
| 
       814 
757 
     | 
    
         
             
            #### Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
         
     | 
| 
       815 
758 
     | 
    
         | 
| 
       816 
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.).
         
     | 
| 
         @@ -893,28 +836,51 @@ Glimmer app: 
     | 
|
| 
       893 
836 
     | 
    
         
             
            
         
     | 
| 
       894 
837 
     | 
    
         
             
            
         
     | 
| 
       895 
838 
     | 
    
         | 
| 
       896 
     | 
    
         
            -
            ###### Hello,  
     | 
| 
      
 839 
     | 
    
         
            +
            ###### Hello, Combobox!
         
     | 
| 
       897 
840 
     | 
    
         | 
| 
       898 
     | 
    
         
            -
            Glimmer code (from [samples/hello/ 
     | 
| 
      
 841 
     | 
    
         
            +
            Glimmer code (from [samples/hello/hello_combobox.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_combobox.rb)):
         
     | 
| 
       899 
842 
     | 
    
         | 
| 
       900 
843 
     | 
    
         
             
            ```ruby
         
     | 
| 
       901 
     | 
    
         
            -
             
     | 
| 
       902 
     | 
    
         
            -
             
     | 
| 
       903 
     | 
    
         
            -
             
     | 
| 
       904 
     | 
    
         
            -
              
         
     | 
| 
       905 
     | 
    
         
            -
             
     | 
| 
       906 
     | 
    
         
            -
             
     | 
| 
       907 
     | 
    
         
            -
                 
     | 
| 
       908 
     | 
    
         
            -
             
     | 
| 
      
 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
         
     | 
| 
       909 
861 
     | 
    
         | 
| 
       910 
     | 
    
         
            -
               
     | 
| 
       911 
     | 
    
         
            -
                 
     | 
| 
       912 
     | 
    
         
            -
                 
     | 
| 
       913 
     | 
    
         
            -
             
     | 
| 
       914 
     | 
    
         
            -
             
     | 
| 
       915 
     | 
    
         
            -
             
     | 
| 
       916 
     | 
    
         
            -
             
     | 
| 
       917 
     | 
    
         
            -
            #  
     | 
| 
      
 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
         
     | 
| 
       918 
884 
     | 
    
         
             
            ```
         
     | 
| 
       919 
885 
     | 
    
         | 
| 
       920 
886 
     | 
    
         
             
            Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
         
     | 
| 
         @@ -925,8 +891,8 @@ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combobox.rb'" 
     | 
|
| 
       925 
891 
     | 
    
         | 
| 
       926 
892 
     | 
    
         
             
            Glimmer app:
         
     | 
| 
       927 
893 
     | 
    
         | 
| 
       928 
     | 
    
         
            -
            
         
     | 
| 
      
 895 
     | 
    
         
            +
            
         
     | 
| 
       930 
896 
     | 
    
         | 
| 
       931 
897 
     | 
    
         
             
            #### Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
         
     | 
| 
       932 
898 
     | 
    
         | 
| 
         @@ -961,39 +927,13 @@ Mac 
     | 
|
| 
       961 
927 
     | 
    
         | 
| 
       962 
928 
     | 
    
         
             
            
         
     | 
| 
       963 
929 
     | 
    
         | 
| 
       964 
     | 
    
         
            -
             
     | 
| 
       965 
     | 
    
         
            -
             
     | 
| 
       966 
     | 
    
         
            -
            
         
     | 
| 
       967 
     | 
    
         
            -
             
     | 
| 
       968 
     | 
    
         
            -
            ###### Basic Button
         
     | 
| 
       969 
     | 
    
         
            -
             
     | 
| 
       970 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       971 
     | 
    
         
            -
            require 'glimmer-dsl-libui'
         
     | 
| 
       972 
     | 
    
         
            -
             
     | 
| 
       973 
     | 
    
         
            -
            include Glimmer
         
     | 
| 
      
 930 
     | 
    
         
            +
            Windows
         
     | 
| 
       974 
931 
     | 
    
         | 
| 
       975 
     | 
    
         
            -
            window( 
     | 
| 
       976 
     | 
    
         
            -
              button('Button') {
         
     | 
| 
       977 
     | 
    
         
            -
                on_clicked do
         
     | 
| 
       978 
     | 
    
         
            -
                  msg_box('Information', 'You clicked the button')
         
     | 
| 
       979 
     | 
    
         
            -
                end
         
     | 
| 
       980 
     | 
    
         
            -
              }
         
     | 
| 
       981 
     | 
    
         
            -
              
         
     | 
| 
       982 
     | 
    
         
            -
              on_closing do
         
     | 
| 
       983 
     | 
    
         
            -
                puts 'Bye Bye'
         
     | 
| 
       984 
     | 
    
         
            -
              end
         
     | 
| 
       985 
     | 
    
         
            -
            }.show
         
     | 
| 
       986 
     | 
    
         
            -
            ```
         
     | 
| 
       987 
     | 
    
         
            -
             
     | 
| 
       988 
     | 
    
         
            -
            Mac
         
     | 
| 
       989 
     | 
    
         
            -
             
     | 
| 
       990 
     | 
    
         
            -
            
         
     | 
| 
       991 
     | 
    
         
            -
            
         
     | 
| 
      
 932 
     | 
    
         
            +
            
         
     | 
| 
       992 
933 
     | 
    
         | 
| 
       993 
934 
     | 
    
         
             
            Linux
         
     | 
| 
       994 
935 
     | 
    
         | 
| 
       995 
     | 
    
         
            -
            
         
     | 
| 
      
 936 
     | 
    
         
            +
            
         
     | 
| 
       997 
937 
     | 
    
         | 
| 
       998 
938 
     | 
    
         
             
            ###### Basic Table Progress Bar
         
     | 
| 
       999 
939 
     | 
    
         | 
| 
         @@ -1036,6 +976,10 @@ Mac 
     | 
|
| 
       1036 
976 
     | 
    
         | 
| 
       1037 
977 
     | 
    
         
             
            
         
     | 
| 
       1038 
978 
     | 
    
         | 
| 
      
 979 
     | 
    
         
            +
            Windows
         
     | 
| 
      
 980 
     | 
    
         
            +
             
     | 
| 
      
 981 
     | 
    
         
            +
            
         
     | 
| 
      
 982 
     | 
    
         
            +
             
     | 
| 
       1039 
983 
     | 
    
         
             
            Linux
         
     | 
| 
       1040 
984 
     | 
    
         | 
| 
       1041 
985 
     | 
    
         
             
            
         
     | 
| 
         @@ -1147,10 +1091,91 @@ Mac 
     | 
|
| 
       1147 
1091 
     | 
    
         | 
| 
       1148 
1092 
     | 
    
         
             
            
         
     | 
| 
       1149 
1093 
     | 
    
         | 
| 
      
 1094 
     | 
    
         
            +
            Windows
         
     | 
| 
      
 1095 
     | 
    
         
            +
             
     | 
| 
      
 1096 
     | 
    
         
            +
            
         
     | 
| 
      
 1097 
     | 
    
         
            +
             
     | 
| 
       1150 
1098 
     | 
    
         
             
            Linux
         
     | 
| 
       1151 
1099 
     | 
    
         | 
| 
       1152 
1100 
     | 
    
         
             
            
         
     | 
| 
       1153 
1101 
     | 
    
         | 
| 
      
 1102 
     | 
    
         
            +
            #### Glimmer DSL for XML (& HTML)
         
     | 
| 
      
 1103 
     | 
    
         
            +
             
     | 
| 
      
 1104 
     | 
    
         
            +
            [Glimmer DSL for XML](https://github.com/AndyObtiva/glimmer-dsl-xml) provides Ruby syntax for building XML (eXtensible Markup Language) documents.
         
     | 
| 
      
 1105 
     | 
    
         
            +
             
     | 
| 
      
 1106 
     | 
    
         
            +
            Within the context of desktop development, Glimmer DSL for XML is useful in providing XML data for the [SWT Browser widget](https://github.com/AndyObtiva/glimmer/tree/master#browser-widget).
         
     | 
| 
      
 1107 
     | 
    
         
            +
             
     | 
| 
      
 1108 
     | 
    
         
            +
            ##### XML DSL
         
     | 
| 
      
 1109 
     | 
    
         
            +
             
     | 
| 
      
 1110 
     | 
    
         
            +
            Simply start with `html` keyword and add HTML inside its block using Glimmer DSL syntax.
         
     | 
| 
      
 1111 
     | 
    
         
            +
            Once done, you may call `to_s`, `to_xml`, or `to_html` to get the formatted HTML output.
         
     | 
| 
      
 1112 
     | 
    
         
            +
             
     | 
| 
      
 1113 
     | 
    
         
            +
            Here are all the Glimmer XML DSL top-level keywords:
         
     | 
| 
      
 1114 
     | 
    
         
            +
            - `html`
         
     | 
| 
      
 1115 
     | 
    
         
            +
            - `tag`: enables custom tag creation for exceptional cases by passing tag name as '_name' attribute
         
     | 
| 
      
 1116 
     | 
    
         
            +
            - `name_space`: enables namespacing html tags
         
     | 
| 
      
 1117 
     | 
    
         
            +
             
     | 
| 
      
 1118 
     | 
    
         
            +
            Element properties are typically passed as a key/value hash (e.g. `section(id: 'main', class: 'accordion')`) . However, for properties like "selected" or "checked", you must leave value `nil` or otherwise pass in front of the hash (e.g. `input(:checked, type: 'checkbox')` )
         
     | 
| 
      
 1119 
     | 
    
         
            +
             
     | 
| 
      
 1120 
     | 
    
         
            +
            Example (basic HTML):
         
     | 
| 
      
 1121 
     | 
    
         
            +
             
     | 
| 
      
 1122 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1123 
     | 
    
         
            +
            @xml = html {
         
     | 
| 
      
 1124 
     | 
    
         
            +
              head {
         
     | 
| 
      
 1125 
     | 
    
         
            +
                meta(name: "viewport", content: "width=device-width, initial-scale=2.0")
         
     | 
| 
      
 1126 
     | 
    
         
            +
              }
         
     | 
| 
      
 1127 
     | 
    
         
            +
              body {
         
     | 
| 
      
 1128 
     | 
    
         
            +
                h1 { "Hello, World!" }
         
     | 
| 
      
 1129 
     | 
    
         
            +
              }
         
     | 
| 
      
 1130 
     | 
    
         
            +
            }
         
     | 
| 
      
 1131 
     | 
    
         
            +
            puts @xml
         
     | 
| 
      
 1132 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1133 
     | 
    
         
            +
             
     | 
| 
      
 1134 
     | 
    
         
            +
            Output:
         
     | 
| 
      
 1135 
     | 
    
         
            +
             
     | 
| 
      
 1136 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1137 
     | 
    
         
            +
            <html><head><meta name="viewport" content="width=device-width, initial-scale=2.0" /></head><body><h1>Hello, World!</h1></body></html>
         
     | 
| 
      
 1138 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1139 
     | 
    
         
            +
             
     | 
| 
      
 1140 
     | 
    
         
            +
            #### Glimmer DSL for CSS
         
     | 
| 
      
 1141 
     | 
    
         
            +
             
     | 
| 
      
 1142 
     | 
    
         
            +
            [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css) provides Ruby syntax for building CSS (Cascading Style Sheets).
         
     | 
| 
      
 1143 
     | 
    
         
            +
             
     | 
| 
      
 1144 
     | 
    
         
            +
            Within the context of [Glimmer](https://github.com/AndyObtiva/glimmer) app development, Glimmer DSL for CSS is useful in providing CSS for the [SWT Browser widget](https://github.com/AndyObtiva/glimmer/tree/master#browser-widget).
         
     | 
| 
      
 1145 
     | 
    
         
            +
             
     | 
| 
      
 1146 
     | 
    
         
            +
            ##### CSS DSL
         
     | 
| 
      
 1147 
     | 
    
         
            +
             
     | 
| 
      
 1148 
     | 
    
         
            +
            Simply start with `css` keyword and add stylesheet rule sets inside its block using Glimmer DSL syntax.
         
     | 
| 
      
 1149 
     | 
    
         
            +
            Once done, you may call `to_s` or `to_css` to get the formatted CSS output.
         
     | 
| 
      
 1150 
     | 
    
         
            +
             
     | 
| 
      
 1151 
     | 
    
         
            +
            `css` is the only top-level keyword in the Glimmer CSS DSL
         
     | 
| 
      
 1152 
     | 
    
         
            +
             
     | 
| 
      
 1153 
     | 
    
         
            +
            Selectors may be specified by `s` keyword or HTML element keyword directly (e.g. `body`)
         
     | 
| 
      
 1154 
     | 
    
         
            +
            Rule property values may be specified by `pv` keyword or underscored property name directly (e.g. `font_size`)
         
     | 
| 
      
 1155 
     | 
    
         
            +
             
     | 
| 
      
 1156 
     | 
    
         
            +
            Example:
         
     | 
| 
      
 1157 
     | 
    
         
            +
             
     | 
| 
      
 1158 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1159 
     | 
    
         
            +
            @css = css {
         
     | 
| 
      
 1160 
     | 
    
         
            +
              body {
         
     | 
| 
      
 1161 
     | 
    
         
            +
                font_size '1.1em'
         
     | 
| 
      
 1162 
     | 
    
         
            +
                pv 'background', 'white'
         
     | 
| 
      
 1163 
     | 
    
         
            +
              }
         
     | 
| 
      
 1164 
     | 
    
         
            +
              
         
     | 
| 
      
 1165 
     | 
    
         
            +
              s('body > h1') {
         
     | 
| 
      
 1166 
     | 
    
         
            +
                background_color :red
         
     | 
| 
      
 1167 
     | 
    
         
            +
                pv 'font-size', '2em'
         
     | 
| 
      
 1168 
     | 
    
         
            +
              }
         
     | 
| 
      
 1169 
     | 
    
         
            +
            }
         
     | 
| 
      
 1170 
     | 
    
         
            +
            puts @css
         
     | 
| 
      
 1171 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1172 
     | 
    
         
            +
             
     | 
| 
      
 1173 
     | 
    
         
            +
            Output:
         
     | 
| 
      
 1174 
     | 
    
         
            +
             
     | 
| 
      
 1175 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1176 
     | 
    
         
            +
            body{font-size:1.1em;background:white}body > h1{background-color:red;font-size:2em}
         
     | 
| 
      
 1177 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1178 
     | 
    
         
            +
             
     | 
| 
       1154 
1179 
     | 
    
         
             
            ## Data-Binding Library
         
     | 
| 
       1155 
1180 
     | 
    
         | 
| 
       1156 
1181 
     | 
    
         
             
            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.
         
     | 
| 
         @@ -1160,15 +1185,79 @@ Glimmer enhances observed models automatically (including array operations like 
     | 
|
| 
       1160 
1185 
     | 
    
         
             
            This relies mainly on the Observer Design Pattern and the MVP (Model-View-Presenter) Architectural Pattern (a variation on MVC)
         
     | 
| 
       1161 
1186 
     | 
    
         | 
| 
       1162 
1187 
     | 
    
         
             
            These are the main classes concerning data-binding:
         
     | 
| 
       1163 
     | 
    
         
            -
            - `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`)
         
     | 
| 
      
 1188 
     | 
    
         
            +
            - `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).
         
     | 
| 
       1164 
1189 
     | 
    
         
             
            - `Glimmer::DataBinding::Observable`: General super-module for all observables. Main methods concerned are: `add_observer` and `remove_observer`
         
     | 
| 
       1165 
     | 
    
         
            -
            - `Glimmer::DataBinding::ObservableModel`: Mixin module for any observable model with observable attributes. 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.
         
     | 
| 
       1166 
     | 
    
         
            -
            - `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.
         
     | 
| 
       1167 
     | 
    
         
            -
            - `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!`)
         
     | 
| 
      
 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.
         
     | 
| 
      
 1191 
     | 
    
         
            +
            - `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 
     | 
    
         
            +
            - `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.
         
     | 
| 
       1168 
1193 
     | 
    
         
             
            - `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
         
     | 
| 
       1169 
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 `<=`
         
     | 
| 
       1170 
1195 
     | 
    
         | 
| 
       1171 
     | 
    
         
            -
             
     | 
| 
      
 1196 
     | 
    
         
            +
            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 
     | 
    
         
            +
             
     | 
| 
      
 1198 
     | 
    
         
            +
            Example of observing a model attribute:
         
     | 
| 
      
 1199 
     | 
    
         
            +
             
     | 
| 
      
 1200 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1201 
     | 
    
         
            +
            Glimmer::DataBinding::Observer.proc do |new_value|
         
     | 
| 
      
 1202 
     | 
    
         
            +
              # Do some work with new value for model attribute
         
     | 
| 
      
 1203 
     | 
    
         
            +
            end.observe(model, attribute)
         
     | 
| 
      
 1204 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1205 
     | 
    
         
            +
             
     | 
| 
      
 1206 
     | 
    
         
            +
            Example of observing an array recursively (avoid recursion unless really needed since it fires on all fine-grained nested array changes):
         
     | 
| 
      
 1207 
     | 
    
         
            +
             
     | 
| 
      
 1208 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1209 
     | 
    
         
            +
            Glimmer::DataBinding::Observer.proc do |new_value|
         
     | 
| 
      
 1210 
     | 
    
         
            +
              # Do some work with new array value
         
     | 
| 
      
 1211 
     | 
    
         
            +
            end.observe(array, recursive: true)
         
     | 
| 
      
 1212 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1213 
     | 
    
         
            +
             
     | 
| 
      
 1214 
     | 
    
         
            +
            Example of observing a hash key:
         
     | 
| 
      
 1215 
     | 
    
         
            +
             
     | 
| 
      
 1216 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1217 
     | 
    
         
            +
            Glimmer::DataBinding::Observer.proc do |new_value|
         
     | 
| 
      
 1218 
     | 
    
         
            +
              # Do some work with new value for hash key
         
     | 
| 
      
 1219 
     | 
    
         
            +
            end.observe(hash, :price)
         
     | 
| 
      
 1220 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1221 
     | 
    
         
            +
             
     | 
| 
      
 1222 
     | 
    
         
            +
            Example of observing a hash for all key changes:
         
     | 
| 
      
 1223 
     | 
    
         
            +
             
     | 
| 
      
 1224 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1225 
     | 
    
         
            +
            Glimmer::DataBinding::Observer.proc do |new_value, changed_key|
         
     | 
| 
      
 1226 
     | 
    
         
            +
              # Do some work with new value and changed key for hash
         
     | 
| 
      
 1227 
     | 
    
         
            +
            end.observe(hash)
         
     | 
| 
      
 1228 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1229 
     | 
    
         
            +
             
     | 
| 
      
 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.
         
     | 
| 
      
 1231 
     | 
    
         
            +
             
     | 
| 
      
 1232 
     | 
    
         
            +
            Example of observing nested model attributes:
         
     | 
| 
      
 1233 
     | 
    
         
            +
             
     | 
| 
      
 1234 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1235 
     | 
    
         
            +
            ModelBinding.new(model, "address1.street").add_observer do |new_address1_street_value|
         
     | 
| 
      
 1236 
     | 
    
         
            +
              # Do some work with new address 1 street value
         
     | 
| 
      
 1237 
     | 
    
         
            +
            end
         
     | 
| 
      
 1238 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1239 
     | 
    
         
            +
             
     | 
| 
      
 1240 
     | 
    
         
            +
            Example of observing indexed array changes (combined with a nested model attribute):
         
     | 
| 
      
 1241 
     | 
    
         
            +
             
     | 
| 
      
 1242 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1243 
     | 
    
         
            +
            ModelBinding.new(model, "employees[5].name").add_observer do |new_employee_6_name|
         
     | 
| 
      
 1244 
     | 
    
         
            +
              # Do some work with new employee 6 (index 5)'s name
         
     | 
| 
      
 1245 
     | 
    
         
            +
            end
         
     | 
| 
      
 1246 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1247 
     | 
    
         
            +
             
     | 
| 
      
 1248 
     | 
    
         
            +
            Example of observing double-indexed nested array changes:
         
     | 
| 
      
 1249 
     | 
    
         
            +
             
     | 
| 
      
 1250 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1251 
     | 
    
         
            +
            ModelBinding.new(model, "grid[5][7]").add_observer do |new_grid_cell_value|
         
     | 
| 
      
 1252 
     | 
    
         
            +
              # Do some work with new grid cell value for row index 5 and column index 7
         
     | 
| 
      
 1253 
     | 
    
         
            +
            end
         
     | 
| 
      
 1254 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1255 
     | 
    
         
            +
             
     | 
| 
      
 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.
         
     | 
| 
      
 1257 
     | 
    
         
            +
             
     | 
| 
      
 1258 
     | 
    
         
            +
            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 
     | 
    
         
            +
             
     | 
| 
      
 1260 
     | 
    
         
            +
            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)
         
     | 
| 
       1172 
1261 
     | 
    
         | 
| 
       1173 
1262 
     | 
    
         
             
            ## Glimmer Process
         
     | 
| 
       1174 
1263 
     | 
    
         | 
| 
         @@ -1221,8 +1310,9 @@ If you would like to contribute to Glimmer, please study up on Glimmer and [SWT] 
     | 
|
| 
       1221 
1310 
     | 
    
         | 
| 
       1222 
1311 
     | 
    
         
             
            You may apply for contributing to any of these Glimmer DSL gems whether you prefer to focus on the desktop or web:
         
     | 
| 
       1223 
1312 
     | 
    
         
             
            - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
         
     | 
| 
       1224 
     | 
    
         
            -
            - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
         
     | 
| 
       1225 
1313 
     | 
    
         
             
            - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
         
     | 
| 
      
 1314 
     | 
    
         
            +
            - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
         
     | 
| 
      
 1315 
     | 
    
         
            +
            - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
         
     | 
| 
       1226 
1316 
     | 
    
         
             
            - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
         
     | 
| 
       1227 
1317 
     | 
    
         
             
            - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
         
     | 
| 
       1228 
1318 
     | 
    
         | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            2. 
     | 
| 
      
 1 
     | 
    
         
            +
            2.5.3
         
     |