glimmer 2.2.1 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
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,10 @@ 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-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
38
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
39
39
 
40
40
  ## Table of Contents
41
41
 
@@ -47,10 +47,10 @@ Start by checking out Glimmer's original GUI DSL, which got extracted into its o
47
47
  - [Official DSLs](#official-dsls)
48
48
  - [Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)](#glimmer-dsl-for-swt-jruby-desktop-development-gui-framework)
49
49
  - [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
50
  - [Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)](#glimmer-dsl-for-tk-mri-ruby-desktop-development-gui-library)
53
51
  - [Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)](#glimmer-dsl-for-libui-prerequisite-free-ruby-desktop-development-gui-library)
52
+ - [Glimmer DSL for XML (& HTML)](#glimmer-dsl-for-xml--html)
53
+ - [Glimmer DSL for CSS](#glimmer-dsl-for-css)
54
54
  - [Data-Binding Library](#data-binding-library)
55
55
  - [Glimmer Process](#glimmer-process)
56
56
  - [Resources](#resources)
@@ -71,13 +71,32 @@ Glimmer is fundamentally a DSL Engine that can support any number of DSLs like t
71
71
  Glimmer DSL syntax consists mainly of:
72
72
  - **keywords** (e.g. `table` for a table widget)
73
73
  - **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)
74
+ - **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)
75
+
76
+ Here is a Hello, World! example from [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt):
77
+
78
+ ```ruby
79
+ include Glimmer
80
+
81
+ shell(:no_resize) { # keyword + style arg
82
+ text "Glimmer" # attribute content
83
+
84
+ label { # keyword content
85
+ text "Hello, World!" # attribute content
86
+ }
87
+ }.open
88
+ ```
89
+
90
+ That code renders the following GUI (Graphical User Interface):
91
+
92
+ ![Hello World](images/glimmer-hello-world.png)
75
93
 
76
94
  The Glimmer DSL Engine's architecture is based on the following Design Patterns and Data Structures:
77
95
  - **Interpreter Design Pattern**: to define interpretable expressions of DSL keywords
78
96
  - **Chain of Responsibility Design Pattern / Queue Data Structure**: to chain expression handlers in order of importance for processing DSL keywords
79
97
  - **Adapter Design Pattern**: to adapt expressions into handlers in a chain of responsibility
80
98
  - **Stack Data Structure**: to handle processing parent/child nesting of DSL keyword expressions in the correct order
99
+ - **Proxy Design Pattern**: to shield consumers of GUI libraries built with Glimmer from low-level GUI widget details
81
100
 
82
101
  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
102
 
@@ -210,7 +229,7 @@ end
210
229
  ### Setup
211
230
 
212
231
  Follow these steps to author a [Glimmer](https://rubygems.org/gems/glimmer) DSL:
213
- - Add `gem 'glimmer', '~> 2.2.1'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.2.1` and add `require 'glimmer'`
232
+ - Add `gem 'glimmer', '~> 2.4.1'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.4.1` and add `require 'glimmer'`
214
233
  - 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
234
  - Create `glimmer/dsl/[dsl_name]/[expresion_name]_expresion.rb` for every [expresion_name] expression needed, whether dynamic or static
216
235
 
@@ -734,83 +753,6 @@ You should see "Apple Calculator Theme"
734
753
 
735
754
  [![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)
736
755
 
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
756
  #### Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
815
757
 
816
758
  [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.).
@@ -856,7 +798,7 @@ Glimmer app:
856
798
 
857
799
  ![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)
858
800
 
859
- ###### Hello, Tab!
801
+ ###### Hello, Notebook!
860
802
 
861
803
  Glimmer code (from [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_tab.rb)):
862
804
 
@@ -864,7 +806,7 @@ Glimmer code (from [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/gl
864
806
  include Glimmer
865
807
 
866
808
  root {
867
- title 'Hello, Tab!'
809
+ title 'Hello, Notebook!'
868
810
 
869
811
  notebook {
870
812
  frame(text: 'English') {
@@ -885,48 +827,71 @@ root {
885
827
  Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
886
828
 
887
829
  ```
888
- ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_tab.rb'"
830
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_notebook.rb'"
889
831
  ```
890
832
 
891
833
  Glimmer app:
892
834
 
893
- ![glimmer dsl tk screenshot sample hello tab English](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-tab-english.png)
894
- ![glimmer dsl tk screenshot sample hello tab French](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-tab-french.png)
835
+ ![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)
836
+ ![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)
895
837
 
896
- ###### Hello, Combo!
838
+ ###### Hello, Combobox!
897
839
 
898
- Glimmer code (from [samples/hello/hello_combo.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_combo.rb)):
840
+ Glimmer code (from [samples/hello/hello_combobox.rb](https://github.com/AndyObtiva/glimmer-dsl-tk/blob/master/samples/hello/hello_combobox.rb)):
899
841
 
900
842
  ```ruby
901
- # ... more code precedes
902
- root {
903
- title 'Hello, Combo!'
904
-
905
- combobox { |proxy|
906
- state 'readonly'
907
- text bind(person, :country)
908
- }
843
+ require 'glimmer-dsl-tk'
844
+
845
+ class Person
846
+ attr_accessor :country, :country_options
847
+
848
+ def initialize
849
+ self.country_options=["", "Canada", "US", "Mexico"]
850
+ self.country = "Canada"
851
+ end
852
+
853
+ def reset_country
854
+ self.country = "Canada"
855
+ end
856
+ end
857
+
858
+ class HelloCombobox
859
+ include Glimmer
909
860
 
910
- button { |proxy|
911
- text "Reset Selection"
912
- command {
913
- person.reset_country
914
- }
915
- }
916
- }.open
917
- # ... more code follows
861
+ def launch
862
+ person = Person.new
863
+
864
+ root {
865
+ title 'Hello, Combobox!'
866
+
867
+ combobox {
868
+ readonly true # this applies to text editing only (item selection still triggers a write to model)
869
+ text <=> [person, :country]
870
+ }
871
+
872
+ button {
873
+ text "Reset Selection"
874
+ command {
875
+ person.reset_country
876
+ }
877
+ }
878
+ }.open
879
+ end
880
+ end
881
+
882
+ HelloCombobox.new.launch
918
883
  ```
919
884
 
920
885
  Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
921
886
 
922
887
  ```
923
- ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combo.rb'"
888
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combobox.rb'"
924
889
  ```
925
890
 
926
891
  Glimmer app:
927
892
 
928
- ![glimmer dsl tk screenshot sample hello combo](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-combo.png)
929
- ![glimmer dsl tk screenshot sample hello combo dropdown](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-tk/master/images/glimmer-dsl-tk-screenshot-sample-hello-combo-dropdown.png)
893
+ ![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)
894
+ ![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)
930
895
 
931
896
  #### Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
932
897
 
@@ -961,257 +926,254 @@ Mac
961
926
 
962
927
  ![glimmer-dsl-libui-mac-basic-window.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-basic-window.png)
963
928
 
929
+ Windows
930
+
931
+ ![glimmer-dsl-libui-windows-basic-window.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-basic-window.png)
932
+
964
933
  Linux
965
934
 
966
935
  ![glimmer-dsl-libui-linux-basic-window.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-basic-window.png)
967
936
 
968
- ###### Basic Button
937
+ ###### Basic Table Progress Bar
969
938
 
970
939
  ```ruby
971
940
  require 'glimmer-dsl-libui'
972
941
 
973
942
  include Glimmer
974
943
 
975
- window('hello world', 300, 200) { |w|
976
- button('Button') {
977
- on_clicked do
978
- msg_box(w, 'Information', 'You clicked the button')
979
- end
944
+ data = [
945
+ ['task 1', 0],
946
+ ['task 2', 15],
947
+ ['task 3', 100],
948
+ ['task 4', 75],
949
+ ['task 5', -1],
950
+ ]
951
+
952
+ window('Task Progress', 300, 200) {
953
+ vertical_box {
954
+ table {
955
+ text_column('Task')
956
+ progress_bar_column('Progress')
957
+
958
+ cell_rows data # implicit data-binding
959
+ }
960
+
961
+ button('Mark All As Done') {
962
+ stretchy false
963
+
964
+ on_clicked do
965
+ data.each_with_index do |row_data, row|
966
+ data[row] = [row_data[0], 100] # automatically updates table due to implicit data-binding
967
+ end
968
+ end
969
+ }
980
970
  }
981
-
982
- on_closing do
983
- puts 'Bye Bye'
984
- end
985
971
  }.show
986
972
  ```
987
973
 
988
974
  Mac
989
975
 
990
- ![glimmer-dsl-libui-mac-basic-button.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-basic-button.png)
991
- ![glimmer-dsl-libui-mac-basic-button-msg-box.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-basic-button-msg-box.png)
976
+ ![glimmer-dsl-libui-mac-basic-table-progress-bar.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-basic-table-progress-bar.png)
977
+
978
+ Windows
979
+
980
+ ![glimmer-dsl-libui-windows-basic-table-progress-bar.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-basic-table-progress-bar.png)
992
981
 
993
982
  Linux
994
983
 
995
- ![glimmer-dsl-libui-linux-basic-button.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-basic-button.png)
996
- ![glimmer-dsl-libui-linux-basic-button-msg-box.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-basic-button-msg-box.png)
984
+ ![glimmer-dsl-libui-linux-basic-table-progress-bar.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-basic-table-progress-bar.png)
997
985
 
998
- ###### Control Gallery
986
+ ###### Area Gallery
999
987
 
1000
988
  ```ruby
1001
989
  require 'glimmer-dsl-libui'
1002
990
 
1003
991
  include Glimmer
1004
992
 
1005
- menu('File') {
1006
- menu_item('Open') {
1007
- on_clicked do
1008
- file = open_file(MAIN_WINDOW)
1009
- puts file unless file.nil?
1010
- end
1011
- }
1012
-
1013
- menu_item('Save') {
1014
- on_clicked do
1015
- file = save_file(MAIN_WINDOW)
1016
- puts file unless file.nil?
1017
- end
1018
- }
1019
-
1020
- quit_menu_item {
1021
- on_clicked do
1022
- puts 'Bye Bye'
1023
- end
1024
- }
1025
-
1026
- preferences_menu_item # Can optionally contain an on_clicked listener
1027
- }
1028
-
1029
- menu('Edit') {
1030
- check_menu_item('Checkable Item_')
1031
- separator_menu_item
1032
- menu_item('Disabled Item_') {
1033
- enabled false
1034
- }
1035
- }
1036
-
1037
- menu('Help') {
1038
- menu_item('Help')
1039
-
1040
- about_menu_item # Can optionally contain an on_clicked listener
1041
- }
1042
-
1043
- MAIN_WINDOW = window('Control Gallery', 600, 500) {
1044
- margined true
1045
-
1046
- on_closing do
1047
- puts 'Bye Bye'
1048
- end
1049
-
1050
- vertical_box {
1051
- horizontal_box {
1052
- group('Basic Controls') {
1053
- vertical_box {
1054
- button('Button') {
1055
- stretchy false
1056
-
1057
- on_clicked do
1058
- msg_box(MAIN_WINDOW, 'Information', 'You clicked the button')
1059
- end
1060
- }
1061
-
1062
- checkbox('Checkbox') {
1063
- stretchy false
1064
-
1065
- on_toggled do |c|
1066
- checked = c.checked == 1
1067
- MAIN_WINDOW.title = "Checkbox is #{checked}"
1068
- c.text = "I am the checkbox (#{checked})"
1069
- end
1070
- }
993
+ window('Area Gallery', 400, 400) {
994
+ area {
995
+ path { # declarative stable path
996
+ square(0, 0, 100)
997
+ square(100, 100, 400)
998
+
999
+ fill r: 102, g: 102, b: 204
1000
+ }
1001
+ path { # declarative stable path
1002
+ rectangle(0, 100, 100, 400)
1003
+ rectangle(100, 0, 400, 100)
1004
+
1005
+ fill r: 204, g: 102, b: 204
1006
+ }
1007
+ path { # declarative stable path
1008
+ figure(100, 100) {
1009
+ line(100, 400)
1010
+ line(400, 100)
1011
+ line(400, 400)
1071
1012
 
1072
- label('Label') { stretchy false }
1013
+ closed true
1014
+ }
1073
1015
 
1074
- horizontal_separator { stretchy false }
1016
+ fill r: 202, g: 102, b: 104, a: 0.5
1017
+ stroke r: 0, g: 0, b: 0
1018
+ }
1019
+ path { # declarative stable path
1020
+ figure(0, 0) {
1021
+ bezier(200, 100, 100, 200, 400, 100)
1022
+ bezier(300, 100, 100, 300, 100, 400)
1023
+ bezier(100, 300, 300, 100, 400, 400)
1075
1024
 
1076
- date_picker { stretchy false }
1025
+ closed true
1026
+ }
1077
1027
 
1078
- time_picker { stretchy false }
1028
+ fill r: 202, g: 102, b: 204, a: 0.5
1029
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
1030
+ }
1031
+ path { # declarative stable path
1032
+ arc(200, 200, 90, 0, 360, false)
1079
1033
 
1080
- date_time_picker { stretchy false }
1034
+ fill r: 202, g: 102, b: 204, a: 0.5
1035
+ stroke r: 0, g: 0, b: 0, thickness: 2
1036
+ }
1037
+
1038
+ on_mouse_event do |area_mouse_event|
1039
+ p area_mouse_event
1040
+ end
1041
+
1042
+ on_mouse_moved do |area_mouse_event|
1043
+ puts 'moved'
1044
+ end
1045
+
1046
+ on_mouse_down do |area_mouse_event|
1047
+ puts 'mouse down'
1048
+ end
1049
+
1050
+ on_mouse_up do |area_mouse_event|
1051
+ puts 'mouse up'
1052
+ end
1053
+
1054
+ on_mouse_drag_started do |area_mouse_event|
1055
+ puts 'drag started'
1056
+ end
1057
+
1058
+ on_mouse_dragged do |area_mouse_event|
1059
+ puts 'dragged'
1060
+ end
1061
+
1062
+ on_mouse_dropped do |area_mouse_event|
1063
+ puts 'dropped'
1064
+ end
1065
+
1066
+ on_mouse_entered do
1067
+ puts 'entered'
1068
+ end
1069
+
1070
+ on_mouse_exited do
1071
+ puts 'exited'
1072
+ end
1073
+
1074
+ on_key_event do |area_key_event|
1075
+ p area_key_event
1076
+ end
1077
+
1078
+ on_key_up do |area_key_event|
1079
+ puts 'key up'
1080
+ end
1081
+
1082
+ on_key_down do |area_key_event|
1083
+ puts 'key down'
1084
+ end
1085
+ }
1086
+ }.show
1087
+ ```
1081
1088
 
1082
- font_button { stretchy false }
1089
+ Mac
1083
1090
 
1084
- color_button { stretchy false }
1085
- }
1086
- }
1091
+ ![glimmer-dsl-libui-mac-area-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-area-gallery.png)
1087
1092
 
1088
- vertical_box {
1089
- group('Numbers') {
1090
- stretchy false
1093
+ Windows
1091
1094
 
1092
- vertical_box {
1093
- spinbox(0, 100) {
1094
- stretchy false
1095
- value 42
1095
+ ![glimmer-dsl-libui-windows-area-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-area-gallery.png)
1096
1096
 
1097
- on_changed do |s|
1098
- puts "New Spinbox value: #{s.value}"
1099
- end
1100
- }
1097
+ Linux
1101
1098
 
1102
- slider(0, 100) {
1103
- stretchy false
1099
+ ![glimmer-dsl-libui-linux-area-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-area-gallery.png)
1104
1100
 
1105
- on_changed do |s|
1106
- v = s.value
1107
- puts "New Slider value: #{v}"
1108
- @progress_bar.value = v
1109
- end
1110
- }
1101
+ #### Glimmer DSL for XML (& HTML)
1111
1102
 
1112
- @progress_bar = progress_bar { stretchy false }
1113
- }
1114
- }
1103
+ [Glimmer DSL for XML](https://github.com/AndyObtiva/glimmer-dsl-xml) provides Ruby syntax for building XML (eXtensible Markup Language) documents.
1115
1104
 
1116
- group('Lists') {
1117
- stretchy false
1105
+ 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).
1118
1106
 
1119
- vertical_box {
1120
- combobox {
1121
- stretchy false
1122
- items 'combobox Item 1', 'combobox Item 2', 'combobox Item 3' # also accepts a single array argument
1107
+ ##### XML DSL
1123
1108
 
1124
- on_selected do |c|
1125
- puts "New combobox selection: #{c.selected}"
1126
- end
1127
- }
1109
+ Simply start with `html` keyword and add HTML inside its block using Glimmer DSL syntax.
1110
+ Once done, you may call `to_s`, `to_xml`, or `to_html` to get the formatted HTML output.
1128
1111
 
1129
- editable_combobox {
1130
- stretchy false
1131
- items 'Editable Item 1', 'Editable Item 2', 'Editable Item 3' # also accepts a single array argument
1132
- }
1112
+ Here are all the Glimmer XML DSL top-level keywords:
1113
+ - `html`
1114
+ - `tag`: enables custom tag creation for exceptional cases by passing tag name as '_name' attribute
1115
+ - `name_space`: enables namespacing html tags
1133
1116
 
1134
- radio_buttons {
1135
- items 'Radio Button 1', 'Radio Button 2', 'Radio Button 3' # also accepts a single array argument
1136
- }
1137
- }
1138
- }
1117
+ 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')` )
1139
1118
 
1140
- tab {
1141
- tab_item('Page 1') {
1142
- horizontal_box {
1143
- entry {
1144
- text 'Please enter your feelings'
1119
+ Example (basic HTML):
1145
1120
 
1146
- on_changed do |e|
1147
- puts "Current textbox data: '#{e.text}'"
1148
- end
1149
- }
1150
- }
1151
- }
1152
-
1153
- tab_item('Page 2') {
1154
- horizontal_box
1155
- }
1156
-
1157
- tab_item('Page 3') {
1158
- horizontal_box
1159
- }
1160
- }
1161
- }
1162
- }
1121
+ ```ruby
1122
+ @xml = html {
1123
+ head {
1124
+ meta(name: "viewport", content: "width=device-width, initial-scale=2.0")
1125
+ }
1126
+ body {
1127
+ h1 { "Hello, World!" }
1163
1128
  }
1164
1129
  }
1165
-
1166
- MAIN_WINDOW.show
1130
+ puts @xml
1167
1131
  ```
1168
1132
 
1169
- Mac
1133
+ Output:
1170
1134
 
1171
- ![glimmer-dsl-libui-mac-control-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-control-gallery.png)
1135
+ ```
1136
+ <html><head><meta name="viewport" content="width=device-width, initial-scale=2.0" /></head><body><h1>Hello, World!</h1></body></html>
1137
+ ```
1172
1138
 
1173
- Linux
1139
+ #### Glimmer DSL for CSS
1174
1140
 
1175
- ![glimmer-dsl-libui-linux-control-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-control-gallery.png)
1141
+ [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css) provides Ruby syntax for building CSS (Cascading Style Sheets).
1176
1142
 
1177
- ###### Basic Table
1143
+ 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).
1178
1144
 
1179
- ```ruby
1180
- require 'glimmer-dsl-libui'
1145
+ ##### CSS DSL
1181
1146
 
1182
- include Glimmer
1147
+ Simply start with `css` keyword and add stylesheet rule sets inside its block using Glimmer DSL syntax.
1148
+ Once done, you may call `to_s` or `to_css` to get the formatted CSS output.
1183
1149
 
1184
- data = [
1185
- %w[cat meow],
1186
- %w[dog woof],
1187
- %w[chicken cock-a-doodle-doo],
1188
- %w[hourse neigh],
1189
- %w[cow moo]
1190
- ]
1150
+ `css` is the only top-level keyword in the Glimmer CSS DSL
1191
1151
 
1192
- window('Animal sounds', 300, 200) {
1193
- horizontal_box {
1194
- table {
1195
- text_column('Animal')
1196
- text_column('Description')
1152
+ Selectors may be specified by `s` keyword or HTML element keyword directly (e.g. `body`)
1153
+ Rule property values may be specified by `pv` keyword or underscored property name directly (e.g. `font_size`)
1197
1154
 
1198
- cell_rows data
1199
- }
1155
+ Example:
1156
+
1157
+ ```ruby
1158
+ @css = css {
1159
+ body {
1160
+ font_size '1.1em'
1161
+ pv 'background', 'white'
1200
1162
  }
1201
1163
 
1202
- on_closing do
1203
- puts 'Bye Bye'
1204
- end
1205
- }.show
1164
+ s('body > h1') {
1165
+ background_color :red
1166
+ pv 'font-size', '2em'
1167
+ }
1168
+ }
1169
+ puts @css
1206
1170
  ```
1207
1171
 
1208
- Mac
1209
-
1210
- ![glimmer-dsl-libui-mac-basic-table.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-basic-table.png)
1211
-
1212
- Linux
1172
+ Output:
1213
1173
 
1214
- ![glimmer-dsl-libui-linux-basic-table.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-basic-table.png)
1174
+ ```
1175
+ body{font-size:1.1em;background:white}body > h1{background-color:red;font-size:2em}
1176
+ ```
1215
1177
 
1216
1178
  ## Data-Binding Library
1217
1179
 
@@ -1225,12 +1187,76 @@ These are the main classes concerning data-binding:
1225
1187
  - `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`)
1226
1188
  - `Glimmer::DataBinding::Observable`: General super-module for all observables. Main methods concerned are: `add_observer` and `remove_observer`
1227
1189
  - `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.
1228
- - `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`)
1190
+ - `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).
1229
1191
  - `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!`)
1230
1192
  - `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
1231
1193
  - `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 `<=`
1232
1194
 
1233
- You may learn more from [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)
1195
+ 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`).
1196
+
1197
+ Example of observing a model attribute:
1198
+
1199
+ ```ruby
1200
+ Glimmer::DataBinding::Observer.proc do |new_value|
1201
+ # Do some work with new value for model attribute
1202
+ end.observe(model, attribute)
1203
+ ```
1204
+
1205
+ Example of observing an array recursively (avoid recursion unless really needed since it fires on all fine-grained nested array changes):
1206
+
1207
+ ```ruby
1208
+ Glimmer::DataBinding::Observer.proc do |new_value|
1209
+ # Do some work with new array value
1210
+ end.observe(array, recursive: true)
1211
+ ```
1212
+
1213
+ Example of observing a hash key:
1214
+
1215
+ ```ruby
1216
+ Glimmer::DataBinding::Observer.proc do |new_value|
1217
+ # Do some work with new value for hash key
1218
+ end.observe(hash, :price)
1219
+ ```
1220
+
1221
+ Example of observing a hash for all key changes:
1222
+
1223
+ ```ruby
1224
+ Glimmer::DataBinding::Observer.proc do |new_value, changed_key|
1225
+ # Do some work with new value and changed key for hash
1226
+ end.observe(hash)
1227
+ ```
1228
+
1229
+ 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.
1230
+
1231
+ Example of observing nested model attributes:
1232
+
1233
+ ```ruby
1234
+ ModelBinding.new(model, "address1.street").add_observer do |new_address1_street_value|
1235
+ # Do some work with new address 1 street value
1236
+ end
1237
+ ```
1238
+
1239
+ Example of observing indexed array changes (combined with a nested model attribute):
1240
+
1241
+ ```ruby
1242
+ ModelBinding.new(model, "employees[5].name").add_observer do |new_employee_6_name|
1243
+ # Do some work with new employee 6 (index 5)'s name
1244
+ end
1245
+ ```
1246
+
1247
+ Example of observing double-indexed nested array changes:
1248
+
1249
+ ```ruby
1250
+ ModelBinding.new(model, "grid[5][7]").add_observer do |new_grid_cell_value|
1251
+ # Do some work with new grid cell value for row index 5 and column index 7
1252
+ end
1253
+ ```
1254
+
1255
+ 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.
1256
+
1257
+ All of the features above make Glimmer's data-binding library one of the most sophisticated and advanced in the industry since they automate everything instead of requiring endless manual configuration, thus resulting in some of the tersest most declarative syntax for using observers and data-binding.
1258
+
1259
+ 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)
1234
1260
 
1235
1261
  ## Glimmer Process
1236
1262
 
@@ -1283,8 +1309,9 @@ If you would like to contribute to Glimmer, please study up on Glimmer and [SWT]
1283
1309
 
1284
1310
  You may apply for contributing to any of these Glimmer DSL gems whether you prefer to focus on the desktop or web:
1285
1311
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
1286
- - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
1287
1312
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
1313
+ - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
1314
+ - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
1288
1315
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
1289
1316
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
1290
1317