glimmer-dsl-opal 0.0.3 → 0.0.8

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