glimmer-dsl-opal 0.0.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/README.md +995 -74
  4. data/VERSION +1 -1
  5. data/lib/glimmer-dsl-opal.rb +42 -7
  6. data/lib/glimmer-dsl-opal/ext/exception.rb +5 -0
  7. data/lib/glimmer-dsl-opal/missing/net/http.rb +17 -0
  8. data/lib/glimmer-dsl-opal/missing/uri.rb +26 -0
  9. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager.rb +2 -3
  10. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact.rb +0 -0
  11. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact_manager_presenter.rb +0 -0
  12. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact_repository.rb +24 -99
  13. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/login.rb +0 -1
  14. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe.rb +5 -5
  15. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe/board.rb +0 -0
  16. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe/cell.rb +0 -0
  17. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_browser.rb +0 -0
  18. data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +63 -0
  19. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_computed.rb +19 -19
  20. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_computed/contact.rb +0 -0
  21. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_shell.rb +155 -0
  22. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_widget.rb +86 -0
  23. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_list_multi_selection.rb +0 -0
  24. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_list_single_selection.rb +0 -0
  25. data/lib/glimmer-dsl-opal/samples/hello/hello_tab.rb +50 -0
  26. data/lib/glimmer-dsl-opal/samples/hello/hello_world.rb +29 -0
  27. data/lib/glimmer-dsl-opal/vendor/jquery.js +2 -0
  28. data/lib/glimmer/data_binding/element_binding.rb +1 -1
  29. data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
  30. data/lib/glimmer/data_binding/list_selection_binding.rb +1 -1
  31. data/lib/glimmer/data_binding/table_items_binding.rb +70 -0
  32. data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
  33. data/lib/glimmer/dsl/opal/color_expression.rb +38 -0
  34. data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
  35. data/lib/glimmer/dsl/opal/combo_selection_data_binding_expression.rb +2 -2
  36. data/lib/glimmer/dsl/opal/custom_widget_expression.rb +57 -0
  37. data/lib/glimmer/dsl/opal/dsl.rb +17 -14
  38. data/lib/glimmer/dsl/opal/font_expression.rb +47 -0
  39. data/lib/glimmer/dsl/opal/layout_data_expression.rb +2 -2
  40. data/lib/glimmer/dsl/opal/{text_expression.rb → layout_expression.rb} +5 -5
  41. data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +2 -3
  42. data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
  43. data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
  44. data/lib/glimmer/dsl/opal/property_expression.rb +5 -2
  45. data/lib/glimmer/dsl/opal/rgb_expression.rb +32 -0
  46. data/lib/glimmer/dsl/opal/rgba_expression.rb +32 -0
  47. data/lib/glimmer/dsl/opal/shell_expression.rb +2 -2
  48. data/lib/glimmer/dsl/opal/swt_expression.rb +46 -0
  49. data/lib/glimmer/dsl/opal/{composite_expression.rb → table_column_expression.rb} +3 -3
  50. data/lib/glimmer/dsl/opal/{list_expression.rb → table_expression.rb} +3 -3
  51. data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
  52. data/lib/glimmer/dsl/opal/widget_expression.rb +24 -0
  53. data/lib/glimmer/dsl/opal/widget_listener_expression.rb +16 -3
  54. data/lib/glimmer/swt.rb +499 -0
  55. data/lib/glimmer/swt/browser_proxy.rb +27 -0
  56. data/lib/glimmer/swt/button_proxy.rb +40 -0
  57. data/lib/glimmer/swt/color_proxy.rb +119 -0
  58. data/lib/glimmer/{opal/select_proxy.rb → swt/combo_proxy.rb} +24 -19
  59. data/lib/glimmer/swt/composite_proxy.rb +31 -0
  60. data/lib/glimmer/swt/display_proxy.rb +25 -0
  61. data/lib/glimmer/{opal → swt}/event_listener_proxy.rb +1 -1
  62. data/lib/glimmer/swt/fill_layout_proxy.rb +84 -0
  63. data/lib/glimmer/swt/font_proxy.rb +79 -0
  64. data/lib/glimmer/swt/grid_layout_proxy.rb +71 -0
  65. data/lib/glimmer/swt/label_proxy.rb +34 -0
  66. data/lib/glimmer/swt/layout_data_proxy.rb +52 -0
  67. data/lib/glimmer/swt/layout_proxy.rb +62 -0
  68. data/lib/glimmer/{opal → swt}/list_proxy.rb +31 -23
  69. data/lib/glimmer/swt/message_box_proxy.rb +143 -0
  70. data/lib/glimmer/{opal → swt}/point.rb +1 -1
  71. data/lib/glimmer/{opal → swt}/property_owner.rb +1 -1
  72. data/lib/glimmer/swt/row_layout_proxy.rb +105 -0
  73. data/lib/glimmer/swt/shell_proxy.rb +245 -0
  74. data/lib/glimmer/swt/style_constantizable.rb +154 -0
  75. data/lib/glimmer/swt/swt_proxy.rb +53 -0
  76. data/lib/glimmer/{opal/tab_folder.rb → swt/tab_folder_proxy.rb} +21 -15
  77. data/lib/glimmer/swt/tab_item_proxy.rb +84 -0
  78. data/lib/glimmer/swt/table_column_proxy.rb +56 -0
  79. data/lib/glimmer/swt/table_item_proxy.rb +147 -0
  80. data/lib/glimmer/swt/table_proxy.rb +159 -0
  81. data/lib/glimmer/swt/text_proxy.rb +46 -0
  82. data/lib/glimmer/swt/widget_proxy.rb +490 -0
  83. data/lib/glimmer/ui/custom_shell.rb +73 -0
  84. data/lib/glimmer/ui/custom_widget.rb +290 -0
  85. data/lib/glimmer/util/proc_tracker.rb +39 -0
  86. metadata +134 -74
  87. data/lib/glimmer/config.rb +0 -22
  88. data/lib/glimmer/dsl/engine.rb +0 -193
  89. data/lib/glimmer/dsl/expression.rb +0 -42
  90. data/lib/glimmer/dsl/expression_handler.rb +0 -48
  91. data/lib/glimmer/dsl/opal/browser_expression.rb +0 -17
  92. data/lib/glimmer/dsl/opal/button_expression.rb +0 -18
  93. data/lib/glimmer/dsl/opal/combo_expression.rb +0 -17
  94. data/lib/glimmer/dsl/opal/grid_layout_expression.rb +0 -17
  95. data/lib/glimmer/dsl/opal/label_expression.rb +0 -17
  96. data/lib/glimmer/dsl/opal/tab_folder_expression.rb +0 -17
  97. data/lib/glimmer/dsl/opal/tab_item_expression.rb +0 -17
  98. data/lib/glimmer/dsl/parent_expression.rb +0 -12
  99. data/lib/glimmer/dsl/static_expression.rb +0 -36
  100. data/lib/glimmer/dsl/top_level_expression.rb +0 -7
  101. data/lib/glimmer/error.rb +0 -6
  102. data/lib/glimmer/invalid_keyword_error.rb +0 -6
  103. data/lib/glimmer/opal/div_proxy.rb +0 -22
  104. data/lib/glimmer/opal/document_proxy.rb +0 -128
  105. data/lib/glimmer/opal/element_proxy.rb +0 -281
  106. data/lib/glimmer/opal/grid_layout_proxy.rb +0 -53
  107. data/lib/glimmer/opal/iframe_proxy.rb +0 -23
  108. data/lib/glimmer/opal/input_proxy.rb +0 -41
  109. data/lib/glimmer/opal/label_proxy.rb +0 -25
  110. data/lib/glimmer/opal/layout_data_proxy.rb +0 -31
  111. data/lib/glimmer/opal/tab_item.rb +0 -98
  112. data/lib/samples/elaborate/launch +0 -6
  113. data/lib/samples/hello/hello_combo.rb +0 -34
  114. data/lib/samples/hello/hello_tab.rb +0 -24
  115. data/lib/samples/hello/hello_world.rb +0 -8
  116. data/lib/samples/hello/launch +0 -10
  117. data/lib/samples/launch +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbf51689c9728f9af6a7670f703584c79def82be3f74085556f91cbc9f02cd51
4
- data.tar.gz: e73b3c81aa113ca61e080a5c0fce7299c0812c04883aaf8864bdec5dc80fad00
3
+ metadata.gz: 4149153253dd59829bf590c406ff2e5b18c11a62cbbaf7130877f2046a04d2a1
4
+ data.tar.gz: f82f4d9c0bff2625f1f4ef8bef4be2703789a72aed847d4c851697d916cf48c4
5
5
  SHA512:
6
- metadata.gz: 98c27b51a8de0e218ed4e888660fb6dbf110deda9b1444b7fd75dc72d5477a5eaa277d2a64d92f223bcf0d3b8c398bf2da369a26e000c2544c34952c9fd7f8ad
7
- data.tar.gz: 05725471322ba4a5e55115360fa2a970e69c6f076c36480b3354c86968ac796e63c0e0c1250ca2639f100a329363c51fc7a0254b66a918aa7ed4130f538c2ce4
6
+ metadata.gz: 202c4686ab1a2bf31377cbe4ee6f173c92318460e0758cb74356132323c571b381f3bd69d0d47933ac44c54a79fd24520ce7c2e1ffa1412db903ae2c27ce259b
7
+ data.tar.gz: 182085ad652639b3d83b9853bf993702839cb8066074b92e5377b5b8aa1998d659d925ef0d1f5cac0c659241bd97cf7fe109d2008142e0f5b34165f49e93bc67
@@ -1,5 +1,55 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.2.0
4
+
5
+ - Color support
6
+ - Font support
7
+ - Custom Widget Support
8
+ - Hello, Custom Widget! sample
9
+ - Updated Hello, Combo! sample to match the latest changes in Glimmer DSL for SWT
10
+ - `SWT` full re-implementation in Opal as `Glimmer::SWT` with all the `SWT` style constants
11
+
12
+ ## 0.1.0
13
+
14
+ - Code redesign to better match the glimmer-dsl-swt APIs
15
+ - opal-jquery refactoring
16
+ - opal-rspec test coverage
17
+
18
+ ## 0.0.9
19
+
20
+ - Upgraded to glimmer gem v0.9.3
21
+ - Fixed issue with missing Glimmer::Opal::ElementProxy#id=(value) method breaking Contact Manager sample Find feature
22
+
23
+ ## 0.0.8
24
+
25
+ - Contact Manager sample support
26
+
27
+ ## 0.0.7
28
+
29
+ - Tic Tac Toe sample support
30
+ - Login sample support
31
+
32
+ ## 0.0.6
33
+
34
+ - Hello, Tab! sample support
35
+
36
+ ## 0.0.5
37
+
38
+ - Hello, Browser! sample support
39
+
40
+ ## 0.0.4
41
+
42
+ - Hello, List Single Selection! sample support
43
+ - Hello, List Multi Selection! sample support
44
+
45
+ ## 0.0.3
46
+
47
+ - Hello, Computed! sample support
48
+
49
+ ## 0.0.2
50
+
51
+ - Hello, Combo! sample support
52
+
3
53
  ## 0.0.1
4
54
 
5
55
  - Initial support for webifying Glimmer SWT apps
data/README.md CHANGED
@@ -1,12 +1,14 @@
1
- # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=65 /> Glimmer DSL for Opal 0.0.6 (Web GUI for Desktop Apps)
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Opal 0.2.0 (Webify Desktop Apps)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-opal.svg)](http://badge.fury.io/rb/glimmer-dsl-opal)
3
3
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
4
 
5
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Opal is a web GUI adaptor for desktop apps built with [Glimmer](https://github.com/AndyObtiva/glimmer) & [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt).
5
+ ### You can finally live in pure Ruby land even on the web!
6
6
 
7
- It enables running [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps on the web via [Rails](https://rubyonrails.org/) 5 and [Opal](https://opalrb.com/) 1.
7
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Opal](https://opalrb.com/) is an experimental proof-of-concept web GUI adapter for [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)). It webifies them via [Rails](https://rubyonrails.org/), allowing Ruby desktop apps to run on the web via [Opal Ruby](https://opalrb.com/) without changing a line of code. Apps may then be custom-styled for the web with standard CSS by web designers.
8
8
 
9
- NOTE: Alpha Version 0.0.6 only supports Hello sample capabilities (detailed under [Examples](#examples)):
9
+ Glimmer DSL for Opal webifier successfully reuses the entire [Glimmer](https://github.com/AndyObtiva/glimmer) core DSL engine in [Opal Ruby](https://opalrb.com/) inside a web browser, and as such inherits the full range of powerful Glimmer desktop [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities for the web.
10
+
11
+ NOTE: Alpha Version 0.2.0 only supports bare-minimum capabilities for the following [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) [samples](https://github.com/AndyObtiva/glimmer#samples):
10
12
  - [Hello, World!](#hello-world)
11
13
  - [Hello, Combo!](#hello-combo)
12
14
  - [Hello, Computed!](#hello-computed)
@@ -14,9 +16,14 @@ NOTE: Alpha Version 0.0.6 only supports Hello sample capabilities (detailed unde
14
16
  - [Hello, List Multi Selection!](#hello-list-multi-selection)
15
17
  - [Hello, Browser!](#hello-browser)
16
18
  - [Hello, Tab!](#hello-tab)
17
-
18
- Other Glimmer DSL gems:
19
- - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
19
+ - [Hello, Custom Widget!](#hello-custom-widget)
20
+ - [Login](#login)
21
+ - [Tic Tac Toe](#tic-tac-toe)
22
+ - [Contact Manager](#contact-manager)
23
+
24
+ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
25
+ - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Library)
26
+ - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (Ruby Desktop Development GUI Library)
20
27
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
21
28
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
22
29
 
@@ -24,6 +31,7 @@ Other Glimmer DSL gems:
24
31
 
25
32
  The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) have partial support in Opal:
26
33
 
34
+ Widgets:
27
35
  - `shell`
28
36
  - `label`
29
37
  - `combo`
@@ -33,51 +41,111 @@ The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glim
33
41
  - `list` & `list(:multi)`
34
42
  - `tab_folder`
35
43
  - `tab_item`
36
- - `on_widget_selected`
37
- - `on_modify_text`
44
+ - `table`
45
+ - `table_column`
46
+ - `message_box`
47
+
48
+ Graphics:
49
+ - `color`
50
+ - `font`
51
+
52
+ Layouts:
38
53
  - `grid_layout`
54
+ - `row_layout`
55
+ - `fill_layout`
39
56
  - `layout_data`
40
57
 
58
+ Data-Binding/Observers:
59
+ - `bind`
60
+ - `observe`
61
+ - `on_widget_selected`
62
+ - `on_modify_text`
63
+
64
+ Event loop:
65
+ - `async_exec`
66
+
41
67
  ## Pre-requisites
42
68
 
43
69
  - Rails 5: [https://github.com/rails/rails/tree/5-2-stable](https://github.com/rails/rails/tree/5-2-stable)
44
70
  - Opal 1: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
71
+ - jQuery 3: [https://code.jquery.com/](https://code.jquery.com/) (jQuery 3.5.1 is included in the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem)
45
72
 
46
73
  ## Setup
47
74
 
48
- Please follow these instructions to make Glimmer desktop apps work in Opal inside Rails 5
75
+ (NOTE: if you run into issues, keep in mind this is a very early experimental and incomplete alpha. Also, there is a slight chance issues you encounter are fixed in master or some other branch that you could check out instead)
76
+
77
+ Please install a Rails 5 gem (e.g. `gem install rails -v5.2.4.3` )
49
78
 
50
79
  Start a new Rails 5 app:
51
80
 
52
81
  ```
53
- rails new hello_world
82
+ rails new glimmer_app
54
83
  ```
55
84
 
56
- Follow instructions to setup opal with a rails application: config/initializers/assets.rb
85
+ Add the following to `Gemfile`:
57
86
 
58
- Add the following to `Gemfile` (NOTE: if you run into issues, they are probably fixed in master or development/wip branch, you may check out instead):
59
87
  ```
60
- gem 'opal-rails'
61
- gem 'opal-browser'
62
- gem 'glimmer-dsl-opal', '~> 0.0.6', require: false
88
+ gem 'opal-rails', '~> 1.1.2'
89
+ gem 'opal-async', '~> 1.1.1'
90
+ gem 'opal-jquery', '~> 0.4.4'
91
+ gem 'glimmer-dsl-opal', '~> 0.2.0', require: false
92
+ gem 'glimmer-dsl-xml', '~> 1.0.0', require: false
93
+ gem 'glimmer-dsl-css', '~> 1.0.0', require: false
94
+
63
95
  ```
64
96
 
65
- Edit `config/initializers/assets.rb` and add:
97
+ Follow (opal-rails)[https://github.com/opal/opal-rails] instructions, basically the configuration of: config/initializers/assets.rb
98
+
99
+ Edit `config/initializers/assets.rb` and add the following at the bottom:
66
100
  ```
67
101
  Opal.use_gem 'glimmer-dsl-opal'
68
102
  ```
69
103
 
70
- Add the following line to the top of an empty `app/assets/javascripts/application.js.rb`
104
+ Add the following line to the top of an empty `app/assets/javascripts/application.rb` (replacing `application.js`)
71
105
 
72
106
  ```ruby
73
- require 'glimmer-dsl-opal' # brings opal and opal browser too
107
+ require 'glimmer-dsl-opal' # brings opal and other dependencies automatically
108
+ ```
109
+
110
+ Run:
111
+
112
+ ```
113
+ rails g scaffold welcome
74
114
  ```
75
115
 
76
- ## Examples
116
+ Modify `config/routes.rb`:
77
117
 
78
- ### Hello, World!
118
+ ```ruby
119
+ root to: 'welcome#index'
120
+ ```
79
121
 
80
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
122
+ Add more code to `app/assets/javascripts/application.rb` inside a `Document.ready?` block from one of the samples below or a [Glimmer](https://github.com/AndyObtiva/glimmer) [app](https://github.com/AndyObtiva/glimmer#app)/[custom-shell gem](https://github.com/AndyObtiva/glimmer#custom-shell-gem).
123
+
124
+ ```ruby
125
+ Document.ready? do
126
+ # require-statement/code goes here.
127
+ end
128
+ ```
129
+
130
+ ## Samples
131
+
132
+ Follow the instructions below to try out [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) samples webified via [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal)
133
+
134
+ Also, this external sample app contains all the samples mentioned below configured inside a Rails 5 [Opal](https://opalrb.com/) app with all the pre-requisites ready to go for convenience:
135
+
136
+ [https://github.com/AndyObtiva/sample-glimmer-dsl-opal-rails5-app](https://github.com/AndyObtiva/sample-glimmer-dsl-opal-rails5-app)
137
+
138
+ ### Hello Samples
139
+
140
+ #### Hello, World!
141
+
142
+ Add the following require statement to `app/assets/javascripts/application.rb`
143
+
144
+ ```ruby
145
+ require 'glimmer-dsl-opal/samples/hello/hello_world'
146
+ ```
147
+
148
+ Or add the Glimmer code directly if you prefer to play around with it:
81
149
 
82
150
  ```ruby
83
151
  include Glimmer
@@ -87,7 +155,7 @@ shell {
87
155
  label {
88
156
  text 'Hello, World!'
89
157
  }
90
- }
158
+ }.open
91
159
  ```
92
160
 
93
161
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
@@ -107,39 +175,53 @@ You should see "Hello, World!"
107
175
 
108
176
  ![Glimmer DSL for Opal Hello World](images/glimmer-dsl-opal-hello-world.png)
109
177
 
110
- ### Hello, Combo!
178
+ #### Hello, Combo!
111
179
 
112
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
180
+ Add the following require statement to `app/assets/javascripts/application.rb`
181
+
182
+ ```ruby
183
+ require 'glimmer-dsl-opal/samples/hello/hello_combo'
184
+ ```
185
+
186
+ Or add the Glimmer code directly if you prefer to play around with it:
113
187
 
114
188
  ```ruby
115
189
  class Person
116
190
  attr_accessor :country, :country_options
117
-
191
+
118
192
  def initialize
119
- self.country_options=["", "Canada", "US", "Mexico"]
120
- self.country = "Canada"
193
+ self.country_options = ['', 'Canada', 'US', 'Mexico']
194
+ reset_country
121
195
  end
122
196
 
123
197
  def reset_country
124
- self.country = "Canada"
198
+ self.country = 'Canada'
125
199
  end
126
200
  end
127
201
 
128
202
  class HelloCombo
129
203
  include Glimmer
204
+
130
205
  def launch
131
206
  person = Person.new
207
+
132
208
  shell {
133
- composite {
134
- combo(:read_only) {
135
- selection bind(person, :country)
136
- }
137
- button {
138
- text "Reset"
139
- on_widget_selected do
140
- person.reset_country
141
- end
142
- }
209
+ row_layout(:vertical) {
210
+ pack false
211
+ }
212
+
213
+ text 'Hello, Combo!'
214
+
215
+ combo(:read_only) {
216
+ selection bind(person, :country)
217
+ }
218
+
219
+ button {
220
+ text 'Reset Selection'
221
+
222
+ on_widget_selected do
223
+ person.reset_country
224
+ end
143
225
  }
144
226
  }.open
145
227
  end
@@ -164,9 +246,16 @@ You should see "Hello, Combo!"
164
246
 
165
247
  ![Glimmer DSL for Opal Hello Combo](images/glimmer-dsl-opal-hello-combo.png)
166
248
 
167
- ### Hello, Computed!
249
+ #### Hello, Computed!
250
+
251
+ Add the following require statement to `app/assets/javascripts/application.rb`
168
252
 
169
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
253
+
254
+ ```ruby
255
+ require 'glimmer-dsl-opal/samples/hello/hello_computed'
256
+ ```
257
+
258
+ Or add the Glimmer code directly if you prefer to play around with it:
170
259
 
171
260
  ```ruby
172
261
  class HelloComputed
@@ -196,15 +285,15 @@ class HelloComputed
196
285
 
197
286
  def initialize
198
287
  @contact = Contact.new(
199
- first_name: "Barry",
200
- last_name: "McKibbin",
288
+ first_name: 'Barry',
289
+ last_name: 'McKibbin',
201
290
  year_of_birth: 1985
202
291
  )
203
292
  end
204
293
 
205
294
  def launch
206
295
  shell {
207
- text "Hello Computed"
296
+ text 'Hello, Computed!'
208
297
  composite {
209
298
  grid_layout {
210
299
  num_columns 2
@@ -212,44 +301,44 @@ class HelloComputed
212
301
  horizontal_spacing 20
213
302
  vertical_spacing 10
214
303
  }
215
- label {text "First &Name: "}
304
+ label {text 'First &Name: '}
216
305
  text {
217
306
  text bind(@contact, :first_name)
218
307
  layout_data {
219
- horizontalAlignment :fill
220
- grabExcessHorizontalSpace true
308
+ horizontal_alignment :fill
309
+ grab_excess_horizontal_space true
221
310
  }
222
311
  }
223
- label {text "&Last Name: "}
312
+ label {text '&Last Name: '}
224
313
  text {
225
314
  text bind(@contact, :last_name)
226
315
  layout_data {
227
- horizontalAlignment :fill
228
- grabExcessHorizontalSpace true
316
+ horizontal_alignment :fill
317
+ grab_excess_horizontal_space true
229
318
  }
230
319
  }
231
- label {text "&Year of Birth: "}
320
+ label {text '&Year of Birth: '}
232
321
  text {
233
322
  text bind(@contact, :year_of_birth)
234
323
  layout_data {
235
- horizontalAlignment :fill
236
- grabExcessHorizontalSpace true
324
+ horizontal_alignment :fill
325
+ grab_excess_horizontal_space true
237
326
  }
238
327
  }
239
- label {text "Name: "}
328
+ label {text 'Name: '}
240
329
  label {
241
330
  text bind(@contact, :name, computed_by: [:first_name, :last_name])
242
331
  layout_data {
243
- horizontalAlignment :fill
244
- grabExcessHorizontalSpace true
332
+ horizontal_alignment :fill
333
+ grab_excess_horizontal_space true
245
334
  }
246
335
  }
247
- label {text "Age: "}
336
+ label {text 'Age: '}
248
337
  label {
249
338
  text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
250
339
  layout_data {
251
- horizontalAlignment :fill
252
- grabExcessHorizontalSpace true
340
+ horizontal_alignment :fill
341
+ grab_excess_horizontal_space true
253
342
  }
254
343
  }
255
344
  }
@@ -276,9 +365,16 @@ You should see "Hello, Computed!"
276
365
 
277
366
  ![Glimmer DSL for Opal Hello Computed](images/glimmer-dsl-opal-hello-computed.png)
278
367
 
279
- ### Hello, List Single Selection!
368
+ #### Hello, List Single Selection!
369
+
370
+ Add the following require statement to `app/assets/javascripts/application.rb`
371
+
372
+
373
+ ```ruby
374
+ require 'glimmer-dsl-opal/samples/hello/hello_list_single_selection'
375
+ ```
280
376
 
281
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
377
+ Or add the Glimmer code directly if you prefer to play around with it:
282
378
 
283
379
  ```ruby
284
380
  class Person
@@ -318,7 +414,7 @@ HelloListSingleSelection.new.launch
318
414
  ```
319
415
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
320
416
 
321
- ![Glimmer DSL for SWT Hello List Single Selection](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-list-single-selection.png)
417
+ ![Glimmer DSL for SWT Hello List Single Selection](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-list-single-selection.png)
322
418
 
323
419
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
324
420
 
@@ -333,9 +429,15 @@ You should see "Hello, List Single Selection!"
333
429
 
334
430
  ![Glimmer DSL for Opal Hello List Single Selection](images/glimmer-dsl-opal-hello-list-single-selection.png)
335
431
 
336
- ### Hello, List Multi Selection!
432
+ #### Hello, List Multi Selection!
337
433
 
338
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
434
+ Add the following require statement to `app/assets/javascripts/application.rb`
435
+
436
+ ```ruby
437
+ require 'glimmer-dsl-opal/samples/hello/hello_list_multi_selection'
438
+ ```
439
+
440
+ Or add the Glimmer code directly if you prefer to play around with it:
339
441
 
340
442
  ```ruby
341
443
  class Person
@@ -385,7 +487,7 @@ HelloListMultiSelection.new.launch
385
487
  ```
386
488
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
387
489
 
388
- ![Glimmer DSL for SWT Hello List Multi Selection](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-list-multi-selection.png)
490
+ ![Glimmer DSL for SWT Hello List Multi Selection](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-list-multi-selection.png)
389
491
 
390
492
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
391
493
 
@@ -400,9 +502,15 @@ You should see "Hello, List Multi Selection!"
400
502
 
401
503
  ![Glimmer DSL for Opal Hello List Multi Selection](images/glimmer-dsl-opal-hello-list-multi-selection.png)
402
504
 
403
- ### Hello, Browser!
505
+ #### Hello, Browser!
506
+
507
+ Add the following require statement to `app/assets/javascripts/application.rb`
404
508
 
405
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
509
+ ```ruby
510
+ require 'glimmer-dsl-opal/samples/hello/hello_browser'
511
+ ```
512
+
513
+ Or add the Glimmer code directly if you prefer to play around with it:
406
514
 
407
515
  ```ruby
408
516
  include Glimmer
@@ -416,7 +524,7 @@ shell {
416
524
  ```
417
525
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
418
526
 
419
- ![Glimmer DSL for SWT Hello Browser](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-browser.png)
527
+ ![Glimmer DSL for SWT Hello Browser](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-browser.png)
420
528
 
421
529
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
422
530
 
@@ -431,9 +539,15 @@ You should see "Hello, Browser!"
431
539
 
432
540
  ![Glimmer DSL for Opal Hello Browser](images/glimmer-dsl-opal-hello-browser.png)
433
541
 
434
- ### Hello, Tab!
542
+ #### Hello, Tab!
543
+
544
+ Add the following require statement to `app/assets/javascripts/application.rb`
545
+
546
+ ```ruby
547
+ require 'glimmer-dsl-opal/samples/hello/hello_tab'
548
+ ```
435
549
 
436
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
550
+ Or add the Glimmer code directly if you prefer to play around with it:
437
551
 
438
552
  ```ruby
439
553
  class HelloTab
@@ -463,8 +577,8 @@ HelloTab.new.launch
463
577
  ```
464
578
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
465
579
 
466
- ![Glimmer DSL for SWT Hello Tab English](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-tab-english.png)
467
- ![Glimmer DSL for SWT Hello Tab French](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-tab-french.png)
580
+ ![Glimmer DSL for SWT Hello Tab English](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-tab-english.png)
581
+ ![Glimmer DSL for SWT Hello Tab French](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-tab-french.png)
468
582
 
469
583
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
470
584
 
@@ -480,6 +594,807 @@ You should see "Hello, Tab!"
480
594
  ![Glimmer DSL for Opal Hello Tab English](images/glimmer-dsl-opal-hello-tab-english.png)
481
595
  ![Glimmer DSL for Opal Hello Tab French](images/glimmer-dsl-opal-hello-tab-french.png)
482
596
 
597
+ #### Hello, Custom Widget!
598
+
599
+ Add the following require statement to `app/assets/javascripts/application.rb`
600
+
601
+ ```ruby
602
+ require 'glimmer-dsl-opal/samples/hello/hello_custom_widget'
603
+ ```
604
+
605
+ Or add the Glimmer code directly if you prefer to play around with it:
606
+
607
+ ```ruby
608
+ # This class declares a `greeting_label` custom widget (by convention)
609
+ class GreetingLabel
610
+ include Glimmer::UI::CustomWidget
611
+
612
+ # multiple options without default values
613
+ options :name, :colors
614
+
615
+ # single option with default value
616
+ option :greeting, default: 'Hello'
617
+
618
+ # internal attribute (not a custom widget option)
619
+ attr_accessor :color
620
+
621
+ before_body {
622
+ @font = {height: 24, style: :bold}
623
+ @color = :black
624
+ }
625
+
626
+ after_body {
627
+ return if colors.nil?
628
+
629
+ Thread.new {
630
+ colors.cycle { |color|
631
+ async_exec {
632
+ self.color = color
633
+ }
634
+ sleep(1)
635
+ }
636
+ }
637
+ }
638
+
639
+ body {
640
+ # pass received swt_style through to label to customize (e.g. :center to center text)
641
+ label(swt_style) {
642
+ text "#{greeting}, #{name}!"
643
+ font @font
644
+ foreground bind(self, :color)
645
+ }
646
+ }
647
+
648
+ end
649
+
650
+ # including Glimmer enables the Glimmer DSL syntax, including auto-discovery of the `greeting_label` custom widget
651
+ include Glimmer
652
+
653
+ shell {
654
+ fill_layout :vertical
655
+
656
+ minimum_size 215, 215
657
+ text 'Hello, Custom Widget!'
658
+
659
+ # custom widget options are passed in a hash
660
+ greeting_label(name: 'Sean')
661
+
662
+ # pass :center SWT style followed by custom widget options hash
663
+ greeting_label(:center, name: 'Laura', greeting: 'Aloha') #
664
+
665
+ greeting_label(:right, name: 'Rick') {
666
+ # you can nest attributes under custom widgets just like any standard widget
667
+ foreground :red
668
+ }
669
+
670
+ # the colors option cycles between colors for the label foreground every second
671
+ greeting_label(:center, name: 'Mary', greeting: 'Aloha', colors: [:red, :dark_green, :blue])
672
+ }.open
673
+ ```
674
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
675
+
676
+ ![Glimmer DSL for SWT Hello Custom Widget](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-custom-widget.gif)
677
+
678
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
679
+
680
+ Start the Rails server:
681
+ ```
682
+ rails s
683
+ ```
684
+
685
+ Visit `http://localhost:3000`
686
+
687
+ You should see "Hello, Custom Widget!"
688
+
689
+ ![Glimmer DSL for Opal Hello Custom Widget](images/glimmer-dsl-opal-hello-custom-widget.gif)
690
+
691
+ ### Elaborate Samples
692
+
693
+ #### Login
694
+
695
+ Add the following require statement to `app/assets/javascripts/application.rb`
696
+
697
+ ```ruby
698
+ require 'glimmer-dsl-opal/samples/elaborate/login'
699
+ ```
700
+
701
+ Or add the Glimmer code directly if you prefer to play around with it:
702
+
703
+ ```ruby
704
+ require "observer"
705
+
706
+ #Presents login screen data
707
+ class LoginPresenter
708
+
709
+ attr_accessor :user_name
710
+ attr_accessor :password
711
+ attr_accessor :status
712
+
713
+ def initialize
714
+ @user_name = ""
715
+ @password = ""
716
+ @status = "Logged Out"
717
+ end
718
+
719
+ def status=(status)
720
+ @status = status
721
+
722
+ #TODO add feature to bind dependent properties to master property (2017-07-25 nested data binding)
723
+ notify_observers("logged_in")
724
+ notify_observers("logged_out")
725
+ end
726
+
727
+ def logged_in
728
+ self.status == "Logged In"
729
+ end
730
+
731
+ def logged_out
732
+ !self.logged_in
733
+ end
734
+
735
+ def login
736
+ self.status = "Logged In"
737
+ end
738
+
739
+ def logout
740
+ self.user_name = ""
741
+ self.password = ""
742
+ self.status = "Logged Out"
743
+ end
744
+
745
+ end
746
+
747
+ #Login screen
748
+ class Login
749
+ include Glimmer
750
+
751
+ def launch
752
+ presenter = LoginPresenter.new
753
+ @shell = shell {
754
+ text "Login"
755
+ composite {
756
+ grid_layout 2, false #two columns with differing widths
757
+
758
+ label { text "Username:" } # goes in column 1
759
+ text { # goes in column 2
760
+ text bind(presenter, :user_name)
761
+ enabled bind(presenter, :logged_out)
762
+ }
763
+
764
+ label { text "Password:" }
765
+ text(:password, :border) {
766
+ text bind(presenter, :password)
767
+ enabled bind(presenter, :logged_out)
768
+ }
769
+
770
+ label { text "Status:" }
771
+ label { text bind(presenter, :status) }
772
+
773
+ button {
774
+ text "Login"
775
+ enabled bind(presenter, :logged_out)
776
+ on_widget_selected { presenter.login }
777
+ }
778
+
779
+ button {
780
+ text "Logout"
781
+ enabled bind(presenter, :logged_in)
782
+ on_widget_selected { presenter.logout }
783
+ }
784
+ }
785
+ }
786
+ @shell.open
787
+ end
788
+ end
789
+
790
+ Login.new.launch
791
+ ```
792
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
793
+
794
+ ![Glimmer DSL for SWT Login](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-login.png)
795
+ ![Glimmer DSL for SWT Login Filled In](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-login-filled-in.png)
796
+ ![Glimmer DSL for SWT Login Logged In](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-login-logged-in.png)
797
+
798
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
799
+
800
+ Start the Rails server:
801
+ ```
802
+ rails s
803
+ ```
804
+
805
+ Visit `http://localhost:3000`
806
+
807
+ You should see "Login" dialog
808
+
809
+ ![Glimmer DSL for Opal Login](images/glimmer-dsl-opal-login.png)
810
+ ![Glimmer DSL for Opal Login Filled In](images/glimmer-dsl-opal-login-filled-in.png)
811
+ ![Glimmer DSL for Opal Login Logged In](images/glimmer-dsl-opal-login-logged-in.png)
812
+
813
+ #### Tic Tac Toe
814
+
815
+ Add the following require statement to `app/assets/javascripts/application.rb`
816
+
817
+ ```ruby
818
+ require 'glimmer-dsl-opal/samples/elaborate/tic_tac_toe'
819
+ ```
820
+
821
+ Or add the Glimmer code directly if you prefer to play around with it:
822
+
823
+ ```ruby
824
+ class TicTacToe
825
+ class Cell
826
+ EMPTY = ""
827
+ attr_accessor :sign, :empty
828
+
829
+ def initialize
830
+ reset
831
+ end
832
+
833
+ def mark(sign)
834
+ self.sign = sign
835
+ end
836
+
837
+ def reset
838
+ self.sign = EMPTY
839
+ end
840
+
841
+ def sign=(sign_symbol)
842
+ @sign = sign_symbol
843
+ self.empty = sign == EMPTY
844
+ end
845
+
846
+ def marked
847
+ !empty
848
+ end
849
+ end
850
+ end
851
+
852
+ class TicTacToe
853
+ class Board
854
+ DRAW = :draw
855
+ IN_PROGRESS = :in_progress
856
+ WIN = :win
857
+ attr :winning_sign
858
+ attr_accessor :game_status
859
+
860
+ def initialize
861
+ @sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
862
+ build_grid
863
+ @winning_sign = Cell::EMPTY
864
+ @game_status = IN_PROGRESS
865
+ end
866
+
867
+ #row and column numbers are 1-based
868
+ def mark(row, column)
869
+ self[row, column].mark(current_sign)
870
+ game_over? #updates winning sign
871
+ end
872
+
873
+ def current_sign
874
+ @current_sign = @sign_state_machine[@current_sign]
875
+ end
876
+
877
+ def [](row, column)
878
+ @grid[row-1][column-1]
879
+ end
880
+
881
+ def game_over?
882
+ win? or draw?
883
+ end
884
+
885
+ def win?
886
+ win = (row_win? or column_win? or diagonal_win?)
887
+ self.game_status=WIN if win
888
+ win
889
+ end
890
+
891
+ def reset
892
+ (1..3).each do |row|
893
+ (1..3).each do |column|
894
+ self[row, column].reset
895
+ end
896
+ end
897
+ @winning_sign = Cell::EMPTY
898
+ @current_sign = nil
899
+ self.game_status=IN_PROGRESS
900
+ end
901
+
902
+ private
903
+
904
+ def build_grid
905
+ @grid = []
906
+ 3.times do |row_index| #0-based
907
+ @grid << []
908
+ 3.times { @grid[row_index] << Cell.new }
909
+ end
910
+ end
911
+
912
+ def row_win?
913
+ (1..3).each do |row|
914
+ if row_has_same_sign(row)
915
+ @winning_sign = self[row, 1].sign
916
+ return true
917
+ end
918
+ end
919
+ false
920
+ end
921
+
922
+ def column_win?
923
+ (1..3).each do |column|
924
+ if column_has_same_sign(column)
925
+ @winning_sign = self[1, column].sign
926
+ return true
927
+ end
928
+ end
929
+ false
930
+ end
931
+
932
+ #needs refactoring if we ever decide to make the board size dynamic
933
+ def diagonal_win?
934
+ if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
935
+ @winning_sign = self[1, 1].sign
936
+ return true
937
+ end
938
+ if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
939
+ @winning_sign = self[3, 1].sign
940
+ return true
941
+ end
942
+ false
943
+ end
944
+
945
+ def draw?
946
+ @board_full = true
947
+ 3.times do |x|
948
+ 3.times do |y|
949
+ @board_full = false if self[x, y].empty
950
+ end
951
+ end
952
+ self.game_status = DRAW if @board_full
953
+ @board_full
954
+ end
955
+
956
+ def row_has_same_sign(number)
957
+ row_sign = self[number, 1].sign
958
+ [2, 3].each do |column|
959
+ return false unless row_sign == (self[number, column].sign)
960
+ end
961
+ true if self[number, 1].marked
962
+ end
963
+
964
+ def column_has_same_sign(number)
965
+ column_sign = self[1, number].sign
966
+ [2, 3].each do |row|
967
+ return false unless column_sign == (self[row, number].sign)
968
+ end
969
+ true if self[1, number].marked
970
+ end
971
+
972
+ end
973
+ end
974
+
975
+ class TicTacToe
976
+ include Glimmer
977
+
978
+ def initialize
979
+ @tic_tac_toe_board = Board.new
980
+ @shell = shell {
981
+ text "Tic-Tac-Toe"
982
+ composite {
983
+ grid_layout 3, true
984
+ (1..3).each { |row|
985
+ (1..3).each { |column|
986
+ button {
987
+ layout_data :fill, :fill, true, true
988
+ text bind(@tic_tac_toe_board[row, column], :sign)
989
+ enabled bind(@tic_tac_toe_board[row, column], :empty)
990
+ on_widget_selected {
991
+ @tic_tac_toe_board.mark(row, column)
992
+ }
993
+ }
994
+ }
995
+ }
996
+ }
997
+ }
998
+ observe(@tic_tac_toe_board, :game_status) { |game_status|
999
+ display_win_message if game_status == Board::WIN
1000
+ display_draw_message if game_status == Board::DRAW
1001
+ }
1002
+ end
1003
+
1004
+ def display_win_message
1005
+ display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
1006
+ end
1007
+
1008
+ def display_draw_message
1009
+ display_game_over_message("Draw!")
1010
+ end
1011
+
1012
+ def display_game_over_message(message_text)
1013
+ message_box(@shell) {
1014
+ text 'Game Over'
1015
+ message message_text
1016
+ }.open
1017
+ @tic_tac_toe_board.reset
1018
+ end
1019
+
1020
+ def open
1021
+ @shell.open
1022
+ end
1023
+ end
1024
+
1025
+ TicTacToe.new.open
1026
+ ```
1027
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1028
+
1029
+ ![Glimmer DSL for SWT Tic Tac Toe](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-tic-tac-toe.png)
1030
+ ![Glimmer DSL for SWT Tic Tac Toe In Progress](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-tic-tac-toe-in-progress.png)
1031
+ ![Glimmer DSL for SWT Tic Tac Toe Game Over](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-tic-tac-toe-game-over.png)
1032
+
1033
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
1034
+
1035
+ Start the Rails server:
1036
+ ```
1037
+ rails s
1038
+ ```
1039
+
1040
+ Visit `http://localhost:3000`
1041
+
1042
+ You should see "Tic Tac Toe"
1043
+
1044
+ ![Glimmer DSL for Opal Tic Tac Toe](images/glimmer-dsl-opal-tic-tac-toe.png)
1045
+ ![Glimmer DSL for Opal Tic Tac Toe In Progress](images/glimmer-dsl-opal-tic-tac-toe-in-progress.png)
1046
+ ![Glimmer DSL for Opal Tic Tac Toe Game Over](images/glimmer-dsl-opal-tic-tac-toe-game-over.png)
1047
+
1048
+ #### Contact Manager
1049
+
1050
+ Add the following require statement to `app/assets/javascripts/application.rb`
1051
+
1052
+ ```ruby
1053
+ require 'glimmer-dsl-opal/samples/elaborate/contact_manager'
1054
+ ```
1055
+
1056
+ Or add the Glimmer code directly if you prefer to play around with it:
1057
+
1058
+ ```ruby
1059
+ class ContactManager
1060
+ class Contact
1061
+ attr_accessor :first_name, :last_name, :email
1062
+
1063
+ def initialize(attribute_map)
1064
+ @first_name = attribute_map[:first_name]
1065
+ @last_name = attribute_map[:last_name]
1066
+ @email = attribute_map[:email]
1067
+ end
1068
+ end
1069
+ end
1070
+
1071
+ class ContactManager
1072
+ class ContactRepository
1073
+ NAMES_FIRST = %w[
1074
+ Liam
1075
+ Noah
1076
+ William
1077
+ James
1078
+ Oliver
1079
+ Benjamin
1080
+ Elijah
1081
+ Lucas
1082
+ Mason
1083
+ Logan
1084
+ Alexander
1085
+ Ethan
1086
+ Jacob
1087
+ Michael
1088
+ Daniel
1089
+ Henry
1090
+ Jackson
1091
+ Sebastian
1092
+ Aiden
1093
+ Matthew
1094
+ Samuel
1095
+ David
1096
+ Joseph
1097
+ Carter
1098
+ Owen
1099
+ Wyatt
1100
+ John
1101
+ Jack
1102
+ Luke
1103
+ Jayden
1104
+ Dylan
1105
+ Grayson
1106
+ Levi
1107
+ Isaac
1108
+ Gabriel
1109
+ Julian
1110
+ Mateo
1111
+ Anthony
1112
+ Jaxon
1113
+ Lincoln
1114
+ Joshua
1115
+ Christopher
1116
+ Andrew
1117
+ Theodore
1118
+ Caleb
1119
+ Ryan
1120
+ Asher
1121
+ Nathan
1122
+ Thomas
1123
+ Leo
1124
+ Isaiah
1125
+ Charles
1126
+ Josiah
1127
+ Hudson
1128
+ Christian
1129
+ Hunter
1130
+ Connor
1131
+ Eli
1132
+ Ezra
1133
+ Aaron
1134
+ Landon
1135
+ Adrian
1136
+ Jonathan
1137
+ Nolan
1138
+ Jeremiah
1139
+ Easton
1140
+ Elias
1141
+ Colton
1142
+ Cameron
1143
+ Carson
1144
+ Robert
1145
+ Angel
1146
+ Maverick
1147
+ Nicholas
1148
+ Dominic
1149
+ Jaxson
1150
+ Greyson
1151
+ Adam
1152
+ Ian
1153
+ Austin
1154
+ Santiago
1155
+ Jordan
1156
+ Cooper
1157
+ Brayden
1158
+ Roman
1159
+ Evan
1160
+ Ezekiel
1161
+ Xaviar
1162
+ Jose
1163
+ Jace
1164
+ Jameson
1165
+ Leonardo
1166
+ Axel
1167
+ Everett
1168
+ Kayden
1169
+ Miles
1170
+ Sawyer
1171
+ Jason
1172
+ Emma
1173
+ Olivia
1174
+ ]
1175
+ NAMES_LAST = %w[
1176
+ Smith
1177
+ Johnson
1178
+ Williams
1179
+ Brown
1180
+ Jones
1181
+ Miller
1182
+ Davis
1183
+ Wilson
1184
+ Anderson
1185
+ Taylor
1186
+ ]
1187
+ def initialize(contacts = nil)
1188
+ @contacts = contacts || 100.times.map do |n|
1189
+ random_first_name_index = (rand*NAMES_FIRST.size).to_i
1190
+ random_last_name_index = (rand*NAMES_LAST.size).to_i
1191
+ first_name = NAMES_FIRST[random_first_name_index]
1192
+ last_name = NAMES_LAST[random_last_name_index]
1193
+ email = "#{first_name}@#{last_name}.com".downcase
1194
+ Contact.new(
1195
+ first_name: first_name,
1196
+ last_name: last_name,
1197
+ email: email
1198
+ )
1199
+ end
1200
+ end
1201
+
1202
+ def find(attribute_filter_map)
1203
+ @contacts.find_all do |contact|
1204
+ match = true
1205
+ attribute_filter_map.keys.each do |attribute_name|
1206
+ contact_value = contact.send(attribute_name).downcase
1207
+ filter_value = attribute_filter_map[attribute_name].downcase
1208
+ match = false unless contact_value.match(filter_value)
1209
+ end
1210
+ match
1211
+ end
1212
+ end
1213
+ end
1214
+ end
1215
+
1216
+ class ContactManager
1217
+ class ContactManagerPresenter
1218
+ attr_accessor :results
1219
+ @@contact_attributes = [:first_name, :last_name, :email]
1220
+ @@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
1221
+
1222
+ def initialize(contact_repository = nil)
1223
+ @contact_repository = contact_repository || ContactRepository.new
1224
+ @results = []
1225
+ end
1226
+
1227
+ def list
1228
+ self.results = @contact_repository.find({})
1229
+ end
1230
+
1231
+ def find
1232
+ filter_map = {}
1233
+ @@contact_attributes.each do |attribute_name|
1234
+ filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
1235
+ end
1236
+ self.results = @contact_repository.find(filter_map)
1237
+ @sort_attribute_name = nil
1238
+ @sort_direction_ascending = nil
1239
+ end
1240
+
1241
+ def toggle_sort(attribute_name)
1242
+ @sort_attribute_name = attribute_name
1243
+ @sort_direction_ascending = !@sort_direction_ascending
1244
+ sorted_results = self.results.sort_by {|contact| contact.send(attribute_name).downcase}
1245
+ sorted_results = sorted_results.reverse unless @sort_direction_ascending
1246
+ self.results = sorted_results
1247
+ end
1248
+ end
1249
+ end
1250
+
1251
+ class ContactManager
1252
+ include Glimmer
1253
+
1254
+ def initialize
1255
+ @contact_manager_presenter = ContactManagerPresenter.new
1256
+ @contact_manager_presenter.list
1257
+ end
1258
+
1259
+ def launch
1260
+ shell {
1261
+ text "Contact Manager"
1262
+ composite {
1263
+ composite {
1264
+ grid_layout 2, false
1265
+ label {text "First &Name: "}
1266
+ text {
1267
+ text bind(@contact_manager_presenter, :first_name)
1268
+ on_key_pressed {|key_event|
1269
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
1270
+ }
1271
+ }
1272
+ label {text "&Last Name: "}
1273
+ text {
1274
+ text bind(@contact_manager_presenter, :last_name)
1275
+ on_key_pressed {|key_event|
1276
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
1277
+ }
1278
+ }
1279
+ label {text "&Email: "}
1280
+ text {
1281
+ text bind(@contact_manager_presenter, :email)
1282
+ on_key_pressed {|key_event|
1283
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
1284
+ }
1285
+ }
1286
+ composite {
1287
+ grid_layout 2, false
1288
+ button {
1289
+ text "&Find"
1290
+ on_widget_selected {
1291
+ @contact_manager_presenter.find
1292
+ }
1293
+ }
1294
+ button {
1295
+ text "&List All"
1296
+ on_widget_selected {
1297
+ @contact_manager_presenter.list
1298
+ }
1299
+ }
1300
+ }
1301
+ }
1302
+
1303
+ table(:multi) { |table_proxy|
1304
+ layout_data {
1305
+ horizontal_alignment :fill
1306
+ vertical_alignment :fill
1307
+ grab_excess_horizontal_space true
1308
+ grab_excess_vertical_space true
1309
+ height_hint 200
1310
+ }
1311
+ table_column {
1312
+ text "First Name"
1313
+ width 80
1314
+ on_widget_selected {
1315
+ @contact_manager_presenter.toggle_sort(:first_name)
1316
+ }
1317
+ }
1318
+ table_column {
1319
+ text "Last Name"
1320
+ width 80
1321
+ on_widget_selected {
1322
+ @contact_manager_presenter.toggle_sort(:last_name)
1323
+ }
1324
+ }
1325
+ table_column {
1326
+ text "Email"
1327
+ width 200
1328
+ on_widget_selected {
1329
+ @contact_manager_presenter.toggle_sort(:email)
1330
+ }
1331
+ }
1332
+ items bind(@contact_manager_presenter, :results), column_properties(:first_name, :last_name, :email)
1333
+ on_mouse_down { |event|
1334
+ table_proxy.edit_table_item(event.table_item, event.column_index)
1335
+ }
1336
+ }
1337
+ }
1338
+ }.open
1339
+ end
1340
+ end
1341
+
1342
+ ContactManager.new.launch
1343
+
1344
+ ```
1345
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1346
+
1347
+ Glimmer DSL for SWT Contact Manager
1348
+
1349
+ ![Glimmer DSL for SWT Contact Manager](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-contact-manager.png)
1350
+
1351
+ Glimmer DSL for SWT Contact Manager Find
1352
+
1353
+ ![Glimmer DSL for SWT Contact Manager Find](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-contact-manager-find.png)
1354
+
1355
+ Glimmer DSL for SWT Contact Manager Edit Started
1356
+
1357
+ ![Glimmer DSL for SWT Contact Manager Edit Started](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-contact-manager-edit-started.png)
1358
+
1359
+ Glimmer DSL for SWT Contact Manager Edit In Progress
1360
+
1361
+ ![Glimmer DSL for SWT Contact Manager Edit In Progress](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-contact-manager-edit-in-progress.png)
1362
+
1363
+ Glimmer DSL for SWT Contact Manager Edit Done
1364
+
1365
+ ![Glimmer DSL for SWT Contact Manager Edit Done](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-contact-manager-edit-done.png)
1366
+
1367
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
1368
+
1369
+ Start the Rails server:
1370
+ ```
1371
+ rails s
1372
+ ```
1373
+
1374
+ Visit `http://localhost:3000`
1375
+
1376
+ You should see "Tic Tac Toe"
1377
+
1378
+ Glimmer DSL for Opal Contact Manager
1379
+
1380
+ ![Glimmer DSL for Opal Contact Manager](images/glimmer-dsl-opal-contact-manager.png)
1381
+
1382
+ Glimmer DSL for Opal Contact Manager Find
1383
+
1384
+ ![Glimmer DSL for Opal Contact Manager Find](images/glimmer-dsl-opal-contact-manager-find.png)
1385
+
1386
+ Glimmer DSL for Opal Contact Manager Edit Started
1387
+
1388
+ ![Glimmer DSL for Opal Contact Manager Edit Started](images/glimmer-dsl-opal-contact-manager-edit-started.png)
1389
+
1390
+ Glimmer DSL for Opal Contact Manager Edit In Progress
1391
+
1392
+ ![Glimmer DSL for Opal Contact Manager Edit In Progress](images/glimmer-dsl-opal-contact-manager-edit-in-progress.png)
1393
+
1394
+ Glimmer DSL for Opal Contact Manager Edit Done
1395
+
1396
+ ![Glimmer DSL for Opal Contact Manager Edit Done](images/glimmer-dsl-opal-contact-manager-edit-done.png)
1397
+
483
1398
  ## Help
484
1399
 
485
1400
  ### Issues
@@ -514,5 +1429,11 @@ These features have been suggested. You might see them in a future version of Gl
514
1429
 
515
1430
  ## License
516
1431
 
517
- Copyright (c) 2020 Andy Maleh.
518
- See LICENSE.txt for further details.
1432
+ [MIT](https://opensource.org/licenses/MIT)
1433
+
1434
+ Copyright (c) 2020 - Andy Maleh.
1435
+ See [LICENSE.txt](LICENSE.txt) for further details.
1436
+
1437
+ --
1438
+
1439
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=40 />](https://github.com/AndyObtiva/glimmer) Built for [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library).