glimmer-dsl-opal 0.0.4 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +983 -34
  4. data/VERSION +1 -1
  5. data/lib/glimmer-dsl-opal.rb +5 -2
  6. data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
  7. data/lib/glimmer/data_binding/table_items_binding.rb +70 -0
  8. data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
  9. data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
  10. data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
  11. data/lib/glimmer/dsl/opal/dsl.rb +11 -0
  12. data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
  13. data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
  14. data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
  15. data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
  16. data/lib/glimmer/dsl/opal/table_column_expression.rb +17 -0
  17. data/lib/glimmer/dsl/opal/table_expression.rb +17 -0
  18. data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
  19. data/lib/glimmer/opal/display_proxy.rb +23 -0
  20. data/lib/glimmer/opal/div_proxy.rb +11 -2
  21. data/lib/glimmer/opal/document_proxy.rb +124 -4
  22. data/lib/glimmer/opal/element_proxy.rb +45 -14
  23. data/lib/glimmer/opal/grid_layout_proxy.rb +3 -1
  24. data/lib/glimmer/opal/iframe_proxy.rb +23 -0
  25. data/lib/glimmer/opal/input_proxy.rb +8 -4
  26. data/lib/glimmer/opal/label_proxy.rb +1 -1
  27. data/lib/glimmer/opal/layout_data_proxy.rb +23 -2
  28. data/lib/glimmer/opal/list_proxy.rb +2 -2
  29. data/lib/glimmer/opal/modal.rb +94 -0
  30. data/lib/glimmer/opal/point.rb +5 -0
  31. data/lib/glimmer/opal/select_proxy.rb +1 -1
  32. data/lib/glimmer/opal/tab_folder.rb +53 -0
  33. data/lib/glimmer/opal/tab_item.rb +98 -0
  34. data/lib/glimmer/opal/table_column.rb +50 -0
  35. data/lib/glimmer/opal/table_item.rb +136 -0
  36. data/lib/glimmer/opal/table_proxy.rb +149 -0
  37. data/lib/samples/elaborate/contact_manager.rb +1 -2
  38. data/lib/samples/elaborate/login.rb +0 -1
  39. data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
  40. data/lib/samples/hello/hello_tab.rb +2 -2
  41. metadata +28 -16
  42. data/lib/glimmer/config.rb +0 -22
  43. data/lib/glimmer/dsl/engine.rb +0 -193
  44. data/lib/glimmer/dsl/expression.rb +0 -42
  45. data/lib/glimmer/dsl/expression_handler.rb +0 -48
  46. data/lib/glimmer/dsl/parent_expression.rb +0 -12
  47. data/lib/glimmer/dsl/static_expression.rb +0 -36
  48. data/lib/glimmer/dsl/top_level_expression.rb +0 -7
  49. data/lib/glimmer/error.rb +0 -6
  50. data/lib/glimmer/invalid_keyword_error.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4abedea4353104a18359a2131eee38b7cff23498f246e35ddec92380798c5555
4
- data.tar.gz: cbba1e1d0b89ebd01c9ddba94cfbeeee5359f93b985e192d826829369794c85e
3
+ metadata.gz: b56026edb0b7ab096e2b972afcc99f2914db153e52fa52616859b44e86d0ad8c
4
+ data.tar.gz: aa94ad9ded4e7cac3ec706db46a012861e9c1e3a0d0026cdcc7833f43733eba0
5
5
  SHA512:
6
- metadata.gz: 8223f782d4e4daeefa03081e95b54fc4ab0e9782825a4fd4c17d041d73284c7bf1c78a3141defa526b648e5d6ab41b63ffafea610584d235f7f6b29adb21d3ca
7
- data.tar.gz: d8f62269cc84ae305f3e6cbd74d371272008d7ed1f6d2d8bb44b3fb95cc96247c7628fb95f788a19e2e30d67aedf017dfc19e82b8467af349d000013caa05219
6
+ metadata.gz: 66e958ca4e486e0a33908fb21d72322c375da35774a86e0514898a50b214bff0ecd7e7f4f5ce930983394cf49d9386ddce45f9ddcc0eb5e0074c455e8ebb87c9
7
+ data.tar.gz: 9e57c5f9a2bb433f182e7f7ce392f19985796cd56f8f40bed01bfed2e7385a25b4bf3fb7b06c541dae0b77cda2a981ac71d2a094d21f0beede0f8867b3fd1333
@@ -1,5 +1,40 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.9
4
+
5
+ - Upgraded to glimmer gem v0.9.3
6
+ - Fixed issue with missing Glimmer::Opal::ElementProxy#id=(value) method breaking Contact Manager sample Find feature
7
+
8
+ ## 0.0.8
9
+
10
+ - Contact Manager sample support
11
+
12
+ ## 0.0.7
13
+
14
+ - Tic Tac Toe sample support
15
+ - Login sample support
16
+
17
+ ## 0.0.6
18
+
19
+ - Hello, Tab! sample support
20
+
21
+ ## 0.0.5
22
+
23
+ - Hello, Browser! sample support
24
+
25
+ ## 0.0.4
26
+
27
+ - Hello, List Single Selection! sample support
28
+ - Hello, List Multi Selection! sample support
29
+
30
+ ## 0.0.3
31
+
32
+ - Hello, Computed! sample support
33
+
34
+ ## 0.0.2
35
+
36
+ - Hello, Combo! sample support
37
+
3
38
  ## 0.0.1
4
39
 
5
40
  - Initial support for webifying Glimmer SWT apps
data/README.md CHANGED
@@ -1,18 +1,20 @@
1
-
2
- # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=65 /> Glimmer DSL for Opal 0.0.4 (Web GUI for Desktop Apps)
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=65 /> Glimmer DSL for Opal 0.0.9 (Webify Desktop Apps)
3
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-opal.svg)](http://badge.fury.io/rb/glimmer-dsl-opal)
4
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)
5
4
 
6
- [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).
7
-
8
- 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.
5
+ Glimmer DSL for Opal is an experimental web GUI adaptor for [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer](https://github.com/AndyObtiva/glimmer) [DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)). It webifies them via [Rails](https://rubyonrails.org/) and [Opal](https://opalrb.com/), allowing Ruby desktop apps to run on the web without changing a line of code. Apps may then be custom-styled for the web via standard CSS.
9
6
 
10
- NOTE: Alpha Version 0.0.4 only supports capabilities below (detailed under [Examples](#examples)):
7
+ NOTE: Alpha Version 0.0.9 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):
11
8
  - [Hello, World!](#hello-world)
12
9
  - [Hello, Combo!](#hello-combo)
13
10
  - [Hello, Computed!](#hello-computed)
14
11
  - [Hello, List Single Selection!](#hello-list-single-selection)
15
12
  - [Hello, List Multi Selection!](#hello-list-multi-selection)
13
+ - [Hello, Browser!](#hello-browser)
14
+ - [Hello, Tab!](#hello-tab)
15
+ - [Login](#login)
16
+ - [Tic Tac Toe](#tic-tac-toe)
17
+ - [Contact Manager](#contact-manager)
16
18
 
17
19
  Other Glimmer DSL gems:
18
20
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
@@ -30,6 +32,16 @@ The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glim
30
32
  - `text`
31
33
  - `composite`
32
34
  - `list` & `list(:multi)`
35
+ - `tab_folder`
36
+ - `tab_item`
37
+ - `table`
38
+ - `table_column`
39
+ - `message_box`
40
+ - `on_widget_selected`
41
+ - `on_modify_text`
42
+ - `observe`
43
+ - `bind`
44
+ - `async_exec`
33
45
  - `grid_layout`
34
46
  - `layout_data`
35
47
 
@@ -40,37 +52,55 @@ The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glim
40
52
 
41
53
  ## Setup
42
54
 
43
- Please follow these instructions to make Glimmer desktop apps work in Opal inside Rails 5
55
+ (NOTE: if you run into issues, they are probably fixed in master or development/wip branch, you may check out instead)
56
+
57
+ Please install a Rails 5 gem (e.g. `gem install rails -v5.2.4.3` )
44
58
 
45
59
  Start a new Rails 5 app:
46
60
 
47
61
  ```
48
- rails new hello_world
62
+ rails new glimmer_app
49
63
  ```
50
64
 
51
- Follow instructions to setup opal with a rails application: config/initializers/assets.rb
65
+ Add the following to `Gemfile`:
52
66
 
53
- 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):
54
67
  ```
55
- gem 'opal-rails'
56
- gem 'opal-browser'
57
- gem 'glimmer-dsl-opal', '~> 0.0.4', require: false
68
+ gem 'opal-rails', '~> 1.1.2'
69
+ gem 'opal-async', '~> 1.1.0'
70
+ gem 'opal-browser', '~> 0.2.0'
71
+ gem 'glimmer-dsl-opal', '~> 0.0.9', require: false
58
72
  ```
59
73
 
60
- Edit `config/initializers/assets.rb` and add:
74
+ Follow (opal-rails)[https://github.com/opal/opal-rails] instructions, basically the configuration of: config/initializers/assets.rb
75
+
76
+ Edit `config/initializers/assets.rb` and add the following at the bottom:
61
77
  ```
62
78
  Opal.use_gem 'glimmer-dsl-opal'
63
79
  ```
64
80
 
65
- ## Examples
81
+ Add the following line to the top of an empty `app/assets/javascripts/application.rb` (replacing `application.js`)
82
+
83
+ ```ruby
84
+ require 'glimmer-dsl-opal' # brings opal and opal browser too
85
+ ```
86
+
87
+ Add more code to `app/assets/javascripts/application.rb` from one of the samples below or require a [Glimmer](https://github.com/AndyObtiva/glimmer) app/[custom-shell](https://github.com/AndyObtiva/glimmer#custom-shell-gem) gem.
88
+
89
+ ## Samples
90
+
91
+ ### Hello Samples
66
92
 
67
- ### Hello, World!
93
+ #### Hello, World!
68
94
 
69
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
95
+ Add the following require statement to `app/assets/javascripts/application.rb`
70
96
 
71
97
  ```ruby
72
- require 'glimmer-dsl-opal' # brings opal and opal browser too
98
+ require 'samples/hello/hello_world'
99
+ ```
100
+
101
+ Or add the Glimmer code directly if you prefer to play around with it:
73
102
 
103
+ ```ruby
74
104
  include Glimmer
75
105
 
76
106
  shell {
@@ -78,12 +108,12 @@ shell {
78
108
  label {
79
109
  text 'Hello, World!'
80
110
  }
81
- }
111
+ }.open
82
112
  ```
83
113
 
84
114
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
85
115
 
86
- ![Glimmer DSL for Opal Hello World](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-world.png)
116
+ ![Glimmer DSL for SWT Hello World](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-world.png)
87
117
 
88
118
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
89
119
 
@@ -98,13 +128,17 @@ You should see "Hello, World!"
98
128
 
99
129
  ![Glimmer DSL for Opal Hello World](images/glimmer-dsl-opal-hello-world.png)
100
130
 
101
- ### Hello, Combo!
131
+ #### Hello, Combo!
102
132
 
103
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
133
+ Add the following require statement to `app/assets/javascripts/application.rb`
104
134
 
105
135
  ```ruby
106
- require 'glimmer-dsl-opal' # brings opal and opal browser too
136
+ require 'samples/hello/hello_combo'
137
+ ```
138
+
139
+ Or add the Glimmer code directly if you prefer to play around with it:
107
140
 
141
+ ```ruby
108
142
  class Person
109
143
  attr_accessor :country, :country_options
110
144
 
@@ -142,7 +176,7 @@ HelloCombo.new.launch
142
176
  ```
143
177
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
144
178
 
145
- ![Glimmer DSL for Opal Hello Combo](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-combo.png)
179
+ ![Glimmer DSL for SWT Hello Combo](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-combo.png)
146
180
 
147
181
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
148
182
 
@@ -157,13 +191,18 @@ You should see "Hello, Combo!"
157
191
 
158
192
  ![Glimmer DSL for Opal Hello Combo](images/glimmer-dsl-opal-hello-combo.png)
159
193
 
160
- ### Hello, Computed!
194
+ #### Hello, Computed!
195
+
196
+ Add the following require statement to `app/assets/javascripts/application.rb`
161
197
 
162
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
163
198
 
164
199
  ```ruby
165
- require 'glimmer-dsl-opal' # brings opal and opal browser too
200
+ require 'samples/hello/hello_computed'
201
+ ```
202
+
203
+ Or add the Glimmer code directly if you prefer to play around with it:
166
204
 
205
+ ```ruby
167
206
  class HelloComputed
168
207
  class Contact
169
208
  attr_accessor :first_name, :last_name, :year_of_birth
@@ -256,7 +295,7 @@ HelloComputed.new.launch
256
295
  ```
257
296
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
258
297
 
259
- ![Glimmer DSL for Opal Hello Computed](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-computed.png)
298
+ ![Glimmer DSL for SWT Hello Computed](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-computed.png)
260
299
 
261
300
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
262
301
 
@@ -271,9 +310,16 @@ You should see "Hello, Computed!"
271
310
 
272
311
  ![Glimmer DSL for Opal Hello Computed](images/glimmer-dsl-opal-hello-computed.png)
273
312
 
274
- ### Hello, List Single Selection!
313
+ #### Hello, List Single Selection!
314
+
315
+ Add the following require statement to `app/assets/javascripts/application.rb`
275
316
 
276
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
317
+
318
+ ```ruby
319
+ require 'samples/hello/hello_list_single_selection'
320
+ ```
321
+
322
+ Or add the Glimmer code directly if you prefer to play around with it:
277
323
 
278
324
  ```ruby
279
325
  class Person
@@ -313,7 +359,7 @@ HelloListSingleSelection.new.launch
313
359
  ```
314
360
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
315
361
 
316
- ![Glimmer DSL for Opal Hello List Single Selection](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-list-single-selection.png)
362
+ ![Glimmer DSL for SWT Hello List Single Selection](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-list-single-selection.png)
317
363
 
318
364
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
319
365
 
@@ -328,9 +374,15 @@ You should see "Hello, List Single Selection!"
328
374
 
329
375
  ![Glimmer DSL for Opal Hello List Single Selection](images/glimmer-dsl-opal-hello-list-single-selection.png)
330
376
 
331
- ### Hello, List Multi Selection!
377
+ #### Hello, List Multi Selection!
332
378
 
333
- Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
379
+ Add the following require statement to `app/assets/javascripts/application.rb`
380
+
381
+ ```ruby
382
+ require 'samples/hello/hello_list_multi_selection'
383
+ ```
384
+
385
+ Or add the Glimmer code directly if you prefer to play around with it:
334
386
 
335
387
  ```ruby
336
388
  class Person
@@ -380,7 +432,7 @@ HelloListMultiSelection.new.launch
380
432
  ```
381
433
  Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
382
434
 
383
- ![Glimmer DSL for Opal Hello List Multi Selection](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-list-multi-selection.png)
435
+ ![Glimmer DSL for SWT Hello List Multi Selection](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-list-multi-selection.png)
384
436
 
385
437
  Glimmer app on the web (using `glimmer-dsl-opal` gem):
386
438
 
@@ -395,6 +447,903 @@ You should see "Hello, List Multi Selection!"
395
447
 
396
448
  ![Glimmer DSL for Opal Hello List Multi Selection](images/glimmer-dsl-opal-hello-list-multi-selection.png)
397
449
 
450
+ #### Hello, Browser!
451
+
452
+ Add the following require statement to `app/assets/javascripts/application.rb`
453
+
454
+ ```ruby
455
+ require 'samples/hello/hello_browser'
456
+ ```
457
+
458
+ Or add the Glimmer code directly if you prefer to play around with it:
459
+
460
+ ```ruby
461
+ include Glimmer
462
+
463
+ shell {
464
+ minimum_size 1024, 860
465
+ browser {
466
+ url 'http://brightonresort.com/about'
467
+ }
468
+ }.open
469
+ ```
470
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
471
+
472
+ ![Glimmer DSL for SWT Hello Browser](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-browser.png)
473
+
474
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
475
+
476
+ Start the Rails server:
477
+ ```
478
+ rails s
479
+ ```
480
+
481
+ Visit `http://localhost:3000`
482
+
483
+ You should see "Hello, Browser!"
484
+
485
+ ![Glimmer DSL for Opal Hello Browser](images/glimmer-dsl-opal-hello-browser.png)
486
+
487
+ #### Hello, Tab!
488
+
489
+ Add the following require statement to `app/assets/javascripts/application.rb`
490
+
491
+ ```ruby
492
+ require 'samples/hello/hello_tab'
493
+ ```
494
+
495
+ Or add the Glimmer code directly if you prefer to play around with it:
496
+
497
+ ```ruby
498
+ class HelloTab
499
+ include Glimmer
500
+ def launch
501
+ shell {
502
+ text "Hello, Tab!"
503
+ tab_folder {
504
+ tab_item {
505
+ text "English"
506
+ label {
507
+ text "Hello, World!"
508
+ }
509
+ }
510
+ tab_item {
511
+ text "French"
512
+ label {
513
+ text "Bonjour, Univers!"
514
+ }
515
+ }
516
+ }
517
+ }.open
518
+ end
519
+ end
520
+
521
+ HelloTab.new.launch
522
+ ```
523
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
524
+
525
+ ![Glimmer DSL for SWT Hello Tab English](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-tab-english.png)
526
+ ![Glimmer DSL for SWT Hello Tab French](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-tab-french.png)
527
+
528
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
529
+
530
+ Start the Rails server:
531
+ ```
532
+ rails s
533
+ ```
534
+
535
+ Visit `http://localhost:3000`
536
+
537
+ You should see "Hello, Tab!"
538
+
539
+ ![Glimmer DSL for Opal Hello Tab English](images/glimmer-dsl-opal-hello-tab-english.png)
540
+ ![Glimmer DSL for Opal Hello Tab French](images/glimmer-dsl-opal-hello-tab-french.png)
541
+
542
+ ### Elaborate Samples
543
+
544
+ #### Login
545
+
546
+ Add the following require statement to `app/assets/javascripts/application.rb`
547
+
548
+ ```ruby
549
+ require 'samples/elaborate/login'
550
+ ```
551
+
552
+ Or add the Glimmer code directly if you prefer to play around with it:
553
+
554
+ ```ruby
555
+ require "observer"
556
+
557
+ #Presents login screen data
558
+ class LoginPresenter
559
+
560
+ attr_accessor :user_name
561
+ attr_accessor :password
562
+ attr_accessor :status
563
+
564
+ def initialize
565
+ @user_name = ""
566
+ @password = ""
567
+ @status = "Logged Out"
568
+ end
569
+
570
+ def status=(status)
571
+ @status = status
572
+
573
+ #TODO add feature to bind dependent properties to master property (2017-07-25 nested data binding)
574
+ notify_observers("logged_in")
575
+ notify_observers("logged_out")
576
+ end
577
+
578
+ def logged_in
579
+ self.status == "Logged In"
580
+ end
581
+
582
+ def logged_out
583
+ !self.logged_in
584
+ end
585
+
586
+ def login
587
+ self.status = "Logged In"
588
+ end
589
+
590
+ def logout
591
+ self.user_name = ""
592
+ self.password = ""
593
+ self.status = "Logged Out"
594
+ end
595
+
596
+ end
597
+
598
+ #Login screen
599
+ class Login
600
+ include Glimmer
601
+
602
+ def launch
603
+ presenter = LoginPresenter.new
604
+ @shell = shell {
605
+ text "Login"
606
+ composite {
607
+ grid_layout 2, false #two columns with differing widths
608
+
609
+ label { text "Username:" } # goes in column 1
610
+ text { # goes in column 2
611
+ text bind(presenter, :user_name)
612
+ enabled bind(presenter, :logged_out)
613
+ }
614
+
615
+ label { text "Password:" }
616
+ text(:password, :border) {
617
+ text bind(presenter, :password)
618
+ enabled bind(presenter, :logged_out)
619
+ }
620
+
621
+ label { text "Status:" }
622
+ label { text bind(presenter, :status) }
623
+
624
+ button {
625
+ text "Login"
626
+ enabled bind(presenter, :logged_out)
627
+ on_widget_selected { presenter.login }
628
+ }
629
+
630
+ button {
631
+ text "Logout"
632
+ enabled bind(presenter, :logged_in)
633
+ on_widget_selected { presenter.logout }
634
+ }
635
+ }
636
+ }
637
+ @shell.open
638
+ end
639
+ end
640
+
641
+ Login.new.launch
642
+ ```
643
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
644
+
645
+ ![Glimmer DSL for SWT Login](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-login.png)
646
+ ![Glimmer DSL for SWT Login Filled In](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-login-filled-in.png)
647
+ ![Glimmer DSL for SWT Login Logged In](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-login-logged-in.png)
648
+
649
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
650
+
651
+ Start the Rails server:
652
+ ```
653
+ rails s
654
+ ```
655
+
656
+ Visit `http://localhost:3000`
657
+
658
+ You should see "Login" dialog
659
+
660
+ ![Glimmer DSL for Opal Login](images/glimmer-dsl-opal-login.png)
661
+ ![Glimmer DSL for Opal Login Filled In](images/glimmer-dsl-opal-login-filled-in.png)
662
+ ![Glimmer DSL for Opal Login Logged In](images/glimmer-dsl-opal-login-logged-in.png)
663
+
664
+ #### Tic Tac Toe
665
+
666
+ Add the following require statement to `app/assets/javascripts/application.rb`
667
+
668
+ ```ruby
669
+ require 'samples/elaborate/tic_tac_toe'
670
+ ```
671
+
672
+ Or add the Glimmer code directly if you prefer to play around with it:
673
+
674
+ ```ruby
675
+ class TicTacToe
676
+ class Cell
677
+ EMPTY = ""
678
+ attr_accessor :sign, :empty
679
+
680
+ def initialize
681
+ reset
682
+ end
683
+
684
+ def mark(sign)
685
+ self.sign = sign
686
+ end
687
+
688
+ def reset
689
+ self.sign = EMPTY
690
+ end
691
+
692
+ def sign=(sign_symbol)
693
+ @sign = sign_symbol
694
+ self.empty = sign == EMPTY
695
+ end
696
+
697
+ def marked
698
+ !empty
699
+ end
700
+ end
701
+ end
702
+
703
+ class TicTacToe
704
+ class Board
705
+ DRAW = :draw
706
+ IN_PROGRESS = :in_progress
707
+ WIN = :win
708
+ attr :winning_sign
709
+ attr_accessor :game_status
710
+
711
+ def initialize
712
+ @sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
713
+ build_grid
714
+ @winning_sign = Cell::EMPTY
715
+ @game_status = IN_PROGRESS
716
+ end
717
+
718
+ #row and column numbers are 1-based
719
+ def mark(row, column)
720
+ self[row, column].mark(current_sign)
721
+ game_over? #updates winning sign
722
+ end
723
+
724
+ def current_sign
725
+ @current_sign = @sign_state_machine[@current_sign]
726
+ end
727
+
728
+ def [](row, column)
729
+ @grid[row-1][column-1]
730
+ end
731
+
732
+ def game_over?
733
+ win? or draw?
734
+ end
735
+
736
+ def win?
737
+ win = (row_win? or column_win? or diagonal_win?)
738
+ self.game_status=WIN if win
739
+ win
740
+ end
741
+
742
+ def reset
743
+ (1..3).each do |row|
744
+ (1..3).each do |column|
745
+ self[row, column].reset
746
+ end
747
+ end
748
+ @winning_sign = Cell::EMPTY
749
+ @current_sign = nil
750
+ self.game_status=IN_PROGRESS
751
+ end
752
+
753
+ private
754
+
755
+ def build_grid
756
+ @grid = []
757
+ 3.times do |row_index| #0-based
758
+ @grid << []
759
+ 3.times { @grid[row_index] << Cell.new }
760
+ end
761
+ end
762
+
763
+ def row_win?
764
+ (1..3).each do |row|
765
+ if row_has_same_sign(row)
766
+ @winning_sign = self[row, 1].sign
767
+ return true
768
+ end
769
+ end
770
+ false
771
+ end
772
+
773
+ def column_win?
774
+ (1..3).each do |column|
775
+ if column_has_same_sign(column)
776
+ @winning_sign = self[1, column].sign
777
+ return true
778
+ end
779
+ end
780
+ false
781
+ end
782
+
783
+ #needs refactoring if we ever decide to make the board size dynamic
784
+ def diagonal_win?
785
+ if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
786
+ @winning_sign = self[1, 1].sign
787
+ return true
788
+ end
789
+ if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
790
+ @winning_sign = self[3, 1].sign
791
+ return true
792
+ end
793
+ false
794
+ end
795
+
796
+ def draw?
797
+ @board_full = true
798
+ 3.times do |x|
799
+ 3.times do |y|
800
+ @board_full = false if self[x, y].empty
801
+ end
802
+ end
803
+ self.game_status = DRAW if @board_full
804
+ @board_full
805
+ end
806
+
807
+ def row_has_same_sign(number)
808
+ row_sign = self[number, 1].sign
809
+ [2, 3].each do |column|
810
+ return false unless row_sign == (self[number, column].sign)
811
+ end
812
+ true if self[number, 1].marked
813
+ end
814
+
815
+ def column_has_same_sign(number)
816
+ column_sign = self[1, number].sign
817
+ [2, 3].each do |row|
818
+ return false unless column_sign == (self[row, number].sign)
819
+ end
820
+ true if self[1, number].marked
821
+ end
822
+
823
+ end
824
+ end
825
+
826
+ class TicTacToe
827
+ include Glimmer
828
+
829
+ def initialize
830
+ @tic_tac_toe_board = Board.new
831
+ @shell = shell {
832
+ text "Tic-Tac-Toe"
833
+ composite {
834
+ grid_layout 3, true
835
+ (1..3).each { |row|
836
+ (1..3).each { |column|
837
+ button {
838
+ layout_data :fill, :fill, true, true
839
+ text bind(@tic_tac_toe_board[row, column], :sign)
840
+ enabled bind(@tic_tac_toe_board[row, column], :empty)
841
+ on_widget_selected {
842
+ @tic_tac_toe_board.mark(row, column)
843
+ }
844
+ }
845
+ }
846
+ }
847
+ }
848
+ }
849
+ observe(@tic_tac_toe_board, :game_status) { |game_status|
850
+ display_win_message if game_status == Board::WIN
851
+ display_draw_message if game_status == Board::DRAW
852
+ }
853
+ end
854
+
855
+ def display_win_message
856
+ display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
857
+ end
858
+
859
+ def display_draw_message
860
+ display_game_over_message("Draw!")
861
+ end
862
+
863
+ def display_game_over_message(message_text)
864
+ message_box(@shell) {
865
+ text 'Game Over'
866
+ message message_text
867
+ }.open
868
+ @tic_tac_toe_board.reset
869
+ end
870
+
871
+ def open
872
+ @shell.open
873
+ end
874
+ end
875
+
876
+ TicTacToe.new.open
877
+ ```
878
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
879
+
880
+ ![Glimmer DSL for SWT Tic Tac Toe](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe.png)
881
+ ![Glimmer DSL for SWT Tic Tac Toe In Progress](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe-in-progress.png)
882
+ ![Glimmer DSL for SWT Tic Tac Toe Game Over](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe-game-over.png)
883
+
884
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
885
+
886
+ Start the Rails server:
887
+ ```
888
+ rails s
889
+ ```
890
+
891
+ Visit `http://localhost:3000`
892
+
893
+ You should see "Tic Tac Toe"
894
+
895
+ ![Glimmer DSL for Opal Tic Tac Toe](images/glimmer-dsl-opal-tic-tac-toe.png)
896
+ ![Glimmer DSL for Opal Tic Tac Toe In Progress](images/glimmer-dsl-opal-tic-tac-toe-in-progress.png)
897
+ ![Glimmer DSL for Opal Tic Tac Toe Game Over](images/glimmer-dsl-opal-tic-tac-toe-game-over.png)
898
+
899
+ #### Contact Manager
900
+
901
+ Add the following require statement to `app/assets/javascripts/application.rb`
902
+
903
+ ```ruby
904
+ require 'samples/elaborate/contact_manager'
905
+ ```
906
+
907
+ Or add the Glimmer code directly if you prefer to play around with it:
908
+
909
+ ```ruby
910
+ class ContactManager
911
+ class Contact
912
+ attr_accessor :first_name, :last_name, :email
913
+
914
+ def initialize(attribute_map)
915
+ @first_name = attribute_map[:first_name]
916
+ @last_name = attribute_map[:last_name]
917
+ @email = attribute_map[:email]
918
+ end
919
+ end
920
+ end
921
+
922
+ class ContactManager
923
+ class ContactRepository
924
+ NAMES_FIRST = %w[
925
+ Liam
926
+ Noah
927
+ William
928
+ James
929
+ Oliver
930
+ Benjamin
931
+ Elijah
932
+ Lucas
933
+ Mason
934
+ Logan
935
+ Alexander
936
+ Ethan
937
+ Jacob
938
+ Michael
939
+ Daniel
940
+ Henry
941
+ Jackson
942
+ Sebastian
943
+ Aiden
944
+ Matthew
945
+ Samuel
946
+ David
947
+ Joseph
948
+ Carter
949
+ Owen
950
+ Wyatt
951
+ John
952
+ Jack
953
+ Luke
954
+ Jayden
955
+ Dylan
956
+ Grayson
957
+ Levi
958
+ Isaac
959
+ Gabriel
960
+ Julian
961
+ Mateo
962
+ Anthony
963
+ Jaxon
964
+ Lincoln
965
+ Joshua
966
+ Christopher
967
+ Andrew
968
+ Theodore
969
+ Caleb
970
+ Ryan
971
+ Asher
972
+ Nathan
973
+ Thomas
974
+ Leo
975
+ Isaiah
976
+ Charles
977
+ Josiah
978
+ Hudson
979
+ Christian
980
+ Hunter
981
+ Connor
982
+ Eli
983
+ Ezra
984
+ Aaron
985
+ Landon
986
+ Adrian
987
+ Jonathan
988
+ Nolan
989
+ Jeremiah
990
+ Easton
991
+ Elias
992
+ Colton
993
+ Cameron
994
+ Carson
995
+ Robert
996
+ Angel
997
+ Maverick
998
+ Nicholas
999
+ Dominic
1000
+ Jaxson
1001
+ Greyson
1002
+ Adam
1003
+ Ian
1004
+ Austin
1005
+ Santiago
1006
+ Jordan
1007
+ Cooper
1008
+ Brayden
1009
+ Roman
1010
+ Evan
1011
+ Ezekiel
1012
+ Xaviar
1013
+ Jose
1014
+ Jace
1015
+ Jameson
1016
+ Leonardo
1017
+ Axel
1018
+ Everett
1019
+ Kayden
1020
+ Miles
1021
+ Sawyer
1022
+ Jason
1023
+ Emma
1024
+ Olivia
1025
+ Ava
1026
+ Isabella
1027
+ Sophia
1028
+ Charlotte
1029
+ Mia
1030
+ Amelia
1031
+ Harper
1032
+ Evelyn
1033
+ Abigail
1034
+ Emily
1035
+ Elizabeth
1036
+ Mila
1037
+ Ella
1038
+ Avery
1039
+ Sofia
1040
+ Camila
1041
+ Aria
1042
+ Scarlett
1043
+ Victoria
1044
+ Madison
1045
+ Luna
1046
+ Grace
1047
+ Chloe
1048
+ Penelope
1049
+ Layla
1050
+ Riley
1051
+ Zoey
1052
+ Nora
1053
+ Lily
1054
+ Eleanor
1055
+ Hannah
1056
+ Lillian
1057
+ Addison
1058
+ Aubrey
1059
+ Ellie
1060
+ Stella
1061
+ Natalie
1062
+ Zoe
1063
+ Leah
1064
+ Hazel
1065
+ Violet
1066
+ Aurora
1067
+ Savannah
1068
+ Audrey
1069
+ Brooklyn
1070
+ Bella
1071
+ Claire
1072
+ Skylar
1073
+ Lucy
1074
+ Paisley
1075
+ Everly
1076
+ Anna
1077
+ Caroline
1078
+ Nova
1079
+ Genesis
1080
+ Emilia
1081
+ Kennedy
1082
+ Samantha
1083
+ Maya
1084
+ Willow
1085
+ Kinsley
1086
+ Naomi
1087
+ Aaliyah
1088
+ Elena
1089
+ Sarah
1090
+ Ariana
1091
+ Allison
1092
+ Gabriella
1093
+ Alice
1094
+ Madelyn
1095
+ Cora
1096
+ Ruby
1097
+ Eva
1098
+ Serenity
1099
+ Autumn
1100
+ Adeline
1101
+ Hailey
1102
+ Gianna
1103
+ Valentina
1104
+ Isla
1105
+ Eliana
1106
+ Quinn
1107
+ Nevaeh
1108
+ Ivy
1109
+ Sadie
1110
+ Piper
1111
+ Lydia
1112
+ Alexa
1113
+ Josephine
1114
+ Emery
1115
+ Julia
1116
+ Delilah
1117
+ Arianna
1118
+ Vivian
1119
+ Kaylee
1120
+ Sophie
1121
+ Brielle
1122
+ Madeline
1123
+ ]
1124
+ NAMES_LAST = %w[
1125
+ Smith
1126
+ Johnson
1127
+ Williams
1128
+ Brown
1129
+ Jones
1130
+ Miller
1131
+ Davis
1132
+ Wilson
1133
+ Anderson
1134
+ Taylor
1135
+ ]
1136
+ def initialize(contacts = nil)
1137
+ @contacts = contacts || 1000.times.map do |n|
1138
+ random_first_name_index = (rand*NAMES_FIRST.size).to_i
1139
+ random_last_name_index = (rand*NAMES_LAST.size).to_i
1140
+ first_name = NAMES_FIRST[random_first_name_index]
1141
+ last_name = NAMES_LAST[random_last_name_index]
1142
+ email = "#{first_name}@#{last_name}.com".downcase
1143
+ Contact.new(
1144
+ first_name: first_name,
1145
+ last_name: last_name,
1146
+ email: email
1147
+ )
1148
+ end
1149
+ end
1150
+
1151
+ def find(attribute_filter_map)
1152
+ @contacts.find_all do |contact|
1153
+ match = true
1154
+ attribute_filter_map.keys.each do |attribute_name|
1155
+ contact_value = contact.send(attribute_name).downcase
1156
+ filter_value = attribute_filter_map[attribute_name].downcase
1157
+ match = false unless contact_value.match(filter_value)
1158
+ end
1159
+ match
1160
+ end
1161
+ end
1162
+ end
1163
+ end
1164
+
1165
+ class ContactManager
1166
+ class ContactManagerPresenter
1167
+ attr_accessor :results
1168
+ @@contact_attributes = [:first_name, :last_name, :email]
1169
+ @@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
1170
+
1171
+ def initialize(contact_repository = nil)
1172
+ @contact_repository = contact_repository || ContactRepository.new
1173
+ @results = []
1174
+ end
1175
+
1176
+ def list
1177
+ self.results = @contact_repository.find({})
1178
+ end
1179
+
1180
+ def find
1181
+ filter_map = {}
1182
+ @@contact_attributes.each do |attribute_name|
1183
+ filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
1184
+ end
1185
+ self.results = @contact_repository.find(filter_map)
1186
+ @sort_attribute_name = nil
1187
+ @sort_direction_ascending = nil
1188
+ end
1189
+
1190
+ def toggle_sort(attribute_name)
1191
+ @sort_attribute_name = attribute_name
1192
+ @sort_direction_ascending = !@sort_direction_ascending
1193
+ sorted_results = self.results.sort_by {|contact| contact.send(attribute_name).downcase}
1194
+ sorted_results = sorted_results.reverse unless @sort_direction_ascending
1195
+ self.results = sorted_results
1196
+ end
1197
+ end
1198
+ end
1199
+
1200
+ class ContactManager
1201
+ include Glimmer
1202
+
1203
+ def initialize
1204
+ @contact_manager_presenter = ContactManagerPresenter.new
1205
+ @contact_manager_presenter.list
1206
+ end
1207
+
1208
+ def launch
1209
+ shell {
1210
+ text "Contact Manager"
1211
+ composite {
1212
+ composite {
1213
+ grid_layout 2, false
1214
+ label {text "First &Name: "}
1215
+ text {
1216
+ text bind(@contact_manager_presenter, :first_name)
1217
+ on_key_pressed {|key_event|
1218
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
1219
+ }
1220
+ }
1221
+ label {text "&Last Name: "}
1222
+ text {
1223
+ text bind(@contact_manager_presenter, :last_name)
1224
+ on_key_pressed {|key_event|
1225
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
1226
+ }
1227
+ }
1228
+ label {text "&Email: "}
1229
+ text {
1230
+ text bind(@contact_manager_presenter, :email)
1231
+ on_key_pressed {|key_event|
1232
+ @contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
1233
+ }
1234
+ }
1235
+ composite {
1236
+ grid_layout 2, false
1237
+ button {
1238
+ text "&Find"
1239
+ on_widget_selected {
1240
+ @contact_manager_presenter.find
1241
+ }
1242
+ }
1243
+ button {
1244
+ text "&List All"
1245
+ on_widget_selected {
1246
+ @contact_manager_presenter.list
1247
+ }
1248
+ }
1249
+ }
1250
+ }
1251
+
1252
+ table(:multi) { |table_proxy|
1253
+ layout_data {
1254
+ horizontal_alignment :fill
1255
+ vertical_alignment :fill
1256
+ grab_excess_horizontal_space true
1257
+ grab_excess_vertical_space true
1258
+ height_hint 200
1259
+ }
1260
+ table_column {
1261
+ text "First Name"
1262
+ width 80
1263
+ on_widget_selected {
1264
+ @contact_manager_presenter.toggle_sort(:first_name)
1265
+ }
1266
+ }
1267
+ table_column {
1268
+ text "Last Name"
1269
+ width 80
1270
+ on_widget_selected {
1271
+ @contact_manager_presenter.toggle_sort(:last_name)
1272
+ }
1273
+ }
1274
+ table_column {
1275
+ text "Email"
1276
+ width 200
1277
+ on_widget_selected {
1278
+ @contact_manager_presenter.toggle_sort(:email)
1279
+ }
1280
+ }
1281
+ items bind(@contact_manager_presenter, :results), column_properties(:first_name, :last_name, :email)
1282
+ on_mouse_down { |event|
1283
+ table_proxy.edit_table_item(event.table_item, event.column_index)
1284
+ }
1285
+ }
1286
+ }
1287
+ }.open
1288
+ end
1289
+ end
1290
+
1291
+ ContactManager.new.launch
1292
+
1293
+ ```
1294
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
1295
+
1296
+ Glimmer DSL for SWT Contact Manager
1297
+
1298
+ ![Glimmer DSL for SWT Contact Manager](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-contact-manager.png)
1299
+
1300
+ Glimmer DSL for SWT Contact Manager Find
1301
+
1302
+ ![Glimmer DSL for SWT Contact Manager Find](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-contact-manager-find.png)
1303
+
1304
+ Glimmer DSL for SWT Contact Manager Edit Started
1305
+
1306
+ ![Glimmer DSL for SWT Contact Manager Edit Started](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-contact-manager-edit-started.png)
1307
+
1308
+ Glimmer DSL for SWT Contact Manager Edit In Progress
1309
+
1310
+ ![Glimmer DSL for SWT Contact Manager Edit In Progress](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-contact-manager-edit-in-progress.png)
1311
+
1312
+ Glimmer DSL for SWT Contact Manager Edit Done
1313
+
1314
+ ![Glimmer DSL for SWT Contact Manager Edit Done](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-contact-manager-edit-done.png)
1315
+
1316
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
1317
+
1318
+ Start the Rails server:
1319
+ ```
1320
+ rails s
1321
+ ```
1322
+
1323
+ Visit `http://localhost:3000`
1324
+
1325
+ You should see "Tic Tac Toe"
1326
+
1327
+ Glimmer DSL for Opal Contact Manager
1328
+
1329
+ ![Glimmer DSL for Opal Contact Manager](images/glimmer-dsl-opal-contact-manager.png)
1330
+
1331
+ Glimmer DSL for Opal Contact Manager Find
1332
+
1333
+ ![Glimmer DSL for Opal Contact Manager Find](images/glimmer-dsl-opal-contact-manager-find.png)
1334
+
1335
+ Glimmer DSL for Opal Contact Manager Edit Started
1336
+
1337
+ ![Glimmer DSL for Opal Contact Manager Edit Started](images/glimmer-dsl-opal-contact-manager-edit-started.png)
1338
+
1339
+ Glimmer DSL for Opal Contact Manager Edit In Progress
1340
+
1341
+ ![Glimmer DSL for Opal Contact Manager Edit In Progress](images/glimmer-dsl-opal-contact-manager-edit-in-progress.png)
1342
+
1343
+ Glimmer DSL for Opal Contact Manager Edit Done
1344
+
1345
+ ![Glimmer DSL for Opal Contact Manager Edit Done](images/glimmer-dsl-opal-contact-manager-edit-done.png)
1346
+
398
1347
  ## Help
399
1348
 
400
1349
  ### Issues