glimmer-dsl-opal 0.0.3 → 0.0.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +1049 -35
- data/VERSION +1 -1
- data/lib/glimmer-dsl-opal.rb +5 -2
- data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
- data/lib/glimmer/data_binding/list_selection_binding.rb +51 -0
- data/lib/glimmer/data_binding/table_items_binding.rb +67 -0
- data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
- data/lib/glimmer/dsl/opal/dsl.rb +14 -0
- data/lib/glimmer/dsl/opal/list_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +42 -0
- data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
- data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
- data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/table_column_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/table_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
- data/lib/glimmer/opal/display_proxy.rb +23 -0
- data/lib/glimmer/opal/div_proxy.rb +11 -2
- data/lib/glimmer/opal/document_proxy.rb +141 -11
- data/lib/glimmer/opal/element_proxy.rb +38 -15
- data/lib/glimmer/opal/grid_layout_proxy.rb +3 -1
- data/lib/glimmer/opal/iframe_proxy.rb +23 -0
- data/lib/glimmer/opal/input_proxy.rb +8 -4
- data/lib/glimmer/opal/label_proxy.rb +1 -1
- data/lib/glimmer/opal/layout_data_proxy.rb +23 -2
- data/lib/glimmer/opal/list_proxy.rb +80 -0
- data/lib/glimmer/opal/modal.rb +94 -0
- data/lib/glimmer/opal/point.rb +5 -0
- data/lib/glimmer/opal/select_proxy.rb +1 -1
- data/lib/glimmer/opal/tab_folder.rb +53 -0
- data/lib/glimmer/opal/tab_item.rb +98 -0
- data/lib/glimmer/opal/table_column.rb +50 -0
- data/lib/glimmer/opal/table_item.rb +136 -0
- data/lib/glimmer/opal/table_proxy.rb +149 -0
- data/lib/samples/elaborate/contact_manager.rb +1 -2
- data/lib/samples/elaborate/login.rb +0 -1
- data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
- data/lib/samples/hello/hello_tab.rb +2 -2
- metadata +30 -14
- data/lib/glimmer/config.rb +0 -22
- data/lib/glimmer/dsl/engine.rb +0 -193
- data/lib/glimmer/dsl/expression.rb +0 -42
- data/lib/glimmer/dsl/expression_handler.rb +0 -48
- data/lib/glimmer/dsl/parent_expression.rb +0 -12
- data/lib/glimmer/dsl/static_expression.rb +0 -36
- data/lib/glimmer/dsl/top_level_expression.rb +0 -7
- data/lib/glimmer/error.rb +0 -6
- data/lib/glimmer/invalid_keyword_error.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a67315f8276add7f19a24f488c635567a39fe798e7e21e49ce23de2aeb6c0d2
|
4
|
+
data.tar.gz: e667498792a2522e9271a04ccd2051396c778e528dd77fbb593c6369eee971e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02db0846e7e3b430387e693aa4981c2f01636a01b5ed5ba32646cbdac15991604ccbd5efa4d8e8b837027c69861c28b8d1917f5bef792121de9be8b86584e064
|
7
|
+
data.tar.gz: 5d07f4b44c97c81bcf554b18d423e0007efe14bf8cdaa8529f0c295581518654a94989dcc1a0e921e8626a7ca3ca243f572a4d163f3e4bd450fe81684303dae2
|
data/CHANGELOG.md
CHANGED
@@ -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
|
[](http://badge.fury.io/rb/glimmer-dsl-opal)
|
4
3
|
[](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
4
|
|
6
|
-
|
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/)
|
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.
|
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
|
-
|
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
|
64
|
+
rails new glimmer_app
|
46
65
|
```
|
47
66
|
|
48
|
-
|
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-
|
54
|
-
gem '
|
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
|
-
|
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
|
-
|
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
|
-

|
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
|

|
97
126
|
|
98
|
-
|
127
|
+
#### Hello, Combo!
|
99
128
|
|
100
|
-
Add the following Glimmer code to `app/assets/javascripts/application.
|
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
|
-

|
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
|

|
156
183
|
|
157
|
-
|
184
|
+
#### Hello, Computed!
|
158
185
|
|
159
|
-
Add the following Glimmer code to `app/assets/javascripts/application.
|
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
|
-

|
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
|

|
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
|
+

|
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
|
+

|
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
|
+

|
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
|
+

|
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
|
+

|
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
|
+

|
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
|
+

|
484
|
+

|
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
|
+

|
498
|
+

|
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
|
+

|
598
|
+

|
599
|
+

|
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
|
+

|
613
|
+

|
614
|
+

|
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
|
+

|
827
|
+

|
828
|
+

|
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
|
+

|
842
|
+

|
843
|
+

|
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
|
+

|
1239
|
+
|
1240
|
+
Glimmer DSL for SWT Contact Manager Find
|
1241
|
+
|
1242
|
+

|
1243
|
+
|
1244
|
+
Glimmer DSL for SWT Contact Manager Edit Started
|
1245
|
+
|
1246
|
+

|
1247
|
+
|
1248
|
+
Glimmer DSL for SWT Contact Manager Edit In Progress
|
1249
|
+
|
1250
|
+

|
1251
|
+
|
1252
|
+
Glimmer DSL for SWT Contact Manager Edit Done
|
1253
|
+
|
1254
|
+

|
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
|
+

|
1270
|
+
|
1271
|
+
Glimmer DSL for Opal Contact Manager Find
|
1272
|
+
|
1273
|
+

|
1274
|
+
|
1275
|
+
Glimmer DSL for Opal Contact Manager Edit Started
|
1276
|
+
|
1277
|
+

|
1278
|
+
|
1279
|
+
Glimmer DSL for Opal Contact Manager Edit In Progress
|
1280
|
+
|
1281
|
+

|
1282
|
+
|
1283
|
+
Glimmer DSL for Opal Contact Manager Edit Done
|
1284
|
+
|
1285
|
+

|
1286
|
+
|
273
1287
|
## Help
|
274
1288
|
|
275
1289
|
### Issues
|