glimmer-dsl-opal 0.10.2 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +252 -0
  3. data/README.md +187 -1301
  4. data/VERSION +1 -1
  5. data/lib/display.rb +3 -0
  6. data/lib/glimmer-dsl-opal.rb +2 -1
  7. data/lib/glimmer-dsl-opal/ext/glimmer/dsl/engine.rb +1 -1
  8. data/lib/glimmer-dsl-opal/samples/elaborate/contact_manager.rb +15 -13
  9. data/lib/glimmer-dsl-opal/samples/elaborate/login.rb +55 -28
  10. data/lib/glimmer-dsl-opal/samples/elaborate/tic_tac_toe.rb +2 -2
  11. data/lib/glimmer-dsl-opal/samples/elaborate/weather.rb +157 -0
  12. data/lib/glimmer-dsl-opal/samples/hello/hello_button.rb +8 -8
  13. data/lib/glimmer-dsl-opal/samples/hello/hello_checkbox.rb +16 -14
  14. data/lib/glimmer-dsl-opal/samples/hello/hello_checkbox_group.rb +14 -9
  15. data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +24 -22
  16. data/lib/glimmer-dsl-opal/samples/hello/hello_computed.rb +32 -14
  17. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_shell.rb +16 -12
  18. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_widget.rb +1 -1
  19. data/lib/glimmer-dsl-opal/samples/hello/hello_date_time.rb +4 -4
  20. data/lib/glimmer-dsl-opal/samples/hello/hello_group.rb +6 -6
  21. data/lib/glimmer-dsl-opal/samples/hello/hello_list_multi_selection.rb +1 -1
  22. data/lib/glimmer-dsl-opal/samples/hello/hello_list_single_selection.rb +1 -1
  23. data/lib/glimmer-dsl-opal/samples/hello/hello_radio.rb +18 -16
  24. data/lib/glimmer-dsl-opal/samples/hello/hello_radio_group.rb +17 -12
  25. data/lib/glimmer-dsl-opal/samples/hello/hello_table.rb +4 -4
  26. data/lib/glimmer/data_binding/table_items_binding.rb +3 -2
  27. data/lib/glimmer/dsl/opal/bind_expression.rb +24 -25
  28. data/lib/glimmer/dsl/opal/custom_widget_expression.rb +8 -8
  29. data/lib/glimmer/dsl/opal/dsl.rb +4 -0
  30. data/lib/glimmer/dsl/opal/menu_expression.rb +1 -1
  31. data/lib/glimmer/dsl/opal/property_expression.rb +2 -1
  32. data/lib/glimmer/dsl/opal/shape_expression.rb +26 -0
  33. data/lib/glimmer/dsl/opal/shell_expression.rb +1 -1
  34. data/lib/{glimmer-dsl-opal/samples/hello/hello_computed/contact.rb → glimmer/dsl/opal/shine_data_binding_expression.rb} +24 -17
  35. data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +2 -2
  36. data/lib/glimmer/dsl/opal/widget_expression.rb +1 -1
  37. data/lib/glimmer/swt/combo_proxy.rb +1 -0
  38. data/lib/glimmer/swt/composite_proxy.rb +2 -0
  39. data/lib/glimmer/swt/dialog_proxy.rb +1 -1
  40. data/lib/glimmer/swt/display_proxy.rb +63 -1
  41. data/lib/glimmer/swt/grid_layout_proxy.rb +17 -17
  42. data/lib/glimmer/swt/layout_proxy.rb +23 -3
  43. data/lib/glimmer/swt/message_box_proxy.rb +1 -1
  44. data/lib/glimmer/swt/row_layout_proxy.rb +12 -3
  45. data/lib/glimmer/swt/table_proxy.rb +19 -3
  46. data/lib/glimmer/swt/widget_proxy.rb +3 -4
  47. data/lib/glimmer/ui/custom_shell.rb +22 -5
  48. data/lib/glimmer/ui/custom_widget.rb +11 -2
  49. data/lib/net/http.rb +14 -6
  50. metadata +14 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e5d23c66c0aec896d96111427221f61325f4239f1f45f4b5115e3a99c922c2c
4
- data.tar.gz: cc9205606ad7d07b24bc8755190de7a763ae5aff5380d59a6280ff291e0d0d6f
3
+ metadata.gz: '009ae1a27f92b9fe4ae8d28374761c84a8a46add536c37b49c67aba167a121b7'
4
+ data.tar.gz: baf143fe8365b8a3164eaf74adc4a3df720521557003d0507f09580f0da9b6b3
5
5
  SHA512:
6
- metadata.gz: 7c21c30a8f1c2b2601fa974bb241d1228de285429ea25df542adbb58d94100d27f953925610e21cff6629ffdd821a4084ca3fc6f1528592d0568df51d944abe7
7
- data.tar.gz: '091ec964115f9672ef746ff7c3a5689df3a5b578acce8d32754c02c8fe193368e41e8113651452b678eb5d0d7d2d688872e79b0a35477219df61ebcf18fc3fd2'
6
+ metadata.gz: 81014168a1822232725770564b6f8a4522f08a4e93db72c4986966deaeac28eaffe7674f9446d7abf2d5a3a6056eec38a7f12508c72f751734bd8dc6356fdc2c
7
+ data.tar.gz: 800d13580d55f8c1255a68b7c07f6c4e7bdfb9308d3a41b14e44e94b50dd66056c9e437df38f73f2d04643633937cd0a99edba8a1ed174194cf8ce0be25328bf
data/CHANGELOG.md ADDED
@@ -0,0 +1,252 @@
1
+ # Change Log
2
+
3
+ ## 0.14.0
4
+
5
+ - Initial Net::HTTP support for get and post_form
6
+ - Added "Weather" elaborate sample (minus multi-threaded refetches)
7
+ - Updated Hello, Button!, Hello, Combo!, and Hello, Computed! from Glimmer DSL for SWT
8
+
9
+ ## 0.13.0
10
+
11
+ - Support Shine data-binding syntax in custom widgets
12
+ - Update Hello, Checkbox!, Hello, Checkbox Group!, Hello, Radio! and Hello, Radio Group! to utilize Shine data-binding syntax from latest glimmer-dsl-swt
13
+
14
+ ## 0.12.0
15
+
16
+ - Support CustomShell.launch opening in the same window if no other shell is open or DisplayProxy.open_custom_shells_in_current_window = true is set
17
+ - Support CustomShell.launch opening a new window if a shell is already open
18
+ - Support passing `table` data-binding column properties as `column_properties` or `column_attributes` an extra hash option to `bind` method call
19
+ - Support Shine data-binding syntax in `table`
20
+ - Update Hello, Custom Shell!, Hello, Table!, Contact Manager, and Login samples to use Shine data-binding syntax
21
+
22
+ ## 0.11.0
23
+
24
+ - Upgrade to glimmer 2.0.0
25
+ - Support Shine syntax for basic widgets (no support for table, tree, shapes, custom widgets, or custom shells)
26
+ - Update samples to use Shine syntax
27
+
28
+ ## 0.10.3
29
+
30
+ - Upgrade to glimmer 1.0.10
31
+ - Improvements to row_layout and grid_layout
32
+ - Adding launch/shutdown class methods to Custom Shells
33
+
34
+ ## 0.10.2
35
+
36
+ - Support multiple dialogs/message_box'es opened from a listener, handling correct ordering of display with a queue scheduler
37
+
38
+ ## 0.10.1
39
+
40
+ - Delaying shell rendering till `#open` method is called as per the right expectation
41
+ - When nesting dialogs on top of each other, disable all previously opened ones leaving only the top-most dialog active
42
+
43
+ ## 0.10.0
44
+
45
+ - Hello, Dialog! Sample
46
+ - Support `dialog` widget
47
+ - Support `width` and `height` on `layout_data` for `row_layout`
48
+ - Support `center` for `row_layout`
49
+
50
+ ## 0.9.3
51
+
52
+ - Extracted pure Ruby Struct to pure-struct gem (since it's also used by YASL)
53
+ - Alpha experimental incomplete implementation of Net::HTTP.post_form
54
+ - Fixed issue with not being able to interact with a shell proxy (LatestShellProxy) after opening (made class autoupgradable to attached ShellProxy after document ready)
55
+
56
+ ## 0.9.2
57
+
58
+ - Fixed issue with opening message_box after internalizing the Document.ready? block
59
+ - Fixed issue with replacing newlines with HTML newlines in `label` and `message_box` text
60
+
61
+ ## 0.9.1
62
+
63
+ - Log errors to error stream ($stderr) instead of standard out (STDOUT)
64
+ - Fixed issue with opening shell caused by internalizing the Document.ready? block
65
+
66
+ ## 0.9.0
67
+
68
+ - Support `menu_bar`
69
+ - Hello, Menu Bar! Sample
70
+ - Remove the need to call Document.ready? before opening a Glimmer shell
71
+ - Support opening a message_box before creating a shell
72
+
73
+ ## 0.8.0
74
+
75
+ - Hello, Pop Up Context Menu! Sample
76
+ - Hello Message Box!
77
+ - Update hello list samples
78
+ - Support context menus `menu`/`menu_item` directly under a widget (using jQuery UI)
79
+ - Support generating new lines when entering `label` `text` with \n (auto-converting to <br />)
80
+ - Support generating new lines when entering `message_box` `message` with \n (auto-converting to <br />)
81
+ - Support having any widget contribute static CSS to ShellProxy
82
+ - Add Kernel#include_package shim to allow running JRuby include_package from Glimmer DSL for SWT without failing
83
+ - Add WidgetProxy#swt_widget to allow running include_package from Glimmer DSL for SWT without failing
84
+
85
+ ## 0.7.5
86
+
87
+ - Update login sample from Glimmer DSL for SWT's latest changes
88
+ - Update contact_manager sample from Glimmer DSL for SWT's latest changes
89
+ - Fixed issue regarding unavailable localStorage data when accessed by custom_widget_expression in hello_checkbox_group, hello_radio_group, and hello_custom_widget
90
+
91
+ ## 0.7.4
92
+
93
+ - Hello, Button! Sample
94
+ - Fix issue with aligning label as :left, :center, or :right via style style when fill_layout is used
95
+ - Fix Hello, Browser sample by accessing https ssl website
96
+ - Fix issue with filling space horizontally when using grid layout
97
+ - Fix broken embedded `calendar` widget data-binding for hello_date_time.rb sample
98
+ - Fix broken message_box after opening multiple shells
99
+ - Fix issue with opening custom shells in new tabs/windows when CustomShell subclass is required conditionally
100
+
101
+ ## 0.7.3
102
+
103
+ - Refactor to use to_collection gem
104
+ - Fix issue with breaking `date`/`date_drop_down` data-binding as table editor on focus lost
105
+ - Fix issue with requiring OS, File, and Display class after they've been extracted out
106
+
107
+ ## 0.7.2
108
+
109
+ - `date_drop_down` `table_column` `editor`
110
+ - `date` `table_column` `editor`
111
+ - `time` `table_column` `editor`
112
+ - Implement `on_focus_gained`, `on_focus_lost` universally on all widgets
113
+ - Add support for Struct keyword_init to Opal
114
+ - Fix issue with hello_table button/combo not being centered (yet stretched)
115
+ - Fix issue with table item selection for booking not working after editing has been added
116
+ - Fix escape keyboard event handling for combo table editor
117
+
118
+ ## 0.7.1
119
+
120
+ - Combo table editor (enabled in Hello, Table! sample)
121
+ - Fix issue with table cell selection for editing not working
122
+ - Remove widget from parent upon dispose
123
+ - Remove listeners upon widget dispose
124
+
125
+ ## 0.7.0
126
+
127
+ - Hello, Table! Sample
128
+ - `table` :editable style to enable auto-editing
129
+ - `table` `header_visible` property to hide header when false
130
+ - `table` `item_count` property to set minimum item count (fill empty rows when below in table items)
131
+ - `table` selection data-binding
132
+ - `table` built-in sorting support
133
+ - `table_column` left text alignment and padding of 5px by default
134
+ - `table` sort property and direction in GUI
135
+ - `table_column` sort_property
136
+ - `table_column` sort_by block
137
+ - `table_column` sort block
138
+ - `table` default sort via property, compare block, and property block
139
+ - `table` additional sort properties
140
+ - Prevent `table` unnecessary updates by comparing data to previous data and not updating when it's the same
141
+ - Contact Manager sample support for on_key_pressed in text widgets upon hitting ENTER
142
+ - Fix issue with edit table item error on sorting table
143
+
144
+ ## 0.6.1
145
+
146
+ - Fix issue with rendering date_time without a block
147
+ - Made listener event handling async to improve performance when triggering multiple events
148
+ - Brought Tic Tac Toe sample up-to-date with changes in Glimmer DSL for SWT
149
+ - Fixed silent error encountered in rendering custom widgets
150
+
151
+ ## 0.6.0
152
+
153
+ - Hello, Date Time! Sample
154
+ - Support `date_time`, `date`, `date_drop_down`, `time`, `calendar` keywords
155
+ - Format Date/Time correctly as per SWT implementation by default
156
+ - Make glimmer-dsl-opal gem into a Rails engine to support importing default static assets like CSS styles and images
157
+ - Show drop down icon next to `date_drop_down` and `time`
158
+
159
+ ## 0.5.1
160
+
161
+ - Fixed issue with Hello, Combo!, Hello, List...! samples
162
+
163
+ ## 0.5.0
164
+
165
+ - Add `margin_top`, `margin_right`, `margin_bottom`, and `margin_left` to RowLayoutProxy
166
+ - `radio`
167
+ - Hello, Radio! Sample
168
+ - `radio_group`
169
+ - Hello, Radio Group! Sample
170
+ - `checkbox`
171
+ - Hello, Checkbox! Sample
172
+ - `checkbox_group`
173
+ - Fix issue with `label` `alignment` property
174
+ - Fix issues with default `composite` `grid_layout` not getting its styles removed when setting `row_layout`
175
+ - `button(:radio)` alias for `radio`
176
+ - `check` alias for `checkbox`
177
+ - `button(:check)` alias for `checkbox`
178
+ - Hello, Group! Sample
179
+ - Group widget
180
+
181
+ ## 0.4.0
182
+
183
+ - Support `display` keyword representing an SWT Display
184
+ - Support display `on_swt_keydown` event listener (display-wide widget observer)
185
+ - Support `DisplayProxy#shells` method keeping track of open shell
186
+ - Make a custom shell open in the same window if there is no shell open already
187
+ - Support `sync_exec` keyword as just an alias to `async_exec`
188
+ - Provide a makeshift require for 'glimmer-dsl-swt' that requires 'glimmer-dsl-opal' instead
189
+ - Fake APIs on the web for OS.os?, File.read, Display.setAppName, Display.setAppVersion
190
+ - Provide a minimal URI class that supports URI::encode_www_form_component and URI::decode_www_form_component from Ruby
191
+
192
+ ## 0.3.0
193
+
194
+ - Support opening a custom shell in a browser tab/window by passing in query parameters to URL (e.g. ?custom_shell=keyword+option1=value1 etc...)
195
+ - Make custom shells automatically open in a new tab/window (while standard shells continue to open in the same window by replacing its content)
196
+ - Hello, Custom Shell! Sample
197
+
198
+ ## 0.2.0
199
+
200
+ - Color support
201
+ - Font support
202
+ - Custom Widget Support
203
+ - Hello, Custom Widget! sample
204
+ - Updated Hello, Combo! sample to match the latest changes in Glimmer DSL for SWT
205
+ - `SWT` full re-implementation in Opal as `Glimmer::SWT` with all the `SWT` style constants
206
+
207
+ ## 0.1.0
208
+
209
+ - Code redesign to better match the glimmer-dsl-swt APIs
210
+ - opal-jquery refactoring
211
+ - opal-rspec test coverage
212
+
213
+ ## 0.0.9
214
+
215
+ - Upgraded to glimmer gem v0.9.3
216
+ - Fixed issue with missing Glimmer::Opal::ElementProxy#id=(value) method breaking Contact Manager sample Find feature
217
+
218
+ ## 0.0.8
219
+
220
+ - Contact Manager sample support
221
+
222
+ ## 0.0.7
223
+
224
+ - Tic Tac Toe sample support
225
+ - Login sample support
226
+
227
+ ## 0.0.6
228
+
229
+ - Hello, Tab! sample support
230
+
231
+ ## 0.0.5
232
+
233
+ - Hello, Browser! sample support
234
+
235
+ ## 0.0.4
236
+
237
+ - Hello, List Single Selection! sample support
238
+ - Hello, List Multi Selection! sample support
239
+
240
+ ## 0.0.3
241
+
242
+ - Hello, Computed! sample support
243
+
244
+ ## 0.0.2
245
+
246
+ - Hello, Combo! sample support
247
+
248
+ ## 0.0.1
249
+
250
+ - Initial support for webifying Glimmer SWT apps
251
+ - Support for Shell and Label widgets (text property only).
252
+ - Hello, World! sample support
data/README.md CHANGED
@@ -1,16 +1,16 @@
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.10.2 (Pure Ruby Web GUI)
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.14.0 (Pure Ruby Web GUI)
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
- ### You can finally live in pure Ruby land on the web!
5
+ ### You can finally live in pure Rubyland on the web!
6
6
 
7
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Opal](https://opalrb.com/) is an **alpha** [gem](https://rubygems.org/gems/glimmer-dsl-opal) that enables building web GUI in pure Ruby via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/).
7
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Opal](https://opalrb.com/) is an **alpha** [gem](https://rubygems.org/gems/glimmer-dsl-opal) that enables building web GUI in pure Ruby via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/) **(now comes with the new Shine data-binding syntax)**.
8
8
 
9
9
  Use in one of two ways:
10
10
  - **Direct:** build the GUI of web apps with the same friendly desktop GUI Ruby syntax as [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt), thus requiring a lot less code than web technologies that is in pure Ruby and avoiding opaque web concepts like 'render' and 'reactive'. No HTML/JS/CSS skills are even required. Web designers may be involved with CSS styling only if needed.
11
- - **Adapter:** auto-webify [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)) via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/) without changing a line of code. Just insert them as a single require statement in a Rails app, and BOOM! They're running on the web! Apps may then optionally be custom-styled for the web by web designers with standard CSS if needed.
11
+ - **Adapter:** auto-webify [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)) via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/) without changing a line of GUI code. Just insert them as a single require statement in a Rails app, and BOOM! They're running on the web! Apps may then optionally be custom-styled for the web by web designers with standard CSS if needed.
12
12
 
13
- Glimmer DSL for Opal 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.
13
+ Glimmer DSL for Opal 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 Glimmer desktop [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities for the web (including Shine syntax using `<=>` and `<=` for bidirectional [two-way] and unidirectional [one-way] data-binding respectively).
14
14
 
15
15
  #### Hello, Table! Sample
16
16
 
@@ -103,7 +103,7 @@ shell {
103
103
 
104
104
  ![Glimmer DSL for SWT Hello Table](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-table.png)
105
105
 
106
- **Hello, Table! (same code) running on the web via Opal on Rails (using the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem):**
106
+ **Hello, Table! (same GUI code) running on the web via Opal on Rails (using the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem):**
107
107
 
108
108
  ![Glimmer DSL for Opal Hello Table](images/glimmer-dsl-opal-hello-table.png)
109
109
 
@@ -141,17 +141,17 @@ Hello, Table! Game Booked
141
141
 
142
142
  NOTE: Glimmer DSL for Opal is an alpha project. Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
143
143
 
144
- **Alpha Version** 0.10.2 only supports bare-minimum capabilities for the included [samples](https://github.com/AndyObtiva/glimmer-dsl-opal#samples) (originally written for [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt))
144
+ **Alpha Version** 0.14.0 only supports bare-minimum capabilities for the included [samples](https://github.com/AndyObtiva/glimmer-dsl-opal#samples) (originally written for [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt))
145
145
 
146
146
  Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
147
147
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
148
148
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
149
149
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
150
- - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (Ruby Desktop Development GUI Library)
150
+ - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
151
151
 
152
152
  ## Table of Contents
153
153
 
154
- - [Glimmer DSL for Opal 0.10.2 (Pure Ruby Web GUI)](#-glimmer-dsl-for-opal-0101-pure-ruby-web-gui)
154
+ - [Glimmer DSL for Opal 0.14.0 (Pure Ruby Web GUI)](#-glimmer-dsl-for-opal-0140-pure-ruby-web-gui)
155
155
  - [Principles](#principles)
156
156
  - [Background](#background)
157
157
  - [Pre-requisites](#pre-requisites)
@@ -184,6 +184,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
184
184
  - [Login](#login)
185
185
  - [Tic Tac Toe](#tic-tac-toe)
186
186
  - [Contact Manager](#contact-manager)
187
+ - [Weather](#weather)
187
188
  - [External Samples](#external-samples)
188
189
  - [Glimmer Calculator](#glimmer-calculator)
189
190
  - [Glimmer Supporting Libraries](#glimmer-supporting-libraries)
@@ -199,15 +200,17 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
199
200
 
200
201
  ## Principles
201
202
 
203
+ Please keep in mind this is a live list of innovative ideas, some of which have not been implemented yet. Watch the project on GitHub to stay up to date with its development.
204
+
202
205
  - **Live purely in Rubyland via the Glimmer GUI DSL**, completely oblivious to web browser technologies, thanks to [Opal](https://opalrb.com/).
203
- - **Forget Routers!** Glimmer DSL for Opal supports auto-routing of custom shells (windows), which are opened as separate tabs in a web browser with automatically generated routes and bookmarkable URLs.
204
- - **HTML is strictly made for creating documents not interactive applications**. As such, software engineers can avoid it and focus on creating web applications more productively with Glimmer DSL for Opal in pure Ruby instead (just like they do in desktop development) while content creators and web designers can be the ones responsible for creating HTML documents for web content purposes only as HTML was originally intended. That way, Glimmer web GUI is used and embedded in web pages when providing users with applications while the rest of the web pages are maintained by non-engineers as pure HTML. This achieves a correct separation of responsibilities and better productivity and maintainability.
206
+ - **HTML is for creating documents not interactive applications**. As such, software engineers can avoid it and focus on creating web applications more productively with Glimmer DSL for Opal in pure Ruby instead (just like they do in desktop development) while content creators and web designers can be the ones responsible for creating HTML documents for web content purposes only as HTML was originally intended. That way, Glimmer web GUI is used and embedded in web pages when providing users with applications while the rest of the web pages are maintained by non-engineers as pure HTML. This achieves a correct separation of responsibilities and better productivity and maintainability.
205
207
  - **Approximate styles by developers via the Glimmer GUI DSL. Perfect styles by designers via pure CSS**. Developers can simply build GUI with approximate styling similar to desktop GUI and mockups without worrying about pixel-perfect aesthetics. Web designers can take styling further with pure CSS since every HTML element auto-generated by Glimmer DSL for Opal has a predictable ID and CSS class. This achieves a proper separation of responsibilities between developers and designers.
206
208
  - **Web servers are used just like servers in traditional client/server architecture**, meaning they simply provide RMI services to enable centralizing some of the application logic and data in the cloud to make available everywhere and enable data-sharing with others.
209
+ - **Forget Routers!** Glimmer DSL for Opal supports auto-routing of custom shells (windows), which are opened as separate tabs in a web browser with automatically generated routes and bookmarkable URLs.
207
210
 
208
211
  ## Background
209
212
 
210
- The original idea behind Glimmer DSL for Opal (which later evolved) was that you start by having a [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) desktop app that communicates with a Rails API for any web/cloud concerns. The pure Ruby [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) is very simple, so it is more productive to build GUI in it since it does not go through a server/client request/response cycle and can be iterated on locally with a much shorter feedback cycle. Once the GUI and the rest of the app is built. You simply embed it in a Rails app as a one line require statement, and BOOM, it just works on the web inside a web browser with the same server/client communication you had in the desktop app (I am working on adding minimal support for net/http in Opal so that desktop apps that use it continue to work in a web browser. Until then, just use [Opal-jQuery](https://github.com/opal/opal-jquery) http support). That way, you get two apps for one: desktop and web.
213
+ The original idea behind Glimmer DSL for Opal (which [later evolved](#principles)) was that you start by having a [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) desktop app that communicates with a Rails API for any web/cloud concerns. The pure Ruby [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) is very simple, so it is more productive to build GUI in it since it does not go through a server/client request/response cycle and can be iterated on locally with a much shorter feedback cycle. Once the GUI and the rest of the app is built. You simply embed it in a Rails app as a one line require statement, and BOOM, it just works on the web inside a web browser with the same server/client communication you had in the desktop app (I am working on adding minimal support for net/http in Opal so that desktop apps that use it continue to work in a web browser. Until then, just use [Opal-jQuery](https://github.com/opal/opal-jquery) http support). That way, you get two apps for one: desktop and web.
211
214
 
212
215
  Part of the idea is that web browsers just render GUI widgets similar to those of a desktop app (after all a web browser is a desktop app), so whether you run your GUI on the desktop or on the web should just be a low-level concern, hopefully automated completely with Glimmer DSL for Opal.
213
216
 
@@ -249,9 +252,9 @@ Add the following to `Gemfile`:
249
252
  gem 'opal-rails', '~> 1.1.2'
250
253
  gem 'opal-async', '~> 1.2.0'
251
254
  gem 'opal-jquery', '~> 0.4.4'
252
- gem 'glimmer-dsl-opal', '~> 0.10.2'
253
- gem 'glimmer-dsl-xml', '~> 1.1.0', require: false
254
- gem 'glimmer-dsl-css', '~> 1.1.0', require: false
255
+ gem 'glimmer-dsl-opal', '~> 0.14.0'
256
+ gem 'glimmer-dsl-xml', '~> 1.2.0', require: false
257
+ gem 'glimmer-dsl-css', '~> 1.2.0', require: false
255
258
 
256
259
  ```
257
260
 
@@ -310,7 +313,7 @@ shell {
310
313
 
311
314
  ## Supported Glimmer DSL Keywords
312
315
 
313
- The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) have partial support in Opal:
316
+ The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) have fully functional partial support in Opal:
314
317
 
315
318
  Widgets:
316
319
  - `button`: featured in [Hello, Checkbox!](#hello-checkbox) / [Hello, Button!](#hello-button) / [Hello, Table!](#hello-table) / [Hello, Radio Group!](#hello-radio-group) / [Hello, Radio!](#hello-radio) / [Hello, Message Box!](#hello-message-box) / [Hello, List Single Selection!](#hello-list-single-selection) / [Hello, List Multi Selection!](#hello-list-multi-selection) / [Hello, Group!](#hello-group) / [Hello, Combo!](#hello-combo) / [Hello, Checkbox Group!](#hello-checkbox-group) / [Contact Manager](#contact-manager) / [Tic Tac Toe](#tic-tac-toe) / [Login](#login)
@@ -438,48 +441,50 @@ require 'glimmer-dsl-opal/samples/hello/hello_combo'
438
441
  Or add the Glimmer code directly if you prefer to play around with it:
439
442
 
440
443
  ```ruby
441
- class Person
442
- attr_accessor :country, :country_options
443
-
444
- def initialize
445
- self.country_options = ['', 'Canada', 'US', 'Mexico']
446
- reset_country
447
- end
448
-
449
- def reset_country
450
- self.country = 'Canada'
444
+ class HelloCombo
445
+ class Person
446
+ attr_accessor :country, :country_options
447
+
448
+ def initialize
449
+ self.country_options = ['', 'Canada', 'US', 'Mexico']
450
+ reset_country!
451
+ end
452
+
453
+ def reset_country!
454
+ self.country = 'Canada'
455
+ end
451
456
  end
452
- end
453
457
 
454
- class HelloCombo
455
- include Glimmer
458
+ include Glimmer::UI::CustomShell
456
459
 
457
- def launch
458
- person = Person.new
459
-
460
+ before_body {
461
+ @person = Person.new
462
+ }
463
+
464
+ body {
460
465
  shell {
461
466
  row_layout(:vertical) {
462
- pack false
467
+ fill true
463
468
  }
464
469
 
465
470
  text 'Hello, Combo!'
466
471
 
467
472
  combo(:read_only) {
468
- selection bind(person, :country)
473
+ selection <=> [@person, :country] # also binds to country_options by convention
469
474
  }
470
475
 
471
476
  button {
472
477
  text 'Reset Selection'
473
478
 
474
479
  on_widget_selected do
475
- person.reset_country
480
+ @person.reset_country!
476
481
  end
477
482
  }
478
- }.open
479
- end
483
+ }
484
+ }
480
485
  end
481
486
 
482
- HelloCombo.new.launch
487
+ HelloCombo.launch
483
488
  ```
484
489
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
485
490
 
@@ -530,22 +535,21 @@ class HelloComputed
530
535
  0
531
536
  end
532
537
  end
533
- end
534
538
 
535
- class HelloComputed
536
- include Glimmer
539
+ include Glimmer::UI::CustomShell
537
540
 
538
- def initialize
541
+ before_body {
539
542
  @contact = Contact.new(
540
543
  first_name: 'Barry',
541
544
  last_name: 'McKibbin',
542
545
  year_of_birth: 1985
543
546
  )
544
- end
547
+ }
545
548
 
546
- def launch
549
+ body {
547
550
  shell {
548
551
  text 'Hello, Computed!'
552
+
549
553
  composite {
550
554
  grid_layout {
551
555
  num_columns 2
@@ -553,52 +557,57 @@ class HelloComputed
553
557
  horizontal_spacing 20
554
558
  vertical_spacing 10
555
559
  }
560
+
556
561
  label {text 'First &Name: '}
557
562
  text {
558
- text bind(@contact, :first_name)
563
+ text <=> [@contact, :first_name]
559
564
  layout_data {
560
565
  horizontal_alignment :fill
561
566
  grab_excess_horizontal_space true
562
567
  }
563
568
  }
569
+
564
570
  label {text '&Last Name: '}
565
571
  text {
566
- text bind(@contact, :last_name)
572
+ text <=> [@contact, :last_name]
567
573
  layout_data {
568
574
  horizontal_alignment :fill
569
575
  grab_excess_horizontal_space true
570
576
  }
571
577
  }
578
+
572
579
  label {text '&Year of Birth: '}
573
580
  text {
574
- text bind(@contact, :year_of_birth)
581
+ text <=> [@contact, :year_of_birth]
575
582
  layout_data {
576
583
  horizontal_alignment :fill
577
584
  grab_excess_horizontal_space true
578
585
  }
579
586
  }
587
+
580
588
  label {text 'Name: '}
581
589
  label {
582
- text bind(@contact, :name, computed_by: [:first_name, :last_name])
590
+ text <= [@contact, :name, computed_by: [:first_name, :last_name]]
583
591
  layout_data {
584
592
  horizontal_alignment :fill
585
593
  grab_excess_horizontal_space true
586
594
  }
587
595
  }
596
+
588
597
  label {text 'Age: '}
589
598
  label {
590
- text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
599
+ text <= [@contact, :age, on_write: :to_i, computed_by: [:year_of_birth]]
591
600
  layout_data {
592
601
  horizontal_alignment :fill
593
602
  grab_excess_horizontal_space true
594
603
  }
595
604
  }
596
605
  }
597
- }.open
598
- end
606
+ }
607
+ }
599
608
  end
600
609
 
601
- HelloComputed.new.launch
610
+ HelloComputed.launch
602
611
  ```
603
612
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
604
613
 
@@ -626,44 +635,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
626
635
  require 'glimmer-dsl-opal/samples/hello/hello_list_single_selection'
627
636
  ```
628
637
 
629
- Or add the Glimmer code directly if you prefer to play around with it:
630
-
631
- ```ruby
632
- class Person
633
- attr_accessor :country, :country_options
634
-
635
- def initialize
636
- self.country_options=["", "Canada", "US", "Mexico"]
637
- self.country = "Canada"
638
- end
639
-
640
- def reset_country
641
- self.country = "Canada"
642
- end
643
- end
644
-
645
- class HelloListSingleSelection
646
- include Glimmer
647
- def launch
648
- person = Person.new
649
- shell {
650
- composite {
651
- list {
652
- selection bind(person, :country)
653
- }
654
- button {
655
- text "Reset"
656
- on_widget_selected do
657
- person.reset_country
658
- end
659
- }
660
- }
661
- }.open
662
- end
663
- end
664
-
665
- HelloListSingleSelection.new.launch
666
- ```
667
638
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
668
639
 
669
640
  ![Glimmer DSL for SWT Hello List Single Selection](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-list-single-selection.png)
@@ -689,63 +660,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
689
660
  require 'glimmer-dsl-opal/samples/hello/hello_list_multi_selection'
690
661
  ```
691
662
 
692
- Or add the Glimmer code directly if you prefer to play around with it:
693
-
694
- ```ruby
695
- class HelloListMultiSelection
696
- class Person
697
- attr_accessor :provinces, :provinces_options
698
-
699
- def initialize
700
- self.provinces_options = [
701
- '',
702
- 'Alberta',
703
- 'British Columbia',
704
- 'Manitoba',
705
- 'New Brunswick',
706
- 'Newfoundland and Labrador',
707
- 'Northwest Territories',
708
- 'Nova Scotia',
709
- 'Nunavut',
710
- 'Ontario',
711
- 'Prince Edward Island',
712
- 'Quebec',
713
- 'Saskatchewan',
714
- 'Yukon'
715
- ]
716
- reset_provinces
717
- end
718
-
719
- def reset_provinces
720
- self.provinces = ['Quebec', 'Manitoba', 'Alberta']
721
- end
722
- end
723
-
724
- include Glimmer
725
-
726
- def launch
727
- person = Person.new
728
-
729
- shell {
730
- grid_layout
731
-
732
- text 'Hello, List Multi Selection!'
733
-
734
- list(:multi) {
735
- selection bind(person, :provinces)
736
- }
737
-
738
- button {
739
- text 'Reset Selections To Default Values'
740
-
741
- on_widget_selected { person.reset_provinces }
742
- }
743
- }.open
744
- end
745
- end
746
-
747
- HelloListMultiSelection.new.launch
748
- ```
749
663
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
750
664
 
751
665
  ![Glimmer DSL for SWT Hello List Multi Selection](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-list-multi-selection.png)
@@ -771,18 +685,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
771
685
  require 'glimmer-dsl-opal/samples/hello/hello_browser'
772
686
  ```
773
687
 
774
- Or add the Glimmer code directly if you prefer to play around with it:
775
-
776
- ```ruby
777
- include Glimmer
778
-
779
- shell {
780
- minimum_size 1024, 860
781
- browser {
782
- url 'http://brightonresort.com/about'
783
- }
784
- }.open
785
- ```
786
688
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
787
689
 
788
690
  ![Glimmer DSL for SWT Hello Browser](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-browser.png)
@@ -887,7 +789,7 @@ class GreetingLabel
887
789
  after_body {
888
790
  return if colors.nil?
889
791
 
890
- Thread.new {
792
+ Thread.new { # imported from Glimmer DSL for SWT. In Opal, avoid Threads and sleep to avoid blocking GUI.
891
793
  colors.cycle { |color|
892
794
  async_exec {
893
795
  self.color = color
@@ -902,7 +804,7 @@ class GreetingLabel
902
804
  label(swt_style) {
903
805
  text "#{greeting}, #{name}!"
904
806
  font @font
905
- foreground bind(self, :color)
807
+ foreground <=> [self, :color]
906
808
  }
907
809
  }
908
810
 
@@ -1124,103 +1026,14 @@ You should see "Hello, Custom Widget!"
1124
1026
 
1125
1027
  #### Hello, Radio!
1126
1028
 
1029
+ This is the low level way of using `radio`
1030
+
1127
1031
  Add the following require statement to `app/assets/javascripts/application.rb`
1128
1032
 
1129
1033
  ```ruby
1130
1034
  require 'glimmer-dsl-opal/samples/hello/hello_radio'
1131
1035
  ```
1132
1036
 
1133
- Or add the Glimmer code directly if you prefer to play around with it:
1134
-
1135
- ```ruby
1136
- class HelloRadio
1137
- class Person
1138
- attr_accessor :male, :female, :child, :teen, :adult, :senior
1139
-
1140
- def initialize
1141
- reset
1142
- end
1143
-
1144
- def reset
1145
- self.male = nil
1146
- self.female = nil
1147
- self.child = nil
1148
- self.teen = nil
1149
- self.adult = true
1150
- self.senior = nil
1151
- end
1152
- end
1153
-
1154
- include Glimmer
1155
-
1156
- def launch
1157
- person = Person.new
1158
-
1159
- shell {
1160
- text 'Hello, Radio!'
1161
- row_layout :vertical
1162
-
1163
- label {
1164
- text 'Gender:'
1165
- font style: :bold
1166
- }
1167
-
1168
- composite {
1169
- row_layout
1170
-
1171
- radio {
1172
- text 'Male'
1173
- selection bind(person, :male)
1174
- }
1175
-
1176
- radio {
1177
- text 'Female'
1178
- selection bind(person, :female)
1179
- }
1180
- }
1181
-
1182
- label {
1183
- text 'Age Group:'
1184
- font style: :bold
1185
- }
1186
-
1187
- composite {
1188
- row_layout
1189
-
1190
- radio {
1191
- text 'Child'
1192
- selection bind(person, :child)
1193
- }
1194
-
1195
- radio {
1196
- text 'Teen'
1197
- selection bind(person, :teen)
1198
- }
1199
-
1200
- radio {
1201
- text 'Adult'
1202
- selection bind(person, :adult)
1203
- }
1204
-
1205
- radio {
1206
- text 'Senior'
1207
- selection bind(person, :senior)
1208
- }
1209
- }
1210
-
1211
- button {
1212
- text 'Reset'
1213
-
1214
- on_widget_selected do
1215
- person.reset
1216
- end
1217
- }
1218
- }.open
1219
- end
1220
- end
1221
-
1222
- HelloRadio.new.launch
1223
- ```
1224
1037
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1225
1038
 
1226
1039
  ![Glimmer DSL for SWT Hello Radio](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-radio.png)
@@ -1240,6 +1053,8 @@ You should see "Hello, Radio!"
1240
1053
 
1241
1054
  #### Hello, Radio Group!
1242
1055
 
1056
+ `radio_group` is a level higher than `radio` in abstraction. It generates a group of radio widgets based on available options in model `attribute_options` methods.
1057
+
1243
1058
  Add the following require statement to `app/assets/javascripts/application.rb`
1244
1059
 
1245
1060
  ```ruby
@@ -1254,7 +1069,7 @@ class HelloRadioGroup
1254
1069
  attr_accessor :gender, :age_group
1255
1070
 
1256
1071
  def initialize
1257
- reset
1072
+ reset!
1258
1073
  end
1259
1074
 
1260
1075
  def gender_options
@@ -1265,17 +1080,19 @@ class HelloRadioGroup
1265
1080
  ['Child', 'Teen', 'Adult', 'Senior']
1266
1081
  end
1267
1082
 
1268
- def reset
1083
+ def reset!
1269
1084
  self.gender = nil
1270
1085
  self.age_group = 'Adult'
1271
1086
  end
1272
1087
  end
1273
1088
 
1274
- include Glimmer
1089
+ include Glimmer::UI::CustomShell
1275
1090
 
1276
- def launch
1277
- person = Person.new
1278
-
1091
+ before_body {
1092
+ @person = Person.new
1093
+ }
1094
+
1095
+ body {
1279
1096
  shell {
1280
1097
  text 'Hello, Radio Group!'
1281
1098
  row_layout :vertical
@@ -1287,7 +1104,7 @@ class HelloRadioGroup
1287
1104
 
1288
1105
  radio_group {
1289
1106
  row_layout :horizontal
1290
- selection bind(person, :gender)
1107
+ selection <=> [@person, :gender]
1291
1108
  }
1292
1109
 
1293
1110
  label {
@@ -1297,21 +1114,21 @@ class HelloRadioGroup
1297
1114
 
1298
1115
  radio_group {
1299
1116
  row_layout :horizontal
1300
- selection bind(person, :age_group)
1117
+ selection <=> [@person, :age_group]
1301
1118
  }
1302
1119
 
1303
1120
  button {
1304
1121
  text 'Reset'
1305
1122
 
1306
1123
  on_widget_selected do
1307
- person.reset
1124
+ @person.reset!
1308
1125
  end
1309
1126
  }
1310
- }.open
1311
- end
1127
+ }
1128
+ }
1312
1129
  end
1313
1130
 
1314
- HelloRadioGroup.new.launch
1131
+ HelloRadioGroup.launch
1315
1132
  ```
1316
1133
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1317
1134
 
@@ -1332,99 +1149,14 @@ You should see "Hello, Radio Group!"
1332
1149
 
1333
1150
  #### Hello, Group!
1334
1151
 
1152
+ Not to be confused with `radio_group` or `checkbox_group`, `group` simply groups arbitrary widgets together and adds a title header above them.
1153
+
1335
1154
  Add the following require statement to `app/assets/javascripts/application.rb`
1336
1155
 
1337
1156
  ```ruby
1338
1157
  require 'glimmer-dsl-opal/samples/hello/hello_group'
1339
1158
  ```
1340
1159
 
1341
- Or add the Glimmer code directly if you prefer to play around with it:
1342
-
1343
- ```ruby
1344
- class HelloGroup
1345
- class Person
1346
- attr_accessor :male, :female, :child, :teen, :adult, :senior
1347
-
1348
- def initialize
1349
- reset
1350
- end
1351
-
1352
- def reset
1353
- self.male = nil
1354
- self.female = nil
1355
- self.child = nil
1356
- self.teen = nil
1357
- self.adult = true
1358
- self.senior = nil
1359
- end
1360
- end
1361
-
1362
- include Glimmer
1363
-
1364
- def launch
1365
- person = Person.new
1366
-
1367
- shell {
1368
- text 'Hello, Group!'
1369
- row_layout :vertical
1370
-
1371
- group {
1372
- row_layout
1373
-
1374
- text 'Gender'
1375
- font style: :bold
1376
-
1377
- radio {
1378
- text 'Male'
1379
- selection bind(person, :male)
1380
- }
1381
-
1382
- radio {
1383
- text 'Female'
1384
- selection bind(person, :female)
1385
- }
1386
- }
1387
-
1388
- group {
1389
- row_layout
1390
-
1391
- text 'Age Group'
1392
- font style: :bold
1393
-
1394
- radio {
1395
- text 'Child'
1396
- selection bind(person, :child)
1397
- }
1398
-
1399
- radio {
1400
- text 'Teen'
1401
- selection bind(person, :teen)
1402
- }
1403
-
1404
- radio {
1405
- text 'Adult'
1406
- selection bind(person, :adult)
1407
- }
1408
-
1409
- radio {
1410
- text 'Senior'
1411
- selection bind(person, :senior)
1412
- }
1413
- }
1414
-
1415
- button {
1416
- text 'Reset'
1417
-
1418
- on_widget_selected do
1419
- person.reset
1420
- end
1421
- }
1422
- }.open
1423
- end
1424
- end
1425
-
1426
- HelloGroup.new.launch
1427
- ```
1428
1160
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1429
1161
 
1430
1162
  ![Glimmer DSL for SWT Hello Group](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-group.png)
@@ -1444,100 +1176,36 @@ You should see "Hello, Group!"
1444
1176
 
1445
1177
  #### Hello, Checkbox!
1446
1178
 
1179
+ This is the low level way of using `checkbox`
1180
+
1447
1181
  Add the following require statement to `app/assets/javascripts/application.rb`
1448
1182
 
1449
1183
  ```ruby
1450
1184
  require 'glimmer-dsl-opal/samples/hello/hello_checkbox'
1451
1185
  ```
1452
1186
 
1453
- Or add the Glimmer code directly if you prefer to play around with it:
1454
-
1455
- ```ruby
1456
- class HelloCheckbox
1457
- class Person
1458
- attr_accessor :skiing, :snowboarding, :snowmobiling, :snowshoeing
1459
-
1460
- def initialize
1461
- reset_activities
1462
- end
1463
-
1464
- def reset_activities
1465
- self.skiing = false
1466
- self.snowboarding = true
1467
- self.snowmobiling = false
1468
- self.snowshoeing = false
1469
- end
1470
- end
1471
-
1472
- include Glimmer
1473
-
1474
- def launch
1475
- person = Person.new
1476
-
1477
- shell {
1478
- text 'Hello, Checkbox!'
1479
- row_layout :vertical
1480
-
1481
- label {
1482
- text 'Check all snow activities you are interested in:'
1483
- font style: :bold
1484
- }
1485
-
1486
- composite {
1487
- checkbox {
1488
- text 'Skiing'
1489
- selection bind(person, :skiing)
1490
- }
1491
-
1492
- checkbox {
1493
- text 'Snowboarding'
1494
- selection bind(person, :snowboarding)
1495
- }
1496
-
1497
- checkbox {
1498
- text 'Snowmobiling'
1499
- selection bind(person, :snowmobiling)
1500
- }
1501
-
1502
- checkbox {
1503
- text 'Snowshoeing'
1504
- selection bind(person, :snowshoeing)
1505
- }
1506
- }
1507
-
1508
- button {
1509
- text 'Reset Activities'
1510
-
1511
- on_widget_selected do
1512
- person.reset_activities
1513
- end
1514
- }
1515
- }.open
1516
- end
1517
- end
1518
-
1519
- HelloCheckbox.new.launch
1520
- ```
1521
- Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1522
-
1523
- ![Glimmer DSL for SWT Hello Checkbox](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-checkbox.png)
1524
-
1525
- Glimmer app on the web (using `glimmer-dsl-opal` gem):
1526
-
1527
- Start the Rails server:
1528
- ```
1529
- rails s
1530
- ```
1531
-
1532
- Visit `http://localhost:3000`
1533
-
1534
- You should see "Hello, Checkbox!"
1535
-
1536
- ![Glimmer DSL for Opal Hello Checkbox](images/glimmer-dsl-opal-hello-checkbox.png)
1537
-
1538
- #### Hello, Checkbox Group!
1539
-
1540
- Add the following require statement to `app/assets/javascripts/application.rb`
1187
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1188
+
1189
+ ![Glimmer DSL for SWT Hello Checkbox](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-checkbox.png)
1190
+
1191
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
1192
+
1193
+ Start the Rails server:
1194
+ ```
1195
+ rails s
1196
+ ```
1197
+
1198
+ Visit `http://localhost:3000`
1199
+
1200
+ You should see "Hello, Checkbox!"
1201
+
1202
+ ![Glimmer DSL for Opal Hello Checkbox](images/glimmer-dsl-opal-hello-checkbox.png)
1203
+
1204
+ #### Hello, Checkbox Group!
1205
+
1206
+ `checkbox_group` is a level higher than `checkbox` in abstraction. It generates a group of checkbox widgets based on available options in model `attribute_options` methods.
1207
+
1208
+ Add the following require statement to `app/assets/javascripts/application.rb`
1541
1209
 
1542
1210
  ```ruby
1543
1211
  require 'glimmer-dsl-opal/samples/hello/hello_checkbox_group'
@@ -1563,11 +1231,13 @@ class HelloCheckboxGroup
1563
1231
  end
1564
1232
  end
1565
1233
 
1566
- include Glimmer
1234
+ include Glimmer::UI::CustomShell
1567
1235
 
1568
- def launch
1569
- person = Person.new
1570
-
1236
+ before_body {
1237
+ @person = Person.new
1238
+ }
1239
+
1240
+ body {
1571
1241
  shell {
1572
1242
  text 'Hello, Checkbox Group!'
1573
1243
  row_layout :vertical
@@ -1578,21 +1248,21 @@ class HelloCheckboxGroup
1578
1248
  }
1579
1249
 
1580
1250
  checkbox_group {
1581
- selection bind(person, :activities)
1251
+ selection <=> [@person, :activities]
1582
1252
  }
1583
1253
 
1584
1254
  button {
1585
1255
  text 'Reset Activities'
1586
1256
 
1587
1257
  on_widget_selected do
1588
- person.reset_activities
1258
+ @person.reset_activities
1589
1259
  end
1590
1260
  }
1591
- }.open
1592
- end
1261
+ }
1262
+ }
1593
1263
  end
1594
1264
 
1595
- HelloCheckboxGroup.new.launch
1265
+ HelloCheckboxGroup.launch
1596
1266
  ```
1597
1267
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1598
1268
 
@@ -1619,53 +1289,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
1619
1289
  require 'glimmer-dsl-opal/samples/hello/hello_date_time'
1620
1290
  ```
1621
1291
 
1622
- Or add the Glimmer code directly if you prefer to play around with it:
1623
-
1624
- ```ruby
1625
- class HelloDateTime
1626
- class Person
1627
- attr_accessor :date_of_birth
1628
- end
1629
-
1630
- include Glimmer
1631
-
1632
- def launch
1633
- person = Person.new
1634
- person.date_of_birth = DateTime.new(2013, 7, 12, 18, 37, 23)
1635
-
1636
- shell {
1637
- row_layout :vertical
1638
-
1639
- text 'Hello, Date Time!'
1640
- minimum_size 180, 180
1641
-
1642
- label {
1643
- text 'Date of Birth'
1644
- font height: 16, style: :bold
1645
- }
1646
-
1647
- date { # alias for date_time(:date)
1648
- date_time bind(person, :date_of_birth)
1649
- }
1650
-
1651
- date_drop_down { # alias for date_time(:date, :drop_down)
1652
- date_time bind(person, :date_of_birth)
1653
- }
1654
-
1655
- time { # alias for date_time(:time)
1656
- date_time bind(person, :date_of_birth)
1657
- }
1658
-
1659
- calendar { # alias for date_time(:calendar)
1660
- date_time bind(person, :date_of_birth)
1661
- }
1662
- }.open
1663
- end
1664
- end
1665
-
1666
- HelloDateTime.new.launch
1667
- ```
1668
-
1669
1292
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1670
1293
 
1671
1294
  ![Glimmer DSL for SWT Hello Checkbox Group](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-date-time.png)
@@ -1693,263 +1316,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
1693
1316
  require 'glimmer-dsl-opal/samples/hello/hello_table'
1694
1317
  ```
1695
1318
 
1696
- Or add the Glimmer code directly if you prefer to play around with it:
1697
-
1698
- ```ruby
1699
- class HelloTable
1700
- class BaseballGame
1701
- class << self
1702
- attr_accessor :selected_game
1703
-
1704
- def all_playoff_games
1705
- @all_playoff_games ||= {
1706
- 'NLDS' => [
1707
- new(Time.new(2037, 10, 6, 12, 0), 'Chicago Cubs', 'Milwaukee Brewers', 'Free Bobblehead'),
1708
- new(Time.new(2037, 10, 7, 12, 0), 'Chicago Cubs', 'Milwaukee Brewers'),
1709
- new(Time.new(2037, 10, 8, 12, 0), 'Milwaukee Brewers', 'Chicago Cubs'),
1710
- new(Time.new(2037, 10, 9, 12, 0), 'Milwaukee Brewers', 'Chicago Cubs'),
1711
- new(Time.new(2037, 10, 10, 12, 0), 'Milwaukee Brewers', 'Chicago Cubs', 'Free Umbrella'),
1712
- new(Time.new(2037, 10, 6, 18, 0), 'Cincinnati Reds', 'St Louis Cardinals', 'Free Bobblehead'),
1713
- new(Time.new(2037, 10, 7, 18, 0), 'Cincinnati Reds', 'St Louis Cardinals'),
1714
- new(Time.new(2037, 10, 8, 18, 0), 'St Louis Cardinals', 'Cincinnati Reds'),
1715
- new(Time.new(2037, 10, 9, 18, 0), 'St Louis Cardinals', 'Cincinnati Reds'),
1716
- new(Time.new(2037, 10, 10, 18, 0), 'St Louis Cardinals', 'Cincinnati Reds', 'Free Umbrella'),
1717
- ],
1718
- 'ALDS' => [
1719
- new(Time.new(2037, 10, 6, 12, 0), 'New York Yankees', 'Boston Red Sox', 'Free Bobblehead'),
1720
- new(Time.new(2037, 10, 7, 12, 0), 'New York Yankees', 'Boston Red Sox'),
1721
- new(Time.new(2037, 10, 8, 12, 0), 'Boston Red Sox', 'New York Yankees'),
1722
- new(Time.new(2037, 10, 9, 12, 0), 'Boston Red Sox', 'New York Yankees'),
1723
- new(Time.new(2037, 10, 10, 12, 0), 'Boston Red Sox', 'New York Yankees', 'Free Umbrella'),
1724
- new(Time.new(2037, 10, 6, 18, 0), 'Houston Astros', 'Cleveland Indians', 'Free Bobblehead'),
1725
- new(Time.new(2037, 10, 7, 18, 0), 'Houston Astros', 'Cleveland Indians'),
1726
- new(Time.new(2037, 10, 8, 18, 0), 'Cleveland Indians', 'Houston Astros'),
1727
- new(Time.new(2037, 10, 9, 18, 0), 'Cleveland Indians', 'Houston Astros'),
1728
- new(Time.new(2037, 10, 10, 18, 0), 'Cleveland Indians', 'Houston Astros', 'Free Umbrella'),
1729
- ],
1730
- 'NLCS' => [
1731
- new(Time.new(2037, 10, 12, 12, 0), 'Chicago Cubs', 'Cincinnati Reds', 'Free Towel'),
1732
- new(Time.new(2037, 10, 13, 12, 0), 'Chicago Cubs', 'Cincinnati Reds'),
1733
- new(Time.new(2037, 10, 14, 12, 0), 'Cincinnati Reds', 'Chicago Cubs'),
1734
- new(Time.new(2037, 10, 15, 18, 0), 'Cincinnati Reds', 'Chicago Cubs'),
1735
- new(Time.new(2037, 10, 16, 18, 0), 'Cincinnati Reds', 'Chicago Cubs'),
1736
- new(Time.new(2037, 10, 17, 18, 0), 'Chicago Cubs', 'Cincinnati Reds'),
1737
- new(Time.new(2037, 10, 18, 12, 0), 'Chicago Cubs', 'Cincinnati Reds', 'Free Poncho'),
1738
- ],
1739
- 'ALCS' => [
1740
- new(Time.new(2037, 10, 12, 12, 0), 'Houston Astros', 'Boston Red Sox', 'Free Towel'),
1741
- new(Time.new(2037, 10, 13, 12, 0), 'Houston Astros', 'Boston Red Sox'),
1742
- new(Time.new(2037, 10, 14, 12, 0), 'Boston Red Sox', 'Houston Astros'),
1743
- new(Time.new(2037, 10, 15, 18, 0), 'Boston Red Sox', 'Houston Astros'),
1744
- new(Time.new(2037, 10, 16, 18, 0), 'Boston Red Sox', 'Houston Astros'),
1745
- new(Time.new(2037, 10, 17, 18, 0), 'Houston Astros', 'Boston Red Sox'),
1746
- new(Time.new(2037, 10, 18, 12, 0), 'Houston Astros', 'Boston Red Sox', 'Free Poncho'),
1747
- ],
1748
- 'World Series' => [
1749
- new(Time.new(2037, 10, 20, 18, 0), 'Chicago Cubs', 'Boston Red Sox', 'Free Baseball Cap'),
1750
- new(Time.new(2037, 10, 21, 18, 0), 'Chicago Cubs', 'Boston Red Sox'),
1751
- new(Time.new(2037, 10, 22, 18, 0), 'Boston Red Sox', 'Chicago Cubs'),
1752
- new(Time.new(2037, 10, 23, 18, 0), 'Boston Red Sox', 'Chicago Cubs'),
1753
- new(Time.new(2037, 10, 24, 18, 0), 'Boston Red Sox', 'Chicago Cubs'),
1754
- new(Time.new(2037, 10, 25, 18, 0), 'Chicago Cubs', 'Boston Red Sox'),
1755
- new(Time.new(2037, 10, 26, 18, 0), 'Chicago Cubs', 'Boston Red Sox', 'Free World Series Polo'),
1756
- ]
1757
- }
1758
- end
1759
-
1760
- def playoff_type
1761
- @playoff_type ||= 'World Series'
1762
- end
1763
-
1764
- def playoff_type=(new_playoff_type)
1765
- @playoff_type = new_playoff_type
1766
- self.schedule=(all_playoff_games[@playoff_type])
1767
- end
1768
-
1769
- def playoff_type_options
1770
- all_playoff_games.keys
1771
- end
1772
-
1773
- def schedule
1774
- @schedule ||= all_playoff_games[playoff_type]
1775
- end
1776
-
1777
- def schedule=(new_schedule)
1778
- @schedule = new_schedule
1779
- end
1780
- end
1781
-
1782
- include Glimmer
1783
- include Glimmer::DataBinding::ObservableModel
1784
-
1785
- TEAM_BALLPARKS = {
1786
- 'Boston Red Sox' => 'Fenway Park',
1787
- 'Chicago Cubs' => 'Wrigley Field',
1788
- 'Cincinnati Reds' => 'Great American Ball Park',
1789
- 'Cleveland Indians' => 'Progressive Field',
1790
- 'Houston Astros' => 'Minute Maid Park',
1791
- 'Milwaukee Brewers' => 'Miller Park',
1792
- 'New York Yankees' => 'Yankee Stadium',
1793
- 'St Louis Cardinals' => 'Busch Stadium',
1794
- }
1795
-
1796
- attr_accessor :date_time, :home_team, :away_team, :ballpark, :promotion
1797
-
1798
- def initialize(date_time, home_team, away_team, promotion = 'N/A')
1799
- self.date_time = date_time
1800
- self.home_team = home_team
1801
- self.away_team = away_team
1802
- self.promotion = promotion
1803
- observe(self, :date_time) do |new_value|
1804
- notify_observers(:game_date)
1805
- notify_observers(:game_time)
1806
- end
1807
- end
1808
-
1809
- def home_team=(home_team_value)
1810
- if home_team_value != away_team
1811
- @home_team = home_team_value
1812
- self.ballpark = TEAM_BALLPARKS[@home_team]
1813
- end
1814
- end
1815
-
1816
- def away_team=(away_team_value)
1817
- if away_team_value != home_team
1818
- @away_team = away_team_value
1819
- end
1820
- end
1821
-
1822
- def date
1823
- Date.new(date_time.year, date_time.month, date_time.day)
1824
- end
1825
-
1826
- def time
1827
- Time.new(0, 1, 1, date_time.hour, date_time.min, date_time.sec, '+00:00')
1828
- end
1829
-
1830
- def game_date
1831
- date_time.strftime("%m/%d/%Y")
1832
- end
1833
-
1834
- def game_time
1835
- date_time.strftime("%I:%M %p")
1836
- end
1837
-
1838
- def home_team_options
1839
- TEAM_BALLPARKS.keys
1840
- end
1841
-
1842
- def away_team_options
1843
- TEAM_BALLPARKS.keys
1844
- end
1845
-
1846
- def ballpark_options
1847
- [TEAM_BALLPARKS[@home_team], TEAM_BALLPARKS[@away_team]]
1848
- end
1849
-
1850
- def to_s
1851
- "#{home_team} vs #{away_team} at #{ballpark} on #{game_date} #{game_time}"
1852
- end
1853
-
1854
- def book!
1855
- "Thank you for booking #{to_s}"
1856
- end
1857
- end
1858
-
1859
- include Glimmer
1860
-
1861
- def launch
1862
- shell {
1863
- grid_layout
1864
-
1865
- text 'Hello, Table!'
1866
-
1867
- label {
1868
- layout_data :center, :center, true, false
1869
-
1870
- text 'Baseball Playoff Schedule'
1871
- font height: 30, style: :bold
1872
- }
1873
-
1874
- combo(:read_only) {
1875
- layout_data :center, :center, true, false
1876
- selection bind(BaseballGame, :playoff_type)
1877
- font height: 16
1878
- }
1879
-
1880
- table(:editable) { |table_proxy|
1881
- layout_data :fill, :fill, true, true
1882
-
1883
- table_column {
1884
- text 'Game Date'
1885
- width 150
1886
- sort_property :date # ensure sorting by real date value (not `game_date` string specified in items below)
1887
- editor :date_drop_down, property: :date_time
1888
- }
1889
- table_column {
1890
- text 'Game Time'
1891
- width 150
1892
- sort_property :time # ensure sorting by real time value (not `game_time` string specified in items below)
1893
- editor :time, property: :date_time
1894
- }
1895
- table_column {
1896
- text 'Ballpark'
1897
- width 180
1898
- editor :none
1899
- }
1900
- table_column {
1901
- text 'Home Team'
1902
- width 150
1903
- editor :combo, :read_only # read_only is simply an SWT style passed to combo widget
1904
- }
1905
- table_column {
1906
- text 'Away Team'
1907
- width 150
1908
- editor :combo, :read_only # read_only is simply an SWT style passed to combo widget
1909
- }
1910
- table_column {
1911
- text 'Promotion'
1912
- width 150
1913
- # default text editor is used here
1914
- }
1915
-
1916
- # Data-bind table items (rows) to a model collection property, specifying column properties ordering per nested model
1917
- items bind(BaseballGame, :schedule), column_properties(:game_date, :game_time, :ballpark, :home_team, :away_team, :promotion)
1918
-
1919
- # Data-bind table selection
1920
- selection bind(BaseballGame, :selected_game)
1921
-
1922
- # Default initial sort property
1923
- sort_property :date
1924
-
1925
- # Sort by these additional properties after handling sort by the column the user clicked
1926
- additional_sort_properties :date, :time, :home_team, :away_team, :ballpark, :promotion
1927
- }
1928
-
1929
- button {
1930
- text 'Book Selected Game'
1931
- layout_data :center, :center, true, false
1932
- font height: 16
1933
- enabled bind(BaseballGame, :selected_game)
1934
-
1935
- on_widget_selected {
1936
- book_selected_game
1937
- }
1938
- }
1939
- }.open
1940
- end
1941
-
1942
- def book_selected_game
1943
- message_box {
1944
- text 'Baseball Game Booked!'
1945
- message BaseballGame.selected_game.book!
1946
- }.open
1947
- end
1948
- end
1949
-
1950
- HelloTable.new.launch
1951
- ```
1952
-
1953
1319
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1954
1320
 
1955
1321
  ![Glimmer DSL for SWT Hello Table](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-table.png)
@@ -2044,30 +1410,30 @@ Or add the Glimmer code directly if you prefer to play around with it:
2044
1410
 
2045
1411
  ```ruby
2046
1412
  class HelloButton
2047
- include Glimmer
1413
+ include Glimmer::UI::CustomShell
2048
1414
 
2049
1415
  attr_accessor :count
2050
1416
 
2051
- def initialize
1417
+ before_body {
2052
1418
  @count = 0
2053
- end
1419
+ }
2054
1420
 
2055
- def launch
1421
+ body {
2056
1422
  shell {
2057
1423
  text 'Hello, Button!'
2058
1424
 
2059
1425
  button {
2060
- text bind(self, :count) {|value| "Click To Increment: #{value} "}
1426
+ text <= [self, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
2061
1427
 
2062
1428
  on_widget_selected {
2063
1429
  self.count += 1
2064
1430
  }
2065
1431
  }
2066
- }.open
2067
- end
1432
+ }
1433
+ }
2068
1434
  end
2069
1435
 
2070
- HelloButton.new.launch
1436
+ HelloButton.launch
2071
1437
  ```
2072
1438
 
2073
1439
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
@@ -2687,19 +2053,24 @@ class LoginPresenter
2687
2053
  end
2688
2054
 
2689
2055
  class Login
2690
- include Glimmer
2056
+ include Glimmer::UI::CustomShell
2057
+
2058
+ before_body {
2059
+ @presenter = LoginPresenter.new
2060
+ }
2691
2061
 
2692
- def launch
2693
- presenter = LoginPresenter.new
2694
- @shell = shell {
2062
+ body {
2063
+ shell {
2695
2064
  text "Login"
2065
+
2696
2066
  composite {
2697
2067
  grid_layout 2, false #two columns with differing widths
2698
2068
 
2699
2069
  label { text "Username:" } # goes in column 1
2700
2070
  @user_name_text = text { # goes in column 2
2701
- text bind(presenter, :user_name)
2702
- enabled bind(presenter, :logged_out)
2071
+ text <=> [@presenter, :user_name]
2072
+ enabled <= [@presenter, :logged_out?, computed_by: :status]
2073
+
2703
2074
  on_key_pressed { |event|
2704
2075
  @password_text.set_focus if event.keyCode == swt(:cr)
2705
2076
  }
@@ -2707,43 +2078,47 @@ class Login
2707
2078
 
2708
2079
  label { text "Password:" }
2709
2080
  @password_text = text(:password, :border) {
2710
- text bind(presenter, :password)
2711
- enabled bind(presenter, :logged_out)
2081
+ text <=> [@presenter, :password]
2082
+ enabled <= [@presenter, :logged_out?, computed_by: :status]
2083
+
2712
2084
  on_key_pressed { |event|
2713
- presenter.login if event.keyCode == swt(:cr)
2085
+ @presenter.login! if event.keyCode == swt(:cr)
2714
2086
  }
2715
2087
  }
2716
2088
 
2717
2089
  label { text "Status:" }
2718
- label { text bind(presenter, :status) }
2090
+ label { text <= [@presenter, :status] }
2719
2091
 
2720
2092
  button {
2721
2093
  text "Login"
2722
- enabled bind(presenter, :logged_out)
2723
- on_widget_selected { presenter.login }
2094
+ enabled <= [@presenter, :logged_out?, computed_by: :status]
2095
+
2096
+ on_widget_selected { @presenter.login! }
2724
2097
  on_key_pressed { |event|
2725
- presenter.login if event.keyCode == swt(:cr)
2098
+ if event.keyCode == swt(:cr)
2099
+ @presenter.login!
2100
+ end
2726
2101
  }
2727
2102
  }
2728
2103
 
2729
2104
  button {
2730
2105
  text "Logout"
2731
- enabled bind(presenter, :logged_in)
2732
- on_widget_selected { presenter.logout }
2106
+ enabled <= [@presenter, :logged_in?, computed_by: :status]
2107
+
2108
+ on_widget_selected { @presenter.logout! }
2733
2109
  on_key_pressed { |event|
2734
2110
  if event.keyCode == swt(:cr)
2735
- presenter.logout
2111
+ @presenter.logout!
2736
2112
  @user_name_text.set_focus
2737
2113
  end
2738
2114
  }
2739
2115
  }
2740
2116
  }
2741
2117
  }
2742
- @shell.open
2743
- end
2118
+ }
2744
2119
  end
2745
2120
 
2746
- Login.new.launch
2121
+ Login.launch
2747
2122
  ```
2748
2123
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
2749
2124
 
@@ -2774,214 +2149,7 @@ Add the following require statement to `app/assets/javascripts/application.rb`
2774
2149
  require 'glimmer-dsl-opal/samples/elaborate/tic_tac_toe'
2775
2150
  ```
2776
2151
 
2777
- Or add the Glimmer code directly if you prefer to play around with it:
2778
-
2779
2152
  ```ruby
2780
- class TicTacToe
2781
- class Cell
2782
- EMPTY = ""
2783
- attr_accessor :sign, :empty
2784
-
2785
- def initialize
2786
- reset
2787
- end
2788
-
2789
- def mark(sign)
2790
- self.sign = sign
2791
- end
2792
-
2793
- def reset
2794
- self.sign = EMPTY
2795
- end
2796
-
2797
- def sign=(sign_symbol)
2798
- @sign = sign_symbol
2799
- self.empty = sign == EMPTY
2800
- end
2801
-
2802
- def marked
2803
- !empty
2804
- end
2805
- end
2806
- end
2807
-
2808
- class TicTacToe
2809
- class Board
2810
- DRAW = :draw
2811
- IN_PROGRESS = :in_progress
2812
- WIN = :win
2813
- attr :winning_sign
2814
- attr_accessor :game_status
2815
-
2816
- def initialize
2817
- @sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
2818
- build_grid
2819
- @winning_sign = Cell::EMPTY
2820
- @game_status = IN_PROGRESS
2821
- end
2822
-
2823
- #row and column numbers are 1-based
2824
- def mark(row, column)
2825
- self[row, column].mark(current_sign)
2826
- game_over? #updates winning sign
2827
- end
2828
-
2829
- def current_sign
2830
- @current_sign = @sign_state_machine[@current_sign]
2831
- end
2832
-
2833
- def [](row, column)
2834
- @grid[row-1][column-1]
2835
- end
2836
-
2837
- def game_over?
2838
- win? or draw?
2839
- end
2840
-
2841
- def win?
2842
- win = (row_win? or column_win? or diagonal_win?)
2843
- self.game_status=WIN if win
2844
- win
2845
- end
2846
-
2847
- def reset
2848
- (1..3).each do |row|
2849
- (1..3).each do |column|
2850
- self[row, column].reset
2851
- end
2852
- end
2853
- @winning_sign = Cell::EMPTY
2854
- @current_sign = nil
2855
- self.game_status=IN_PROGRESS
2856
- end
2857
-
2858
- private
2859
-
2860
- def build_grid
2861
- @grid = []
2862
- 3.times do |row_index| #0-based
2863
- @grid << []
2864
- 3.times { @grid[row_index] << Cell.new }
2865
- end
2866
- end
2867
-
2868
- def row_win?
2869
- (1..3).each do |row|
2870
- if row_has_same_sign(row)
2871
- @winning_sign = self[row, 1].sign
2872
- return true
2873
- end
2874
- end
2875
- false
2876
- end
2877
-
2878
- def column_win?
2879
- (1..3).each do |column|
2880
- if column_has_same_sign(column)
2881
- @winning_sign = self[1, column].sign
2882
- return true
2883
- end
2884
- end
2885
- false
2886
- end
2887
-
2888
- #needs refactoring if we ever decide to make the board size dynamic
2889
- def diagonal_win?
2890
- if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
2891
- @winning_sign = self[1, 1].sign
2892
- return true
2893
- end
2894
- if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
2895
- @winning_sign = self[3, 1].sign
2896
- return true
2897
- end
2898
- false
2899
- end
2900
-
2901
- def draw?
2902
- @board_full = true
2903
- 3.times do |x|
2904
- 3.times do |y|
2905
- @board_full = false if self[x, y].empty
2906
- end
2907
- end
2908
- self.game_status = DRAW if @board_full
2909
- @board_full
2910
- end
2911
-
2912
- def row_has_same_sign(number)
2913
- row_sign = self[number, 1].sign
2914
- [2, 3].each do |column|
2915
- return false unless row_sign == (self[number, column].sign)
2916
- end
2917
- true if self[number, 1].marked
2918
- end
2919
-
2920
- def column_has_same_sign(number)
2921
- column_sign = self[1, number].sign
2922
- [2, 3].each do |row|
2923
- return false unless column_sign == (self[row, number].sign)
2924
- end
2925
- true if self[1, number].marked
2926
- end
2927
-
2928
- end
2929
- end
2930
-
2931
- class TicTacToe
2932
- include Glimmer
2933
-
2934
- def initialize
2935
- @tic_tac_toe_board = Board.new
2936
- @shell = shell {
2937
- text "Tic-Tac-Toe"
2938
- minimum_size 150, 178
2939
- composite {
2940
- grid_layout 3, true
2941
- (1..3).each { |row|
2942
- (1..3).each { |column|
2943
- button {
2944
- layout_data :fill, :fill, true, true
2945
- text bind(@tic_tac_toe_board[row, column], :sign)
2946
- enabled bind(@tic_tac_toe_board[row, column], :empty)
2947
- font style: :bold, height: 20
2948
- on_widget_selected {
2949
- @tic_tac_toe_board.mark(row, column)
2950
- }
2951
- }
2952
- }
2953
- }
2954
- }
2955
- }
2956
- observe(@tic_tac_toe_board, :game_status) { |game_status|
2957
- display_win_message if game_status == Board::WIN
2958
- display_draw_message if game_status == Board::DRAW
2959
- }
2960
- end
2961
-
2962
- def display_win_message
2963
- display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
2964
- end
2965
-
2966
- def display_draw_message
2967
- display_game_over_message("Draw!")
2968
- end
2969
-
2970
- def display_game_over_message(message_text)
2971
- message_box(@shell) {
2972
- text 'Game Over'
2973
- message message_text
2974
- }.open
2975
- @tic_tac_toe_board.reset
2976
- end
2977
-
2978
- def open
2979
- @shell.open
2980
- end
2981
- end
2982
-
2983
- TicTacToe.new.open
2984
- ```
2985
2153
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
2986
2154
 
2987
2155
  ![Glimmer DSL for SWT Tic Tac Toe](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-tic-tac-toe.png)
@@ -3011,321 +2179,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
3011
2179
  require 'glimmer-dsl-opal/samples/elaborate/contact_manager'
3012
2180
  ```
3013
2181
 
3014
- Or add the Glimmer code directly if you prefer to play around with it:
3015
-
3016
- ```ruby
3017
- class ContactManager
3018
- class Contact
3019
- attr_accessor :first_name, :last_name, :email
3020
-
3021
- def initialize(attribute_map)
3022
- @first_name = attribute_map[:first_name]
3023
- @last_name = attribute_map[:last_name]
3024
- @email = attribute_map[:email]
3025
- end
3026
- end
3027
- end
3028
-
3029
- class ContactManager
3030
- class ContactRepository
3031
- NAMES_FIRST = %w[
3032
- Liam
3033
- Noah
3034
- William
3035
- James
3036
- Oliver
3037
- Benjamin
3038
- Elijah
3039
- Lucas
3040
- Mason
3041
- Logan
3042
- Alexander
3043
- Ethan
3044
- Jacob
3045
- Michael
3046
- Daniel
3047
- Henry
3048
- Jackson
3049
- Sebastian
3050
- Aiden
3051
- Matthew
3052
- Samuel
3053
- David
3054
- Joseph
3055
- Carter
3056
- Owen
3057
- Wyatt
3058
- John
3059
- Jack
3060
- Luke
3061
- Jayden
3062
- Dylan
3063
- Grayson
3064
- Levi
3065
- Isaac
3066
- Gabriel
3067
- Julian
3068
- Mateo
3069
- Anthony
3070
- Jaxon
3071
- Lincoln
3072
- Joshua
3073
- Christopher
3074
- Andrew
3075
- Theodore
3076
- Caleb
3077
- Ryan
3078
- Asher
3079
- Nathan
3080
- Thomas
3081
- Leo
3082
- Isaiah
3083
- Charles
3084
- Josiah
3085
- Hudson
3086
- Christian
3087
- Hunter
3088
- Connor
3089
- Eli
3090
- Ezra
3091
- Aaron
3092
- Landon
3093
- Adrian
3094
- Jonathan
3095
- Nolan
3096
- Jeremiah
3097
- Easton
3098
- Elias
3099
- Colton
3100
- Cameron
3101
- Carson
3102
- Robert
3103
- Angel
3104
- Maverick
3105
- Nicholas
3106
- Dominic
3107
- Jaxson
3108
- Greyson
3109
- Adam
3110
- Ian
3111
- Austin
3112
- Santiago
3113
- Jordan
3114
- Cooper
3115
- Brayden
3116
- Roman
3117
- Evan
3118
- Ezekiel
3119
- Xaviar
3120
- Jose
3121
- Jace
3122
- Jameson
3123
- Leonardo
3124
- Axel
3125
- Everett
3126
- Kayden
3127
- Miles
3128
- Sawyer
3129
- Jason
3130
- Emma
3131
- Olivia
3132
- ]
3133
- NAMES_LAST = %w[
3134
- Smith
3135
- Johnson
3136
- Williams
3137
- Brown
3138
- Jones
3139
- Miller
3140
- Davis
3141
- Wilson
3142
- Anderson
3143
- Taylor
3144
- ]
3145
- def initialize(contacts = nil)
3146
- @contacts = contacts || 100.times.map do |n|
3147
- random_first_name_index = (rand*NAMES_FIRST.size).to_i
3148
- random_last_name_index = (rand*NAMES_LAST.size).to_i
3149
- first_name = NAMES_FIRST[random_first_name_index]
3150
- last_name = NAMES_LAST[random_last_name_index]
3151
- email = "#{first_name}@#{last_name}.com".downcase
3152
- Contact.new(
3153
- first_name: first_name,
3154
- last_name: last_name,
3155
- email: email
3156
- )
3157
- end
3158
- end
3159
-
3160
- def find(attribute_filter_map)
3161
- @contacts.find_all do |contact|
3162
- match = true
3163
- attribute_filter_map.keys.each do |attribute_name|
3164
- contact_value = contact.send(attribute_name).downcase
3165
- filter_value = attribute_filter_map[attribute_name].downcase
3166
- match = false unless contact_value.match(filter_value)
3167
- end
3168
- match
3169
- end
3170
- end
3171
- end
3172
- end
3173
-
3174
- class ContactManager
3175
- class ContactManagerPresenter
3176
- attr_accessor :results
3177
- @@contact_attributes = [:first_name, :last_name, :email]
3178
- @@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
3179
-
3180
- def initialize(contact_repository = nil)
3181
- @contact_repository = contact_repository || ContactRepository.new
3182
- @results = []
3183
- end
3184
-
3185
- def list
3186
- self.results = @contact_repository.find({})
3187
- end
3188
-
3189
- def find
3190
- filter_map = {}
3191
- @@contact_attributes.each do |attribute_name|
3192
- filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
3193
- end
3194
- self.results = @contact_repository.find(filter_map)
3195
- @sort_attribute_name = nil
3196
- @sort_direction_ascending = nil
3197
- end
3198
-
3199
- def toggle_sort(attribute_name)
3200
- @sort_attribute_name = attribute_name
3201
- @sort_direction_ascending = !@sort_direction_ascending
3202
- sorted_results = self.results.sort_by {|contact| contact.send(attribute_name).downcase}
3203
- sorted_results = sorted_results.reverse unless @sort_direction_ascending
3204
- self.results = sorted_results
3205
- end
3206
- end
3207
- end
3208
-
3209
- class ContactManager
3210
- include Glimmer
3211
-
3212
- def initialize
3213
- @contact_manager_presenter = ContactManagerPresenter.new
3214
- @contact_manager_presenter.list
3215
- end
3216
-
3217
- def launch
3218
- shell {
3219
- text "Contact Manager"
3220
- composite {
3221
- group {
3222
- grid_layout(2, false) {
3223
- margin_width 0
3224
- margin_height 0
3225
- }
3226
- layout_data :fill, :center, true, false
3227
- text 'Lookup Contacts'
3228
- font height: 24
3229
-
3230
- label {
3231
- layout_data :right, :center, false, false
3232
- text "First &Name: "
3233
- font height: 16
3234
- }
3235
- text {
3236
- layout_data :fill, :center, true, false
3237
- text bind(@contact_manager_presenter, :first_name)
3238
- on_key_pressed {|key_event|
3239
- @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
3240
- }
3241
- }
3242
-
3243
- label {
3244
- layout_data :right, :center, false, false
3245
- text "&Last Name: "
3246
- font height: 16
3247
- }
3248
- text {
3249
- layout_data :fill, :center, true, false
3250
- text bind(@contact_manager_presenter, :last_name)
3251
- on_key_pressed {|key_event|
3252
- @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
3253
- }
3254
- }
3255
-
3256
- label {
3257
- layout_data :right, :center, false, false
3258
- text "&Email: "
3259
- font height: 16
3260
- }
3261
- text {
3262
- layout_data :fill, :center, true, false
3263
- text bind(@contact_manager_presenter, :email)
3264
- on_key_pressed {|key_event|
3265
- @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
3266
- }
3267
- }
3268
-
3269
- composite {
3270
- row_layout {
3271
- margin_width 0
3272
- margin_height 0
3273
- }
3274
- layout_data(:right, :center, false, false) {
3275
- horizontal_span 2
3276
- }
3277
-
3278
- button {
3279
- text "&Find"
3280
- on_widget_selected { @contact_manager_presenter.find }
3281
- on_key_pressed {|key_event|
3282
- @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
3283
- }
3284
- }
3285
-
3286
- button {
3287
- text "&List All"
3288
- on_widget_selected { @contact_manager_presenter.list }
3289
- on_key_pressed {|key_event|
3290
- @contact_manager_presenter.list if key_event.keyCode == swt(:cr)
3291
- }
3292
- }
3293
- }
3294
- }
3295
-
3296
- table(:multi) { |table_proxy|
3297
- layout_data {
3298
- horizontal_alignment :fill
3299
- vertical_alignment :fill
3300
- grab_excess_horizontal_space true
3301
- grab_excess_vertical_space true
3302
- height_hint 200
3303
- }
3304
- table_column {
3305
- text "First Name"
3306
- width 80
3307
- }
3308
- table_column {
3309
- text "Last Name"
3310
- width 80
3311
- }
3312
- table_column {
3313
- text "Email"
3314
- width 200
3315
- }
3316
- items bind(@contact_manager_presenter, :results),
3317
- column_properties(:first_name, :last_name, :email)
3318
- on_mouse_up { |event|
3319
- table_proxy.edit_table_item(event.table_item, event.column_index)
3320
- }
3321
- }
3322
- }
3323
- }.open
3324
- end
3325
- end
3326
-
3327
- ContactManager.new.launch
3328
- ```
3329
2182
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
3330
2183
 
3331
2184
  Glimmer DSL for SWT Contact Manager
@@ -3379,6 +2232,39 @@ Glimmer DSL for Opal Contact Manager Edit Done
3379
2232
 
3380
2233
  ![Glimmer DSL for Opal Contact Manager Edit Done](images/glimmer-dsl-opal-contact-manager-edit-done.png)
3381
2234
 
2235
+ #### Weather
2236
+
2237
+ Add the following require statement to `app/assets/javascripts/application.rb`
2238
+
2239
+ ```ruby
2240
+ require 'glimmer-dsl-opal/samples/elaborate/weather'
2241
+ ```
2242
+
2243
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
2244
+
2245
+ ![Weather Montreal C](https://github.com/AMaleh/glimmer-dsl-swt/raw/master/images/glimmer-weather-montreal-celsius.png)
2246
+
2247
+ ![Weather Montreal F](https://github.com/AMaleh/glimmer-dsl-swt/raw/master/images/glimmer-weather-montreal-fahrenheit.png)
2248
+
2249
+ ![Weather Atlanta F](https://github.com/AMaleh /glimmer-dsl-swt/raw/master/images/glimmer-weather-atlanta-fahrenheit.png)
2250
+
2251
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
2252
+
2253
+ Start the Rails server:
2254
+ ```
2255
+ rails s
2256
+ ```
2257
+
2258
+ Visit `http://localhost:3000`
2259
+
2260
+ You should see "Weather"
2261
+
2262
+ ![Opal Weather Montreal C](/images/glimmer-dsl-opal-weather-montreal-celsius.png)
2263
+
2264
+ ![Opal Weather Montreal F](/images/glimmer-dsl-opal-weather-montreal-fahrenheit.png)
2265
+
2266
+ ![Opal Weather Atlanta F](/images/glimmer-dsl-opal-weather-atlanta-fahrenheit.png)
2267
+
3382
2268
  ### External Samples
3383
2269
 
3384
2270
  #### Glimmer Calculator