glimmer-dsl-opal 0.13.0 → 0.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +180 -1269
- data/VERSION +1 -1
- data/app/controllers/glimmer/application_controller.rb +4 -0
- data/app/controllers/glimmer/image_paths_controller.rb +46 -0
- data/app/views/glimmer/image_paths/index.html.erb +1 -0
- data/{lib/glimmer-dsl-opal/samples/hello/hello_computed/contact.rb → config/routes.rb} +2 -20
- data/lib/glimmer-dsl-opal.rb +8 -2
- data/lib/glimmer-dsl-opal/ext/file.rb +25 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/weather.rb +157 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_button.rb +7 -7
- data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +24 -22
- data/lib/glimmer-dsl-opal/samples/hello/hello_composite.rb +69 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_computed.rb +27 -9
- data/lib/glimmer-dsl-opal/samples/hello/hello_table.rb +28 -20
- data/lib/glimmer-dsl-opal/samples/hello/hello_table/baseball_park.png +0 -0
- data/lib/glimmer/config.rb +11 -0
- data/lib/glimmer/engine.rb +21 -0
- data/lib/glimmer/swt/composite_proxy.rb +34 -0
- data/lib/glimmer/swt/grid_layout_proxy.rb +11 -27
- data/lib/glimmer/swt/label_proxy.rb +15 -2
- data/lib/glimmer/swt/layout_data_proxy.rb +1 -1
- data/lib/glimmer/swt/shell_proxy.rb +43 -0
- data/lib/glimmer/swt/table_item_proxy.rb +3 -0
- data/lib/net/http.rb +15 -6
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2ee052273513ff79b9d9ef0f351f30bfa0c4083f589429646b894b132afa4c3
|
4
|
+
data.tar.gz: f2a9113b2a92168046d19c3068d9b62df1000fdc1dd6c9ea5f168ffb89123fb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20edcc6d97dbee21a5b8b332bc649fb0f7d77f93e41d02095cdbbed43f0686f8c1dd5bf08972bd21511cb983f77caf247f61136ddde5de859f444ac92f31dbf2
|
7
|
+
data.tar.gz: ce7347775105f4b2af132cd68b4a805332b4afe910cb3ff91c0da083bd043e93cf067c693c9e4a54b506c2417d684248d23fa78aecccc264c741c38028b35b6e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.16.1
|
4
|
+
|
5
|
+
- Support GridLayout make_columns_equal_width, horizontal_spacing, and vertical_spacing attributes
|
6
|
+
- Hello, Composite! sample
|
7
|
+
|
8
|
+
## 0.16.0
|
9
|
+
|
10
|
+
- Support label widget background_image attribute
|
11
|
+
- Have File.expand_path support expanding paths even if they did not base off of __dir__ or __FILE__
|
12
|
+
- Custom specification of gems having image paths via server-side configuration in Glimmer::Config.gems_having_image_paths
|
13
|
+
|
14
|
+
## 0.15.1
|
15
|
+
|
16
|
+
- Auto-expose images of gems that depend on glimmer-dsl-opal as downloadable asset links providing `/glimmer/image_paths` server call to obtain them
|
17
|
+
- Update Hello, Table! to work with image background
|
18
|
+
|
19
|
+
## 0.14.0
|
20
|
+
|
21
|
+
- Initial Net::HTTP support for get and post_form
|
22
|
+
- Added "Weather" elaborate sample (minus multi-threaded refetches)
|
23
|
+
- Updated Hello, Button!, Hello, Combo!, and Hello, Computed! from Glimmer DSL for SWT
|
24
|
+
|
3
25
|
## 0.13.0
|
4
26
|
|
5
27
|
- Support Shine data-binding syntax in custom widgets
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Opal 0.
|
1
|
+
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Opal 0.16.0 (Pure Ruby Web GUI)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-opal.svg)](http://badge.fury.io/rb/glimmer-dsl-opal)
|
3
3
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
4
4
|
|
@@ -8,12 +8,14 @@
|
|
8
8
|
|
9
9
|
Use in one of two ways:
|
10
10
|
- **Direct:** build the GUI of web apps with the same friendly desktop GUI Ruby syntax as [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt), thus requiring a lot less code than web technologies that is in pure Ruby and avoiding opaque web concepts like 'render' and 'reactive'. No HTML/JS/CSS skills are even required. Web designers may be involved with CSS styling only if needed.
|
11
|
-
- **Adapter:** auto-webify [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)) via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/) without changing a line of code. Just insert them as a single require statement in a Rails app, and BOOM! They're running on the web! Apps may then optionally be custom-styled for the web by web designers with standard CSS if needed.
|
11
|
+
- **Adapter:** auto-webify [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)) via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/) without changing a line of GUI code. Just insert them as a single require statement in a Rails app, and BOOM! They're running on the web! Apps may then optionally be custom-styled for the web by web designers with standard CSS if needed.
|
12
12
|
|
13
13
|
Glimmer DSL for Opal successfully reuses the entire [Glimmer](https://github.com/AndyObtiva/glimmer) core DSL engine in [Opal Ruby](https://opalrb.com/) inside a web browser, and as such inherits the full range of Glimmer desktop [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities for the web (including Shine syntax using `<=>` and `<=` for bidirectional [two-way] and unidirectional [one-way] data-binding respectively).
|
14
14
|
|
15
15
|
#### Hello, Table! Sample
|
16
16
|
|
17
|
+
Code: [lib/glimmer-dsl-opal/samples/hello/hello_table.rb](lib/glimmer-dsl-opal/samples/hello/hello_table.rb)
|
18
|
+
|
17
19
|
Glimmer GUI code from [glimmer-dsl-opal/samples/hello/hello_table.rb](lib/glimmer-dsl-opal/samples/hello/hello_table.rb):
|
18
20
|
|
19
21
|
```ruby
|
@@ -103,7 +105,7 @@ shell {
|
|
103
105
|
|
104
106
|
![Glimmer DSL for SWT Hello Table](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-table.png)
|
105
107
|
|
106
|
-
**Hello, Table! (same code) running on the web via Opal on Rails (using the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem):**
|
108
|
+
**Hello, Table! (same GUI code) running on the web via Opal on Rails (using the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem):**
|
107
109
|
|
108
110
|
![Glimmer DSL for Opal Hello Table](images/glimmer-dsl-opal-hello-table.png)
|
109
111
|
|
@@ -141,7 +143,7 @@ Hello, Table! Game Booked
|
|
141
143
|
|
142
144
|
NOTE: Glimmer DSL for Opal is an alpha project. Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
|
143
145
|
|
144
|
-
**Alpha Version** 0.
|
146
|
+
**Alpha Version** 0.16.0 only supports bare-minimum capabilities for the included [samples](https://github.com/AndyObtiva/glimmer-dsl-opal#samples) (originally written for [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt))
|
145
147
|
|
146
148
|
Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
147
149
|
- [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
|
@@ -151,7 +153,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
151
153
|
|
152
154
|
## Table of Contents
|
153
155
|
|
154
|
-
- [Glimmer DSL for Opal 0.
|
156
|
+
- [Glimmer DSL for Opal 0.16.0 (Pure Ruby Web GUI)](#-glimmer-dsl-for-opal-0160-pure-ruby-web-gui)
|
155
157
|
- [Principles](#principles)
|
156
158
|
- [Background](#background)
|
157
159
|
- [Pre-requisites](#pre-requisites)
|
@@ -161,6 +163,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
161
163
|
- [Hello Samples](#hello-samples)
|
162
164
|
- [Hello, World!](#hello-world)
|
163
165
|
- [Hello, Combo!](#hello-combo)
|
166
|
+
- [Hello, Composite!](#hello-composite)
|
164
167
|
- [Hello, Computed!](#hello-computed)
|
165
168
|
- [Hello, List Single Selection!](#hello-list-single-selection)
|
166
169
|
- [Hello, List Multi Selection!](#hello-list-multi-selection)
|
@@ -184,6 +187,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
184
187
|
- [Login](#login)
|
185
188
|
- [Tic Tac Toe](#tic-tac-toe)
|
186
189
|
- [Contact Manager](#contact-manager)
|
190
|
+
- [Weather](#weather)
|
187
191
|
- [External Samples](#external-samples)
|
188
192
|
- [Glimmer Calculator](#glimmer-calculator)
|
189
193
|
- [Glimmer Supporting Libraries](#glimmer-supporting-libraries)
|
@@ -205,7 +209,6 @@ Please keep in mind this is a live list of innovative ideas, some of which have
|
|
205
209
|
- **HTML is for creating documents not interactive applications**. As such, software engineers can avoid it and focus on creating web applications more productively with Glimmer DSL for Opal in pure Ruby instead (just like they do in desktop development) while content creators and web designers can be the ones responsible for creating HTML documents for web content purposes only as HTML was originally intended. That way, Glimmer web GUI is used and embedded in web pages when providing users with applications while the rest of the web pages are maintained by non-engineers as pure HTML. This achieves a correct separation of responsibilities and better productivity and maintainability.
|
206
210
|
- **Approximate styles by developers via the Glimmer GUI DSL. Perfect styles by designers via pure CSS**. Developers can simply build GUI with approximate styling similar to desktop GUI and mockups without worrying about pixel-perfect aesthetics. Web designers can take styling further with pure CSS since every HTML element auto-generated by Glimmer DSL for Opal has a predictable ID and CSS class. This achieves a proper separation of responsibilities between developers and designers.
|
207
211
|
- **Web servers are used just like servers in traditional client/server architecture**, meaning they simply provide RMI services to enable centralizing some of the application logic and data in the cloud to make available everywhere and enable data-sharing with others.
|
208
|
-
- **Everybody In!** All JS frameworks sadly suffer from very major software design handicaps because of trying to ensure data security, so you end up with a very strict separation between server data and client data, making your head spin and worrying more about hackers and attackers than serving users. Try again! Thanks to the principle of Everybody In, Glimmer DSL for Opal apps have a very unique software architecture that revolves around the idea of multi-tenancy. Basically, every user gets their own server-side real-estate, that is a fully-secure-and-independent server-side instance that has its own user database, so hackers are not only intentionally allowed in, they are WELCOMED! As such, instead of protecting all users' data with an iron fist over a shared server/database (a terribly insecure architecture no matter how profilerate), you simply provide each user their own fully-independent server/client real-estate, thus be able to focus on serving them in the best way possible by writing code that is so simple it is just like desktop application code, but living in the Cloud on the Web. In summary, just code web as if you're on the desktop and be happy!
|
209
212
|
- **Forget Routers!** Glimmer DSL for Opal supports auto-routing of custom shells (windows), which are opened as separate tabs in a web browser with automatically generated routes and bookmarkable URLs.
|
210
213
|
|
211
214
|
## Background
|
@@ -221,7 +224,8 @@ Alternatively, web developers may directly use [Glimmer DSL for Opal](https://ru
|
|
221
224
|
## Pre-requisites
|
222
225
|
|
223
226
|
- Rails 5: [https://github.com/rails/rails/tree/5-2-stable](https://github.com/rails/rails/tree/5-2-stable)
|
224
|
-
- Opal 1: [https://github.com/opal/opal
|
227
|
+
- Opal 1.0.4: [https://github.com/opal/opal](https://github.com/opal/opal)
|
228
|
+
- Opal-Rails 1.1.2: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
|
225
229
|
- jQuery 3: [https://code.jquery.com/](https://code.jquery.com/) (jQuery 3.5.1 is included in the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem)
|
226
230
|
- jQuery-UI 1.12: [https://code.jquery.com/](https://jqueryui.com/) (jQuery-UI 1.12.1 is included in the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem)
|
227
231
|
- jQuery-UI Timepicker 0.3: [https://code.jquery.com/](https://fgelinas.com/code/timepicker/) (jQuery-UI Timepicker 0.3.3 is included in the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem)
|
@@ -249,10 +253,11 @@ rails new glimmer_app_server
|
|
249
253
|
Add the following to `Gemfile`:
|
250
254
|
|
251
255
|
```
|
252
|
-
gem 'opal
|
256
|
+
gem 'opal', '1.0.4'
|
257
|
+
gem 'opal-rails', '1.1.2'
|
253
258
|
gem 'opal-async', '~> 1.2.0'
|
254
259
|
gem 'opal-jquery', '~> 0.4.4'
|
255
|
-
gem 'glimmer-dsl-opal', '~> 0.
|
260
|
+
gem 'glimmer-dsl-opal', '~> 0.16.0'
|
256
261
|
gem 'glimmer-dsl-xml', '~> 1.2.0', require: false
|
257
262
|
gem 'glimmer-dsl-css', '~> 1.2.0', require: false
|
258
263
|
|
@@ -441,52 +446,54 @@ require 'glimmer-dsl-opal/samples/hello/hello_combo'
|
|
441
446
|
Or add the Glimmer code directly if you prefer to play around with it:
|
442
447
|
|
443
448
|
```ruby
|
444
|
-
class
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
449
|
+
class HelloCombo
|
450
|
+
class Person
|
451
|
+
attr_accessor :country, :country_options
|
452
|
+
|
453
|
+
def initialize
|
454
|
+
self.country_options = ['', 'Canada', 'US', 'Mexico']
|
455
|
+
reset_country!
|
456
|
+
end
|
457
|
+
|
458
|
+
def reset_country!
|
459
|
+
self.country = 'Canada'
|
460
|
+
end
|
454
461
|
end
|
455
|
-
end
|
456
462
|
|
457
|
-
|
458
|
-
include Glimmer
|
463
|
+
include Glimmer::UI::CustomShell
|
459
464
|
|
460
|
-
|
461
|
-
person = Person.new
|
462
|
-
|
465
|
+
before_body {
|
466
|
+
@person = Person.new
|
467
|
+
}
|
468
|
+
|
469
|
+
body {
|
463
470
|
shell {
|
464
471
|
row_layout(:vertical) {
|
465
|
-
|
472
|
+
fill true
|
466
473
|
}
|
467
474
|
|
468
475
|
text 'Hello, Combo!'
|
469
476
|
|
470
477
|
combo(:read_only) {
|
471
|
-
selection <=> [person, :country]
|
478
|
+
selection <=> [@person, :country] # also binds to country_options by convention
|
472
479
|
}
|
473
480
|
|
474
481
|
button {
|
475
482
|
text 'Reset Selection'
|
476
483
|
|
477
484
|
on_widget_selected do
|
478
|
-
person.reset_country
|
485
|
+
@person.reset_country!
|
479
486
|
end
|
480
487
|
}
|
481
|
-
}
|
482
|
-
|
488
|
+
}
|
489
|
+
}
|
483
490
|
end
|
484
491
|
|
485
|
-
HelloCombo.
|
492
|
+
HelloCombo.launch
|
486
493
|
```
|
487
494
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
488
495
|
|
489
|
-
![Glimmer DSL for SWT Hello Combo](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-combo.png)
|
496
|
+
![Glimmer DSL for SWT Hello Combo](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/images/glimmer-hello-combo.png)
|
490
497
|
|
491
498
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
492
499
|
|
@@ -501,6 +508,31 @@ You should see "Hello, Combo!"
|
|
501
508
|
|
502
509
|
![Glimmer DSL for Opal Hello Combo](images/glimmer-dsl-opal-hello-combo.png)
|
503
510
|
|
511
|
+
#### Hello, Composite!
|
512
|
+
|
513
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
514
|
+
|
515
|
+
```ruby
|
516
|
+
require 'glimmer-dsl-opal/samples/hello/hello_composite'
|
517
|
+
```
|
518
|
+
|
519
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
520
|
+
|
521
|
+
![Glimmer DSL for SWT Hello Composite](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/images/glimmer-hello-composite.png)
|
522
|
+
|
523
|
+
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
524
|
+
|
525
|
+
Start the Rails server:
|
526
|
+
```
|
527
|
+
rails s
|
528
|
+
```
|
529
|
+
|
530
|
+
Visit `http://localhost:3000`
|
531
|
+
|
532
|
+
You should see "Hello, Composite!"
|
533
|
+
|
534
|
+
![Glimmer DSL for Opal Hello Composite](images/glimmer-dsl-opal-hello-composite.png)
|
535
|
+
|
504
536
|
#### Hello, Computed!
|
505
537
|
|
506
538
|
Add the following require statement to `app/assets/javascripts/application.rb`
|
@@ -534,17 +566,17 @@ class HelloComputed
|
|
534
566
|
end
|
535
567
|
end
|
536
568
|
|
537
|
-
include Glimmer
|
569
|
+
include Glimmer::UI::CustomShell
|
538
570
|
|
539
|
-
|
571
|
+
before_body {
|
540
572
|
@contact = Contact.new(
|
541
573
|
first_name: 'Barry',
|
542
574
|
last_name: 'McKibbin',
|
543
575
|
year_of_birth: 1985
|
544
576
|
)
|
545
|
-
|
577
|
+
}
|
546
578
|
|
547
|
-
|
579
|
+
body {
|
548
580
|
shell {
|
549
581
|
text 'Hello, Computed!'
|
550
582
|
|
@@ -601,11 +633,11 @@ class HelloComputed
|
|
601
633
|
}
|
602
634
|
}
|
603
635
|
}
|
604
|
-
}
|
605
|
-
|
636
|
+
}
|
637
|
+
}
|
606
638
|
end
|
607
639
|
|
608
|
-
HelloComputed.
|
640
|
+
HelloComputed.launch
|
609
641
|
```
|
610
642
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
611
643
|
|
@@ -633,44 +665,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
633
665
|
require 'glimmer-dsl-opal/samples/hello/hello_list_single_selection'
|
634
666
|
```
|
635
667
|
|
636
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
637
|
-
|
638
|
-
```ruby
|
639
|
-
class Person
|
640
|
-
attr_accessor :country, :country_options
|
641
|
-
|
642
|
-
def initialize
|
643
|
-
self.country_options=["", "Canada", "US", "Mexico"]
|
644
|
-
self.country = "Canada"
|
645
|
-
end
|
646
|
-
|
647
|
-
def reset_country
|
648
|
-
self.country = "Canada"
|
649
|
-
end
|
650
|
-
end
|
651
|
-
|
652
|
-
class HelloListSingleSelection
|
653
|
-
include Glimmer
|
654
|
-
def launch
|
655
|
-
person = Person.new
|
656
|
-
shell {
|
657
|
-
composite {
|
658
|
-
list {
|
659
|
-
selection bind(person, :country)
|
660
|
-
}
|
661
|
-
button {
|
662
|
-
text "Reset"
|
663
|
-
on_widget_selected do
|
664
|
-
person.reset_country
|
665
|
-
end
|
666
|
-
}
|
667
|
-
}
|
668
|
-
}.open
|
669
|
-
end
|
670
|
-
end
|
671
|
-
|
672
|
-
HelloListSingleSelection.new.launch
|
673
|
-
```
|
674
668
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
675
669
|
|
676
670
|
![Glimmer DSL for SWT Hello List Single Selection](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-list-single-selection.png)
|
@@ -696,63 +690,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
696
690
|
require 'glimmer-dsl-opal/samples/hello/hello_list_multi_selection'
|
697
691
|
```
|
698
692
|
|
699
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
700
|
-
|
701
|
-
```ruby
|
702
|
-
class HelloListMultiSelection
|
703
|
-
class Person
|
704
|
-
attr_accessor :provinces, :provinces_options
|
705
|
-
|
706
|
-
def initialize
|
707
|
-
self.provinces_options = [
|
708
|
-
'',
|
709
|
-
'Alberta',
|
710
|
-
'British Columbia',
|
711
|
-
'Manitoba',
|
712
|
-
'New Brunswick',
|
713
|
-
'Newfoundland and Labrador',
|
714
|
-
'Northwest Territories',
|
715
|
-
'Nova Scotia',
|
716
|
-
'Nunavut',
|
717
|
-
'Ontario',
|
718
|
-
'Prince Edward Island',
|
719
|
-
'Quebec',
|
720
|
-
'Saskatchewan',
|
721
|
-
'Yukon'
|
722
|
-
]
|
723
|
-
reset_provinces
|
724
|
-
end
|
725
|
-
|
726
|
-
def reset_provinces
|
727
|
-
self.provinces = ['Quebec', 'Manitoba', 'Alberta']
|
728
|
-
end
|
729
|
-
end
|
730
|
-
|
731
|
-
include Glimmer
|
732
|
-
|
733
|
-
def launch
|
734
|
-
person = Person.new
|
735
|
-
|
736
|
-
shell {
|
737
|
-
grid_layout
|
738
|
-
|
739
|
-
text 'Hello, List Multi Selection!'
|
740
|
-
|
741
|
-
list(:multi) {
|
742
|
-
selection bind(person, :provinces)
|
743
|
-
}
|
744
|
-
|
745
|
-
button {
|
746
|
-
text 'Reset Selections To Default Values'
|
747
|
-
|
748
|
-
on_widget_selected { person.reset_provinces }
|
749
|
-
}
|
750
|
-
}.open
|
751
|
-
end
|
752
|
-
end
|
753
|
-
|
754
|
-
HelloListMultiSelection.new.launch
|
755
|
-
```
|
756
693
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
757
694
|
|
758
695
|
![Glimmer DSL for SWT Hello List Multi Selection](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-list-multi-selection.png)
|
@@ -778,18 +715,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
778
715
|
require 'glimmer-dsl-opal/samples/hello/hello_browser'
|
779
716
|
```
|
780
717
|
|
781
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
782
|
-
|
783
|
-
```ruby
|
784
|
-
include Glimmer
|
785
|
-
|
786
|
-
shell {
|
787
|
-
minimum_size 1024, 860
|
788
|
-
browser {
|
789
|
-
url 'http://brightonresort.com/about'
|
790
|
-
}
|
791
|
-
}.open
|
792
|
-
```
|
793
718
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
794
719
|
|
795
720
|
![Glimmer DSL for SWT Hello Browser](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-browser.png)
|
@@ -894,7 +819,7 @@ class GreetingLabel
|
|
894
819
|
after_body {
|
895
820
|
return if colors.nil?
|
896
821
|
|
897
|
-
Thread.new {
|
822
|
+
Thread.new { # imported from Glimmer DSL for SWT. In Opal, avoid Threads and sleep to avoid blocking GUI.
|
898
823
|
colors.cycle { |color|
|
899
824
|
async_exec {
|
900
825
|
self.color = color
|
@@ -909,7 +834,7 @@ class GreetingLabel
|
|
909
834
|
label(swt_style) {
|
910
835
|
text "#{greeting}, #{name}!"
|
911
836
|
font @font
|
912
|
-
foreground
|
837
|
+
foreground <=> [self, :color]
|
913
838
|
}
|
914
839
|
}
|
915
840
|
|
@@ -1131,103 +1056,14 @@ You should see "Hello, Custom Widget!"
|
|
1131
1056
|
|
1132
1057
|
#### Hello, Radio!
|
1133
1058
|
|
1059
|
+
This is the low level way of using `radio`
|
1060
|
+
|
1134
1061
|
Add the following require statement to `app/assets/javascripts/application.rb`
|
1135
1062
|
|
1136
1063
|
```ruby
|
1137
1064
|
require 'glimmer-dsl-opal/samples/hello/hello_radio'
|
1138
1065
|
```
|
1139
1066
|
|
1140
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
1141
|
-
|
1142
|
-
```ruby
|
1143
|
-
class HelloRadio
|
1144
|
-
class Person
|
1145
|
-
attr_accessor :male, :female, :child, :teen, :adult, :senior
|
1146
|
-
|
1147
|
-
def initialize
|
1148
|
-
reset
|
1149
|
-
end
|
1150
|
-
|
1151
|
-
def reset
|
1152
|
-
self.male = nil
|
1153
|
-
self.female = nil
|
1154
|
-
self.child = nil
|
1155
|
-
self.teen = nil
|
1156
|
-
self.adult = true
|
1157
|
-
self.senior = nil
|
1158
|
-
end
|
1159
|
-
end
|
1160
|
-
|
1161
|
-
include Glimmer
|
1162
|
-
|
1163
|
-
def launch
|
1164
|
-
person = Person.new
|
1165
|
-
|
1166
|
-
shell {
|
1167
|
-
text 'Hello, Radio!'
|
1168
|
-
row_layout :vertical
|
1169
|
-
|
1170
|
-
label {
|
1171
|
-
text 'Gender:'
|
1172
|
-
font style: :bold
|
1173
|
-
}
|
1174
|
-
|
1175
|
-
composite {
|
1176
|
-
row_layout
|
1177
|
-
|
1178
|
-
radio {
|
1179
|
-
text 'Male'
|
1180
|
-
selection bind(person, :male)
|
1181
|
-
}
|
1182
|
-
|
1183
|
-
radio {
|
1184
|
-
text 'Female'
|
1185
|
-
selection bind(person, :female)
|
1186
|
-
}
|
1187
|
-
}
|
1188
|
-
|
1189
|
-
label {
|
1190
|
-
text 'Age Group:'
|
1191
|
-
font style: :bold
|
1192
|
-
}
|
1193
|
-
|
1194
|
-
composite {
|
1195
|
-
row_layout
|
1196
|
-
|
1197
|
-
radio {
|
1198
|
-
text 'Child'
|
1199
|
-
selection bind(person, :child)
|
1200
|
-
}
|
1201
|
-
|
1202
|
-
radio {
|
1203
|
-
text 'Teen'
|
1204
|
-
selection bind(person, :teen)
|
1205
|
-
}
|
1206
|
-
|
1207
|
-
radio {
|
1208
|
-
text 'Adult'
|
1209
|
-
selection bind(person, :adult)
|
1210
|
-
}
|
1211
|
-
|
1212
|
-
radio {
|
1213
|
-
text 'Senior'
|
1214
|
-
selection bind(person, :senior)
|
1215
|
-
}
|
1216
|
-
}
|
1217
|
-
|
1218
|
-
button {
|
1219
|
-
text 'Reset'
|
1220
|
-
|
1221
|
-
on_widget_selected do
|
1222
|
-
person.reset
|
1223
|
-
end
|
1224
|
-
}
|
1225
|
-
}.open
|
1226
|
-
end
|
1227
|
-
end
|
1228
|
-
|
1229
|
-
HelloRadio.new.launch
|
1230
|
-
```
|
1231
1067
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1232
1068
|
|
1233
1069
|
![Glimmer DSL for SWT Hello Radio](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-radio.png)
|
@@ -1247,6 +1083,8 @@ You should see "Hello, Radio!"
|
|
1247
1083
|
|
1248
1084
|
#### Hello, Radio Group!
|
1249
1085
|
|
1086
|
+
`radio_group` is a level higher than `radio` in abstraction. It generates a group of radio widgets based on available options in model `attribute_options` methods.
|
1087
|
+
|
1250
1088
|
Add the following require statement to `app/assets/javascripts/application.rb`
|
1251
1089
|
|
1252
1090
|
```ruby
|
@@ -1261,7 +1099,7 @@ class HelloRadioGroup
|
|
1261
1099
|
attr_accessor :gender, :age_group
|
1262
1100
|
|
1263
1101
|
def initialize
|
1264
|
-
reset
|
1102
|
+
reset!
|
1265
1103
|
end
|
1266
1104
|
|
1267
1105
|
def gender_options
|
@@ -1272,17 +1110,19 @@ class HelloRadioGroup
|
|
1272
1110
|
['Child', 'Teen', 'Adult', 'Senior']
|
1273
1111
|
end
|
1274
1112
|
|
1275
|
-
def reset
|
1113
|
+
def reset!
|
1276
1114
|
self.gender = nil
|
1277
1115
|
self.age_group = 'Adult'
|
1278
1116
|
end
|
1279
1117
|
end
|
1280
1118
|
|
1281
|
-
include Glimmer
|
1119
|
+
include Glimmer::UI::CustomShell
|
1282
1120
|
|
1283
|
-
|
1284
|
-
person = Person.new
|
1285
|
-
|
1121
|
+
before_body {
|
1122
|
+
@person = Person.new
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
body {
|
1286
1126
|
shell {
|
1287
1127
|
text 'Hello, Radio Group!'
|
1288
1128
|
row_layout :vertical
|
@@ -1294,7 +1134,7 @@ class HelloRadioGroup
|
|
1294
1134
|
|
1295
1135
|
radio_group {
|
1296
1136
|
row_layout :horizontal
|
1297
|
-
selection <=> [person, :gender]
|
1137
|
+
selection <=> [@person, :gender]
|
1298
1138
|
}
|
1299
1139
|
|
1300
1140
|
label {
|
@@ -1304,21 +1144,21 @@ class HelloRadioGroup
|
|
1304
1144
|
|
1305
1145
|
radio_group {
|
1306
1146
|
row_layout :horizontal
|
1307
|
-
selection <=> [person, :age_group]
|
1147
|
+
selection <=> [@person, :age_group]
|
1308
1148
|
}
|
1309
1149
|
|
1310
1150
|
button {
|
1311
1151
|
text 'Reset'
|
1312
1152
|
|
1313
1153
|
on_widget_selected do
|
1314
|
-
person.reset
|
1154
|
+
@person.reset!
|
1315
1155
|
end
|
1316
1156
|
}
|
1317
|
-
}
|
1318
|
-
|
1157
|
+
}
|
1158
|
+
}
|
1319
1159
|
end
|
1320
1160
|
|
1321
|
-
HelloRadioGroup.
|
1161
|
+
HelloRadioGroup.launch
|
1322
1162
|
```
|
1323
1163
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1324
1164
|
|
@@ -1339,99 +1179,14 @@ You should see "Hello, Radio Group!"
|
|
1339
1179
|
|
1340
1180
|
#### Hello, Group!
|
1341
1181
|
|
1182
|
+
Not to be confused with `radio_group` or `checkbox_group`, `group` simply groups arbitrary widgets together and adds a title header above them.
|
1183
|
+
|
1342
1184
|
Add the following require statement to `app/assets/javascripts/application.rb`
|
1343
1185
|
|
1344
1186
|
```ruby
|
1345
1187
|
require 'glimmer-dsl-opal/samples/hello/hello_group'
|
1346
1188
|
```
|
1347
1189
|
|
1348
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
1349
|
-
|
1350
|
-
```ruby
|
1351
|
-
class HelloGroup
|
1352
|
-
class Person
|
1353
|
-
attr_accessor :male, :female, :child, :teen, :adult, :senior
|
1354
|
-
|
1355
|
-
def initialize
|
1356
|
-
reset
|
1357
|
-
end
|
1358
|
-
|
1359
|
-
def reset
|
1360
|
-
self.male = nil
|
1361
|
-
self.female = nil
|
1362
|
-
self.child = nil
|
1363
|
-
self.teen = nil
|
1364
|
-
self.adult = true
|
1365
|
-
self.senior = nil
|
1366
|
-
end
|
1367
|
-
end
|
1368
|
-
|
1369
|
-
include Glimmer
|
1370
|
-
|
1371
|
-
def launch
|
1372
|
-
person = Person.new
|
1373
|
-
|
1374
|
-
shell {
|
1375
|
-
text 'Hello, Group!'
|
1376
|
-
row_layout :vertical
|
1377
|
-
|
1378
|
-
group {
|
1379
|
-
row_layout
|
1380
|
-
|
1381
|
-
text 'Gender'
|
1382
|
-
font style: :bold
|
1383
|
-
|
1384
|
-
radio {
|
1385
|
-
text 'Male'
|
1386
|
-
selection <=> [person, :male]
|
1387
|
-
}
|
1388
|
-
|
1389
|
-
radio {
|
1390
|
-
text 'Female'
|
1391
|
-
selection <=> [person, :female]
|
1392
|
-
}
|
1393
|
-
}
|
1394
|
-
|
1395
|
-
group {
|
1396
|
-
row_layout
|
1397
|
-
|
1398
|
-
text 'Age Group'
|
1399
|
-
font style: :bold
|
1400
|
-
|
1401
|
-
radio {
|
1402
|
-
text 'Child'
|
1403
|
-
selection bind(person, :child)
|
1404
|
-
}
|
1405
|
-
|
1406
|
-
radio {
|
1407
|
-
text 'Teen'
|
1408
|
-
selection bind(person, :teen)
|
1409
|
-
}
|
1410
|
-
|
1411
|
-
radio {
|
1412
|
-
text 'Adult'
|
1413
|
-
selection bind(person, :adult)
|
1414
|
-
}
|
1415
|
-
|
1416
|
-
radio {
|
1417
|
-
text 'Senior'
|
1418
|
-
selection bind(person, :senior)
|
1419
|
-
}
|
1420
|
-
}
|
1421
|
-
|
1422
|
-
button {
|
1423
|
-
text 'Reset'
|
1424
|
-
|
1425
|
-
on_widget_selected do
|
1426
|
-
person.reset
|
1427
|
-
end
|
1428
|
-
}
|
1429
|
-
}.open
|
1430
|
-
end
|
1431
|
-
end
|
1432
|
-
|
1433
|
-
HelloGroup.new.launch
|
1434
|
-
```
|
1435
1190
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1436
1191
|
|
1437
1192
|
![Glimmer DSL for SWT Hello Group](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-group.png)
|
@@ -1451,81 +1206,15 @@ You should see "Hello, Group!"
|
|
1451
1206
|
|
1452
1207
|
#### Hello, Checkbox!
|
1453
1208
|
|
1209
|
+
This is the low level way of using `checkbox`
|
1210
|
+
|
1454
1211
|
Add the following require statement to `app/assets/javascripts/application.rb`
|
1455
1212
|
|
1456
1213
|
```ruby
|
1457
1214
|
require 'glimmer-dsl-opal/samples/hello/hello_checkbox'
|
1458
1215
|
```
|
1459
1216
|
|
1460
|
-
|
1461
|
-
|
1462
|
-
```ruby
|
1463
|
-
class HelloCheckbox
|
1464
|
-
class Person
|
1465
|
-
attr_accessor :skiing, :snowboarding, :snowmobiling, :snowshoeing
|
1466
|
-
|
1467
|
-
def initialize
|
1468
|
-
reset_activities
|
1469
|
-
end
|
1470
|
-
|
1471
|
-
def reset_activities
|
1472
|
-
self.skiing = false
|
1473
|
-
self.snowboarding = true
|
1474
|
-
self.snowmobiling = false
|
1475
|
-
self.snowshoeing = false
|
1476
|
-
end
|
1477
|
-
end
|
1478
|
-
|
1479
|
-
include Glimmer
|
1480
|
-
|
1481
|
-
def launch
|
1482
|
-
person = Person.new
|
1483
|
-
|
1484
|
-
shell {
|
1485
|
-
text 'Hello, Checkbox!'
|
1486
|
-
row_layout :vertical
|
1487
|
-
|
1488
|
-
label {
|
1489
|
-
text 'Check all snow activities you are interested in:'
|
1490
|
-
font style: :bold
|
1491
|
-
}
|
1492
|
-
|
1493
|
-
composite {
|
1494
|
-
checkbox {
|
1495
|
-
text 'Skiing'
|
1496
|
-
selection bind(person, :skiing)
|
1497
|
-
}
|
1498
|
-
|
1499
|
-
checkbox {
|
1500
|
-
text 'Snowboarding'
|
1501
|
-
selection bind(person, :snowboarding)
|
1502
|
-
}
|
1503
|
-
|
1504
|
-
checkbox {
|
1505
|
-
text 'Snowmobiling'
|
1506
|
-
selection bind(person, :snowmobiling)
|
1507
|
-
}
|
1508
|
-
|
1509
|
-
checkbox {
|
1510
|
-
text 'Snowshoeing'
|
1511
|
-
selection bind(person, :snowshoeing)
|
1512
|
-
}
|
1513
|
-
}
|
1514
|
-
|
1515
|
-
button {
|
1516
|
-
text 'Reset Activities'
|
1517
|
-
|
1518
|
-
on_widget_selected do
|
1519
|
-
person.reset_activities
|
1520
|
-
end
|
1521
|
-
}
|
1522
|
-
}.open
|
1523
|
-
end
|
1524
|
-
end
|
1525
|
-
|
1526
|
-
HelloCheckbox.new.launch
|
1527
|
-
```
|
1528
|
-
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1217
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1529
1218
|
|
1530
1219
|
![Glimmer DSL for SWT Hello Checkbox](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-checkbox.png)
|
1531
1220
|
|
@@ -1544,6 +1233,8 @@ You should see "Hello, Checkbox!"
|
|
1544
1233
|
|
1545
1234
|
#### Hello, Checkbox Group!
|
1546
1235
|
|
1236
|
+
`checkbox_group` is a level higher than `checkbox` in abstraction. It generates a group of checkbox widgets based on available options in model `attribute_options` methods.
|
1237
|
+
|
1547
1238
|
Add the following require statement to `app/assets/javascripts/application.rb`
|
1548
1239
|
|
1549
1240
|
```ruby
|
@@ -1570,11 +1261,13 @@ class HelloCheckboxGroup
|
|
1570
1261
|
end
|
1571
1262
|
end
|
1572
1263
|
|
1573
|
-
include Glimmer
|
1264
|
+
include Glimmer::UI::CustomShell
|
1574
1265
|
|
1575
|
-
|
1576
|
-
person = Person.new
|
1577
|
-
|
1266
|
+
before_body {
|
1267
|
+
@person = Person.new
|
1268
|
+
}
|
1269
|
+
|
1270
|
+
body {
|
1578
1271
|
shell {
|
1579
1272
|
text 'Hello, Checkbox Group!'
|
1580
1273
|
row_layout :vertical
|
@@ -1585,21 +1278,21 @@ class HelloCheckboxGroup
|
|
1585
1278
|
}
|
1586
1279
|
|
1587
1280
|
checkbox_group {
|
1588
|
-
selection <=> [person, :activities]
|
1281
|
+
selection <=> [@person, :activities]
|
1589
1282
|
}
|
1590
1283
|
|
1591
1284
|
button {
|
1592
1285
|
text 'Reset Activities'
|
1593
1286
|
|
1594
1287
|
on_widget_selected do
|
1595
|
-
person.reset_activities
|
1288
|
+
@person.reset_activities
|
1596
1289
|
end
|
1597
1290
|
}
|
1598
|
-
}
|
1599
|
-
|
1291
|
+
}
|
1292
|
+
}
|
1600
1293
|
end
|
1601
1294
|
|
1602
|
-
HelloCheckboxGroup.
|
1295
|
+
HelloCheckboxGroup.launch
|
1603
1296
|
```
|
1604
1297
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1605
1298
|
|
@@ -1626,53 +1319,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
1626
1319
|
require 'glimmer-dsl-opal/samples/hello/hello_date_time'
|
1627
1320
|
```
|
1628
1321
|
|
1629
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
1630
|
-
|
1631
|
-
```ruby
|
1632
|
-
class HelloDateTime
|
1633
|
-
class Person
|
1634
|
-
attr_accessor :date_of_birth
|
1635
|
-
end
|
1636
|
-
|
1637
|
-
include Glimmer
|
1638
|
-
|
1639
|
-
def launch
|
1640
|
-
person = Person.new
|
1641
|
-
person.date_of_birth = DateTime.new(2013, 7, 12, 18, 37, 23)
|
1642
|
-
|
1643
|
-
shell {
|
1644
|
-
row_layout :vertical
|
1645
|
-
|
1646
|
-
text 'Hello, Date Time!'
|
1647
|
-
minimum_size 180, 180
|
1648
|
-
|
1649
|
-
label {
|
1650
|
-
text 'Date of Birth'
|
1651
|
-
font height: 16, style: :bold
|
1652
|
-
}
|
1653
|
-
|
1654
|
-
date { # alias for date_time(:date)
|
1655
|
-
date_time bind(person, :date_of_birth)
|
1656
|
-
}
|
1657
|
-
|
1658
|
-
date_drop_down { # alias for date_time(:date, :drop_down)
|
1659
|
-
date_time bind(person, :date_of_birth)
|
1660
|
-
}
|
1661
|
-
|
1662
|
-
time { # alias for date_time(:time)
|
1663
|
-
date_time bind(person, :date_of_birth)
|
1664
|
-
}
|
1665
|
-
|
1666
|
-
calendar { # alias for date_time(:calendar)
|
1667
|
-
date_time bind(person, :date_of_birth)
|
1668
|
-
}
|
1669
|
-
}.open
|
1670
|
-
end
|
1671
|
-
end
|
1672
|
-
|
1673
|
-
HelloDateTime.new.launch
|
1674
|
-
```
|
1675
|
-
|
1676
1322
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1677
1323
|
|
1678
1324
|
![Glimmer DSL for SWT Hello Checkbox Group](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-date-time.png)
|
@@ -1700,263 +1346,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
1700
1346
|
require 'glimmer-dsl-opal/samples/hello/hello_table'
|
1701
1347
|
```
|
1702
1348
|
|
1703
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
1704
|
-
|
1705
|
-
```ruby
|
1706
|
-
class HelloTable
|
1707
|
-
class BaseballGame
|
1708
|
-
class << self
|
1709
|
-
attr_accessor :selected_game
|
1710
|
-
|
1711
|
-
def all_playoff_games
|
1712
|
-
@all_playoff_games ||= {
|
1713
|
-
'NLDS' => [
|
1714
|
-
new(Time.new(2037, 10, 6, 12, 0), 'Chicago Cubs', 'Milwaukee Brewers', 'Free Bobblehead'),
|
1715
|
-
new(Time.new(2037, 10, 7, 12, 0), 'Chicago Cubs', 'Milwaukee Brewers'),
|
1716
|
-
new(Time.new(2037, 10, 8, 12, 0), 'Milwaukee Brewers', 'Chicago Cubs'),
|
1717
|
-
new(Time.new(2037, 10, 9, 12, 0), 'Milwaukee Brewers', 'Chicago Cubs'),
|
1718
|
-
new(Time.new(2037, 10, 10, 12, 0), 'Milwaukee Brewers', 'Chicago Cubs', 'Free Umbrella'),
|
1719
|
-
new(Time.new(2037, 10, 6, 18, 0), 'Cincinnati Reds', 'St Louis Cardinals', 'Free Bobblehead'),
|
1720
|
-
new(Time.new(2037, 10, 7, 18, 0), 'Cincinnati Reds', 'St Louis Cardinals'),
|
1721
|
-
new(Time.new(2037, 10, 8, 18, 0), 'St Louis Cardinals', 'Cincinnati Reds'),
|
1722
|
-
new(Time.new(2037, 10, 9, 18, 0), 'St Louis Cardinals', 'Cincinnati Reds'),
|
1723
|
-
new(Time.new(2037, 10, 10, 18, 0), 'St Louis Cardinals', 'Cincinnati Reds', 'Free Umbrella'),
|
1724
|
-
],
|
1725
|
-
'ALDS' => [
|
1726
|
-
new(Time.new(2037, 10, 6, 12, 0), 'New York Yankees', 'Boston Red Sox', 'Free Bobblehead'),
|
1727
|
-
new(Time.new(2037, 10, 7, 12, 0), 'New York Yankees', 'Boston Red Sox'),
|
1728
|
-
new(Time.new(2037, 10, 8, 12, 0), 'Boston Red Sox', 'New York Yankees'),
|
1729
|
-
new(Time.new(2037, 10, 9, 12, 0), 'Boston Red Sox', 'New York Yankees'),
|
1730
|
-
new(Time.new(2037, 10, 10, 12, 0), 'Boston Red Sox', 'New York Yankees', 'Free Umbrella'),
|
1731
|
-
new(Time.new(2037, 10, 6, 18, 0), 'Houston Astros', 'Cleveland Indians', 'Free Bobblehead'),
|
1732
|
-
new(Time.new(2037, 10, 7, 18, 0), 'Houston Astros', 'Cleveland Indians'),
|
1733
|
-
new(Time.new(2037, 10, 8, 18, 0), 'Cleveland Indians', 'Houston Astros'),
|
1734
|
-
new(Time.new(2037, 10, 9, 18, 0), 'Cleveland Indians', 'Houston Astros'),
|
1735
|
-
new(Time.new(2037, 10, 10, 18, 0), 'Cleveland Indians', 'Houston Astros', 'Free Umbrella'),
|
1736
|
-
],
|
1737
|
-
'NLCS' => [
|
1738
|
-
new(Time.new(2037, 10, 12, 12, 0), 'Chicago Cubs', 'Cincinnati Reds', 'Free Towel'),
|
1739
|
-
new(Time.new(2037, 10, 13, 12, 0), 'Chicago Cubs', 'Cincinnati Reds'),
|
1740
|
-
new(Time.new(2037, 10, 14, 12, 0), 'Cincinnati Reds', 'Chicago Cubs'),
|
1741
|
-
new(Time.new(2037, 10, 15, 18, 0), 'Cincinnati Reds', 'Chicago Cubs'),
|
1742
|
-
new(Time.new(2037, 10, 16, 18, 0), 'Cincinnati Reds', 'Chicago Cubs'),
|
1743
|
-
new(Time.new(2037, 10, 17, 18, 0), 'Chicago Cubs', 'Cincinnati Reds'),
|
1744
|
-
new(Time.new(2037, 10, 18, 12, 0), 'Chicago Cubs', 'Cincinnati Reds', 'Free Poncho'),
|
1745
|
-
],
|
1746
|
-
'ALCS' => [
|
1747
|
-
new(Time.new(2037, 10, 12, 12, 0), 'Houston Astros', 'Boston Red Sox', 'Free Towel'),
|
1748
|
-
new(Time.new(2037, 10, 13, 12, 0), 'Houston Astros', 'Boston Red Sox'),
|
1749
|
-
new(Time.new(2037, 10, 14, 12, 0), 'Boston Red Sox', 'Houston Astros'),
|
1750
|
-
new(Time.new(2037, 10, 15, 18, 0), 'Boston Red Sox', 'Houston Astros'),
|
1751
|
-
new(Time.new(2037, 10, 16, 18, 0), 'Boston Red Sox', 'Houston Astros'),
|
1752
|
-
new(Time.new(2037, 10, 17, 18, 0), 'Houston Astros', 'Boston Red Sox'),
|
1753
|
-
new(Time.new(2037, 10, 18, 12, 0), 'Houston Astros', 'Boston Red Sox', 'Free Poncho'),
|
1754
|
-
],
|
1755
|
-
'World Series' => [
|
1756
|
-
new(Time.new(2037, 10, 20, 18, 0), 'Chicago Cubs', 'Boston Red Sox', 'Free Baseball Cap'),
|
1757
|
-
new(Time.new(2037, 10, 21, 18, 0), 'Chicago Cubs', 'Boston Red Sox'),
|
1758
|
-
new(Time.new(2037, 10, 22, 18, 0), 'Boston Red Sox', 'Chicago Cubs'),
|
1759
|
-
new(Time.new(2037, 10, 23, 18, 0), 'Boston Red Sox', 'Chicago Cubs'),
|
1760
|
-
new(Time.new(2037, 10, 24, 18, 0), 'Boston Red Sox', 'Chicago Cubs'),
|
1761
|
-
new(Time.new(2037, 10, 25, 18, 0), 'Chicago Cubs', 'Boston Red Sox'),
|
1762
|
-
new(Time.new(2037, 10, 26, 18, 0), 'Chicago Cubs', 'Boston Red Sox', 'Free World Series Polo'),
|
1763
|
-
]
|
1764
|
-
}
|
1765
|
-
end
|
1766
|
-
|
1767
|
-
def playoff_type
|
1768
|
-
@playoff_type ||= 'World Series'
|
1769
|
-
end
|
1770
|
-
|
1771
|
-
def playoff_type=(new_playoff_type)
|
1772
|
-
@playoff_type = new_playoff_type
|
1773
|
-
self.schedule=(all_playoff_games[@playoff_type])
|
1774
|
-
end
|
1775
|
-
|
1776
|
-
def playoff_type_options
|
1777
|
-
all_playoff_games.keys
|
1778
|
-
end
|
1779
|
-
|
1780
|
-
def schedule
|
1781
|
-
@schedule ||= all_playoff_games[playoff_type]
|
1782
|
-
end
|
1783
|
-
|
1784
|
-
def schedule=(new_schedule)
|
1785
|
-
@schedule = new_schedule
|
1786
|
-
end
|
1787
|
-
end
|
1788
|
-
|
1789
|
-
include Glimmer
|
1790
|
-
include Glimmer::DataBinding::ObservableModel
|
1791
|
-
|
1792
|
-
TEAM_BALLPARKS = {
|
1793
|
-
'Boston Red Sox' => 'Fenway Park',
|
1794
|
-
'Chicago Cubs' => 'Wrigley Field',
|
1795
|
-
'Cincinnati Reds' => 'Great American Ball Park',
|
1796
|
-
'Cleveland Indians' => 'Progressive Field',
|
1797
|
-
'Houston Astros' => 'Minute Maid Park',
|
1798
|
-
'Milwaukee Brewers' => 'Miller Park',
|
1799
|
-
'New York Yankees' => 'Yankee Stadium',
|
1800
|
-
'St Louis Cardinals' => 'Busch Stadium',
|
1801
|
-
}
|
1802
|
-
|
1803
|
-
attr_accessor :date_time, :home_team, :away_team, :ballpark, :promotion
|
1804
|
-
|
1805
|
-
def initialize(date_time, home_team, away_team, promotion = 'N/A')
|
1806
|
-
self.date_time = date_time
|
1807
|
-
self.home_team = home_team
|
1808
|
-
self.away_team = away_team
|
1809
|
-
self.promotion = promotion
|
1810
|
-
observe(self, :date_time) do |new_value|
|
1811
|
-
notify_observers(:game_date)
|
1812
|
-
notify_observers(:game_time)
|
1813
|
-
end
|
1814
|
-
end
|
1815
|
-
|
1816
|
-
def home_team=(home_team_value)
|
1817
|
-
if home_team_value != away_team
|
1818
|
-
@home_team = home_team_value
|
1819
|
-
self.ballpark = TEAM_BALLPARKS[@home_team]
|
1820
|
-
end
|
1821
|
-
end
|
1822
|
-
|
1823
|
-
def away_team=(away_team_value)
|
1824
|
-
if away_team_value != home_team
|
1825
|
-
@away_team = away_team_value
|
1826
|
-
end
|
1827
|
-
end
|
1828
|
-
|
1829
|
-
def date
|
1830
|
-
Date.new(date_time.year, date_time.month, date_time.day)
|
1831
|
-
end
|
1832
|
-
|
1833
|
-
def time
|
1834
|
-
Time.new(0, 1, 1, date_time.hour, date_time.min, date_time.sec, '+00:00')
|
1835
|
-
end
|
1836
|
-
|
1837
|
-
def game_date
|
1838
|
-
date_time.strftime("%m/%d/%Y")
|
1839
|
-
end
|
1840
|
-
|
1841
|
-
def game_time
|
1842
|
-
date_time.strftime("%I:%M %p")
|
1843
|
-
end
|
1844
|
-
|
1845
|
-
def home_team_options
|
1846
|
-
TEAM_BALLPARKS.keys
|
1847
|
-
end
|
1848
|
-
|
1849
|
-
def away_team_options
|
1850
|
-
TEAM_BALLPARKS.keys
|
1851
|
-
end
|
1852
|
-
|
1853
|
-
def ballpark_options
|
1854
|
-
[TEAM_BALLPARKS[@home_team], TEAM_BALLPARKS[@away_team]]
|
1855
|
-
end
|
1856
|
-
|
1857
|
-
def to_s
|
1858
|
-
"#{home_team} vs #{away_team} at #{ballpark} on #{game_date} #{game_time}"
|
1859
|
-
end
|
1860
|
-
|
1861
|
-
def book!
|
1862
|
-
"Thank you for booking #{to_s}"
|
1863
|
-
end
|
1864
|
-
end
|
1865
|
-
|
1866
|
-
include Glimmer
|
1867
|
-
|
1868
|
-
def launch
|
1869
|
-
shell {
|
1870
|
-
grid_layout
|
1871
|
-
|
1872
|
-
text 'Hello, Table!'
|
1873
|
-
|
1874
|
-
label {
|
1875
|
-
layout_data :center, :center, true, false
|
1876
|
-
|
1877
|
-
text 'Baseball Playoff Schedule'
|
1878
|
-
font height: 30, style: :bold
|
1879
|
-
}
|
1880
|
-
|
1881
|
-
combo(:read_only) {
|
1882
|
-
layout_data :center, :center, true, false
|
1883
|
-
selection bind(BaseballGame, :playoff_type)
|
1884
|
-
font height: 16
|
1885
|
-
}
|
1886
|
-
|
1887
|
-
table(:editable) { |table_proxy|
|
1888
|
-
layout_data :fill, :fill, true, true
|
1889
|
-
|
1890
|
-
table_column {
|
1891
|
-
text 'Game Date'
|
1892
|
-
width 150
|
1893
|
-
sort_property :date # ensure sorting by real date value (not `game_date` string specified in items below)
|
1894
|
-
editor :date_drop_down, property: :date_time
|
1895
|
-
}
|
1896
|
-
table_column {
|
1897
|
-
text 'Game Time'
|
1898
|
-
width 150
|
1899
|
-
sort_property :time # ensure sorting by real time value (not `game_time` string specified in items below)
|
1900
|
-
editor :time, property: :date_time
|
1901
|
-
}
|
1902
|
-
table_column {
|
1903
|
-
text 'Ballpark'
|
1904
|
-
width 180
|
1905
|
-
editor :none
|
1906
|
-
}
|
1907
|
-
table_column {
|
1908
|
-
text 'Home Team'
|
1909
|
-
width 150
|
1910
|
-
editor :combo, :read_only # read_only is simply an SWT style passed to combo widget
|
1911
|
-
}
|
1912
|
-
table_column {
|
1913
|
-
text 'Away Team'
|
1914
|
-
width 150
|
1915
|
-
editor :combo, :read_only # read_only is simply an SWT style passed to combo widget
|
1916
|
-
}
|
1917
|
-
table_column {
|
1918
|
-
text 'Promotion'
|
1919
|
-
width 150
|
1920
|
-
# default text editor is used here
|
1921
|
-
}
|
1922
|
-
|
1923
|
-
# Data-bind table items (rows) to a model collection property, specifying column properties ordering per nested model
|
1924
|
-
items bind(BaseballGame, :schedule), column_properties(:game_date, :game_time, :ballpark, :home_team, :away_team, :promotion)
|
1925
|
-
|
1926
|
-
# Data-bind table selection
|
1927
|
-
selection bind(BaseballGame, :selected_game)
|
1928
|
-
|
1929
|
-
# Default initial sort property
|
1930
|
-
sort_property :date
|
1931
|
-
|
1932
|
-
# Sort by these additional properties after handling sort by the column the user clicked
|
1933
|
-
additional_sort_properties :date, :time, :home_team, :away_team, :ballpark, :promotion
|
1934
|
-
}
|
1935
|
-
|
1936
|
-
button {
|
1937
|
-
text 'Book Selected Game'
|
1938
|
-
layout_data :center, :center, true, false
|
1939
|
-
font height: 16
|
1940
|
-
enabled bind(BaseballGame, :selected_game)
|
1941
|
-
|
1942
|
-
on_widget_selected {
|
1943
|
-
book_selected_game
|
1944
|
-
}
|
1945
|
-
}
|
1946
|
-
}.open
|
1947
|
-
end
|
1948
|
-
|
1949
|
-
def book_selected_game
|
1950
|
-
message_box {
|
1951
|
-
text 'Baseball Game Booked!'
|
1952
|
-
message BaseballGame.selected_game.book!
|
1953
|
-
}.open
|
1954
|
-
end
|
1955
|
-
end
|
1956
|
-
|
1957
|
-
HelloTable.new.launch
|
1958
|
-
```
|
1959
|
-
|
1960
1349
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1961
1350
|
|
1962
1351
|
![Glimmer DSL for SWT Hello Table](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-hello-table.png)
|
@@ -2051,30 +1440,30 @@ Or add the Glimmer code directly if you prefer to play around with it:
|
|
2051
1440
|
|
2052
1441
|
```ruby
|
2053
1442
|
class HelloButton
|
2054
|
-
include Glimmer
|
1443
|
+
include Glimmer::UI::CustomShell
|
2055
1444
|
|
2056
1445
|
attr_accessor :count
|
2057
1446
|
|
2058
|
-
|
1447
|
+
before_body {
|
2059
1448
|
@count = 0
|
2060
|
-
|
1449
|
+
}
|
2061
1450
|
|
2062
|
-
|
1451
|
+
body {
|
2063
1452
|
shell {
|
2064
1453
|
text 'Hello, Button!'
|
2065
1454
|
|
2066
1455
|
button {
|
2067
|
-
text
|
1456
|
+
text <= [self, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
|
2068
1457
|
|
2069
1458
|
on_widget_selected {
|
2070
1459
|
self.count += 1
|
2071
1460
|
}
|
2072
1461
|
}
|
2073
|
-
}
|
2074
|
-
|
1462
|
+
}
|
1463
|
+
}
|
2075
1464
|
end
|
2076
1465
|
|
2077
|
-
HelloButton.
|
1466
|
+
HelloButton.launch
|
2078
1467
|
```
|
2079
1468
|
|
2080
1469
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
@@ -2694,19 +2083,24 @@ class LoginPresenter
|
|
2694
2083
|
end
|
2695
2084
|
|
2696
2085
|
class Login
|
2697
|
-
include Glimmer
|
2086
|
+
include Glimmer::UI::CustomShell
|
2087
|
+
|
2088
|
+
before_body {
|
2089
|
+
@presenter = LoginPresenter.new
|
2090
|
+
}
|
2698
2091
|
|
2699
|
-
|
2700
|
-
|
2701
|
-
@shell = shell {
|
2092
|
+
body {
|
2093
|
+
shell {
|
2702
2094
|
text "Login"
|
2095
|
+
|
2703
2096
|
composite {
|
2704
2097
|
grid_layout 2, false #two columns with differing widths
|
2705
2098
|
|
2706
2099
|
label { text "Username:" } # goes in column 1
|
2707
2100
|
@user_name_text = text { # goes in column 2
|
2708
|
-
text
|
2709
|
-
enabled
|
2101
|
+
text <=> [@presenter, :user_name]
|
2102
|
+
enabled <= [@presenter, :logged_out?, computed_by: :status]
|
2103
|
+
|
2710
2104
|
on_key_pressed { |event|
|
2711
2105
|
@password_text.set_focus if event.keyCode == swt(:cr)
|
2712
2106
|
}
|
@@ -2714,43 +2108,47 @@ class Login
|
|
2714
2108
|
|
2715
2109
|
label { text "Password:" }
|
2716
2110
|
@password_text = text(:password, :border) {
|
2717
|
-
text
|
2718
|
-
enabled
|
2111
|
+
text <=> [@presenter, :password]
|
2112
|
+
enabled <= [@presenter, :logged_out?, computed_by: :status]
|
2113
|
+
|
2719
2114
|
on_key_pressed { |event|
|
2720
|
-
presenter.login if event.keyCode == swt(:cr)
|
2115
|
+
@presenter.login! if event.keyCode == swt(:cr)
|
2721
2116
|
}
|
2722
2117
|
}
|
2723
2118
|
|
2724
2119
|
label { text "Status:" }
|
2725
|
-
label { text
|
2120
|
+
label { text <= [@presenter, :status] }
|
2726
2121
|
|
2727
2122
|
button {
|
2728
2123
|
text "Login"
|
2729
|
-
enabled
|
2730
|
-
|
2124
|
+
enabled <= [@presenter, :logged_out?, computed_by: :status]
|
2125
|
+
|
2126
|
+
on_widget_selected { @presenter.login! }
|
2731
2127
|
on_key_pressed { |event|
|
2732
|
-
|
2128
|
+
if event.keyCode == swt(:cr)
|
2129
|
+
@presenter.login!
|
2130
|
+
end
|
2733
2131
|
}
|
2734
2132
|
}
|
2735
2133
|
|
2736
2134
|
button {
|
2737
2135
|
text "Logout"
|
2738
|
-
enabled
|
2739
|
-
|
2136
|
+
enabled <= [@presenter, :logged_in?, computed_by: :status]
|
2137
|
+
|
2138
|
+
on_widget_selected { @presenter.logout! }
|
2740
2139
|
on_key_pressed { |event|
|
2741
2140
|
if event.keyCode == swt(:cr)
|
2742
|
-
presenter.logout
|
2141
|
+
@presenter.logout!
|
2743
2142
|
@user_name_text.set_focus
|
2744
2143
|
end
|
2745
2144
|
}
|
2746
2145
|
}
|
2747
2146
|
}
|
2748
2147
|
}
|
2749
|
-
|
2750
|
-
end
|
2148
|
+
}
|
2751
2149
|
end
|
2752
2150
|
|
2753
|
-
Login.
|
2151
|
+
Login.launch
|
2754
2152
|
```
|
2755
2153
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
2756
2154
|
|
@@ -2781,214 +2179,7 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
2781
2179
|
require 'glimmer-dsl-opal/samples/elaborate/tic_tac_toe'
|
2782
2180
|
```
|
2783
2181
|
|
2784
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
2785
|
-
|
2786
2182
|
```ruby
|
2787
|
-
class TicTacToe
|
2788
|
-
class Cell
|
2789
|
-
EMPTY = ""
|
2790
|
-
attr_accessor :sign, :empty
|
2791
|
-
|
2792
|
-
def initialize
|
2793
|
-
reset
|
2794
|
-
end
|
2795
|
-
|
2796
|
-
def mark(sign)
|
2797
|
-
self.sign = sign
|
2798
|
-
end
|
2799
|
-
|
2800
|
-
def reset
|
2801
|
-
self.sign = EMPTY
|
2802
|
-
end
|
2803
|
-
|
2804
|
-
def sign=(sign_symbol)
|
2805
|
-
@sign = sign_symbol
|
2806
|
-
self.empty = sign == EMPTY
|
2807
|
-
end
|
2808
|
-
|
2809
|
-
def marked
|
2810
|
-
!empty
|
2811
|
-
end
|
2812
|
-
end
|
2813
|
-
end
|
2814
|
-
|
2815
|
-
class TicTacToe
|
2816
|
-
class Board
|
2817
|
-
DRAW = :draw
|
2818
|
-
IN_PROGRESS = :in_progress
|
2819
|
-
WIN = :win
|
2820
|
-
attr :winning_sign
|
2821
|
-
attr_accessor :game_status
|
2822
|
-
|
2823
|
-
def initialize
|
2824
|
-
@sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
|
2825
|
-
build_grid
|
2826
|
-
@winning_sign = Cell::EMPTY
|
2827
|
-
@game_status = IN_PROGRESS
|
2828
|
-
end
|
2829
|
-
|
2830
|
-
#row and column numbers are 1-based
|
2831
|
-
def mark(row, column)
|
2832
|
-
self[row, column].mark(current_sign)
|
2833
|
-
game_over? #updates winning sign
|
2834
|
-
end
|
2835
|
-
|
2836
|
-
def current_sign
|
2837
|
-
@current_sign = @sign_state_machine[@current_sign]
|
2838
|
-
end
|
2839
|
-
|
2840
|
-
def [](row, column)
|
2841
|
-
@grid[row-1][column-1]
|
2842
|
-
end
|
2843
|
-
|
2844
|
-
def game_over?
|
2845
|
-
win? or draw?
|
2846
|
-
end
|
2847
|
-
|
2848
|
-
def win?
|
2849
|
-
win = (row_win? or column_win? or diagonal_win?)
|
2850
|
-
self.game_status=WIN if win
|
2851
|
-
win
|
2852
|
-
end
|
2853
|
-
|
2854
|
-
def reset
|
2855
|
-
(1..3).each do |row|
|
2856
|
-
(1..3).each do |column|
|
2857
|
-
self[row, column].reset
|
2858
|
-
end
|
2859
|
-
end
|
2860
|
-
@winning_sign = Cell::EMPTY
|
2861
|
-
@current_sign = nil
|
2862
|
-
self.game_status=IN_PROGRESS
|
2863
|
-
end
|
2864
|
-
|
2865
|
-
private
|
2866
|
-
|
2867
|
-
def build_grid
|
2868
|
-
@grid = []
|
2869
|
-
3.times do |row_index| #0-based
|
2870
|
-
@grid << []
|
2871
|
-
3.times { @grid[row_index] << Cell.new }
|
2872
|
-
end
|
2873
|
-
end
|
2874
|
-
|
2875
|
-
def row_win?
|
2876
|
-
(1..3).each do |row|
|
2877
|
-
if row_has_same_sign(row)
|
2878
|
-
@winning_sign = self[row, 1].sign
|
2879
|
-
return true
|
2880
|
-
end
|
2881
|
-
end
|
2882
|
-
false
|
2883
|
-
end
|
2884
|
-
|
2885
|
-
def column_win?
|
2886
|
-
(1..3).each do |column|
|
2887
|
-
if column_has_same_sign(column)
|
2888
|
-
@winning_sign = self[1, column].sign
|
2889
|
-
return true
|
2890
|
-
end
|
2891
|
-
end
|
2892
|
-
false
|
2893
|
-
end
|
2894
|
-
|
2895
|
-
#needs refactoring if we ever decide to make the board size dynamic
|
2896
|
-
def diagonal_win?
|
2897
|
-
if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
|
2898
|
-
@winning_sign = self[1, 1].sign
|
2899
|
-
return true
|
2900
|
-
end
|
2901
|
-
if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
|
2902
|
-
@winning_sign = self[3, 1].sign
|
2903
|
-
return true
|
2904
|
-
end
|
2905
|
-
false
|
2906
|
-
end
|
2907
|
-
|
2908
|
-
def draw?
|
2909
|
-
@board_full = true
|
2910
|
-
3.times do |x|
|
2911
|
-
3.times do |y|
|
2912
|
-
@board_full = false if self[x, y].empty
|
2913
|
-
end
|
2914
|
-
end
|
2915
|
-
self.game_status = DRAW if @board_full
|
2916
|
-
@board_full
|
2917
|
-
end
|
2918
|
-
|
2919
|
-
def row_has_same_sign(number)
|
2920
|
-
row_sign = self[number, 1].sign
|
2921
|
-
[2, 3].each do |column|
|
2922
|
-
return false unless row_sign == (self[number, column].sign)
|
2923
|
-
end
|
2924
|
-
true if self[number, 1].marked
|
2925
|
-
end
|
2926
|
-
|
2927
|
-
def column_has_same_sign(number)
|
2928
|
-
column_sign = self[1, number].sign
|
2929
|
-
[2, 3].each do |row|
|
2930
|
-
return false unless column_sign == (self[row, number].sign)
|
2931
|
-
end
|
2932
|
-
true if self[1, number].marked
|
2933
|
-
end
|
2934
|
-
|
2935
|
-
end
|
2936
|
-
end
|
2937
|
-
|
2938
|
-
class TicTacToe
|
2939
|
-
include Glimmer
|
2940
|
-
|
2941
|
-
def initialize
|
2942
|
-
@tic_tac_toe_board = Board.new
|
2943
|
-
@shell = shell {
|
2944
|
-
text "Tic-Tac-Toe"
|
2945
|
-
minimum_size 150, 178
|
2946
|
-
composite {
|
2947
|
-
grid_layout 3, true
|
2948
|
-
(1..3).each { |row|
|
2949
|
-
(1..3).each { |column|
|
2950
|
-
button {
|
2951
|
-
layout_data :fill, :fill, true, true
|
2952
|
-
text bind(@tic_tac_toe_board[row, column], :sign)
|
2953
|
-
enabled bind(@tic_tac_toe_board[row, column], :empty)
|
2954
|
-
font style: :bold, height: 20
|
2955
|
-
on_widget_selected {
|
2956
|
-
@tic_tac_toe_board.mark(row, column)
|
2957
|
-
}
|
2958
|
-
}
|
2959
|
-
}
|
2960
|
-
}
|
2961
|
-
}
|
2962
|
-
}
|
2963
|
-
observe(@tic_tac_toe_board, :game_status) { |game_status|
|
2964
|
-
display_win_message if game_status == Board::WIN
|
2965
|
-
display_draw_message if game_status == Board::DRAW
|
2966
|
-
}
|
2967
|
-
end
|
2968
|
-
|
2969
|
-
def display_win_message
|
2970
|
-
display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
|
2971
|
-
end
|
2972
|
-
|
2973
|
-
def display_draw_message
|
2974
|
-
display_game_over_message("Draw!")
|
2975
|
-
end
|
2976
|
-
|
2977
|
-
def display_game_over_message(message_text)
|
2978
|
-
message_box(@shell) {
|
2979
|
-
text 'Game Over'
|
2980
|
-
message message_text
|
2981
|
-
}.open
|
2982
|
-
@tic_tac_toe_board.reset
|
2983
|
-
end
|
2984
|
-
|
2985
|
-
def open
|
2986
|
-
@shell.open
|
2987
|
-
end
|
2988
|
-
end
|
2989
|
-
|
2990
|
-
TicTacToe.new.open
|
2991
|
-
```
|
2992
2183
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
2993
2184
|
|
2994
2185
|
![Glimmer DSL for SWT Tic Tac Toe](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-tic-tac-toe.png)
|
@@ -3018,321 +2209,6 @@ Add the following require statement to `app/assets/javascripts/application.rb`
|
|
3018
2209
|
require 'glimmer-dsl-opal/samples/elaborate/contact_manager'
|
3019
2210
|
```
|
3020
2211
|
|
3021
|
-
Or add the Glimmer code directly if you prefer to play around with it:
|
3022
|
-
|
3023
|
-
```ruby
|
3024
|
-
class ContactManager
|
3025
|
-
class Contact
|
3026
|
-
attr_accessor :first_name, :last_name, :email
|
3027
|
-
|
3028
|
-
def initialize(attribute_map)
|
3029
|
-
@first_name = attribute_map[:first_name]
|
3030
|
-
@last_name = attribute_map[:last_name]
|
3031
|
-
@email = attribute_map[:email]
|
3032
|
-
end
|
3033
|
-
end
|
3034
|
-
end
|
3035
|
-
|
3036
|
-
class ContactManager
|
3037
|
-
class ContactRepository
|
3038
|
-
NAMES_FIRST = %w[
|
3039
|
-
Liam
|
3040
|
-
Noah
|
3041
|
-
William
|
3042
|
-
James
|
3043
|
-
Oliver
|
3044
|
-
Benjamin
|
3045
|
-
Elijah
|
3046
|
-
Lucas
|
3047
|
-
Mason
|
3048
|
-
Logan
|
3049
|
-
Alexander
|
3050
|
-
Ethan
|
3051
|
-
Jacob
|
3052
|
-
Michael
|
3053
|
-
Daniel
|
3054
|
-
Henry
|
3055
|
-
Jackson
|
3056
|
-
Sebastian
|
3057
|
-
Aiden
|
3058
|
-
Matthew
|
3059
|
-
Samuel
|
3060
|
-
David
|
3061
|
-
Joseph
|
3062
|
-
Carter
|
3063
|
-
Owen
|
3064
|
-
Wyatt
|
3065
|
-
John
|
3066
|
-
Jack
|
3067
|
-
Luke
|
3068
|
-
Jayden
|
3069
|
-
Dylan
|
3070
|
-
Grayson
|
3071
|
-
Levi
|
3072
|
-
Isaac
|
3073
|
-
Gabriel
|
3074
|
-
Julian
|
3075
|
-
Mateo
|
3076
|
-
Anthony
|
3077
|
-
Jaxon
|
3078
|
-
Lincoln
|
3079
|
-
Joshua
|
3080
|
-
Christopher
|
3081
|
-
Andrew
|
3082
|
-
Theodore
|
3083
|
-
Caleb
|
3084
|
-
Ryan
|
3085
|
-
Asher
|
3086
|
-
Nathan
|
3087
|
-
Thomas
|
3088
|
-
Leo
|
3089
|
-
Isaiah
|
3090
|
-
Charles
|
3091
|
-
Josiah
|
3092
|
-
Hudson
|
3093
|
-
Christian
|
3094
|
-
Hunter
|
3095
|
-
Connor
|
3096
|
-
Eli
|
3097
|
-
Ezra
|
3098
|
-
Aaron
|
3099
|
-
Landon
|
3100
|
-
Adrian
|
3101
|
-
Jonathan
|
3102
|
-
Nolan
|
3103
|
-
Jeremiah
|
3104
|
-
Easton
|
3105
|
-
Elias
|
3106
|
-
Colton
|
3107
|
-
Cameron
|
3108
|
-
Carson
|
3109
|
-
Robert
|
3110
|
-
Angel
|
3111
|
-
Maverick
|
3112
|
-
Nicholas
|
3113
|
-
Dominic
|
3114
|
-
Jaxson
|
3115
|
-
Greyson
|
3116
|
-
Adam
|
3117
|
-
Ian
|
3118
|
-
Austin
|
3119
|
-
Santiago
|
3120
|
-
Jordan
|
3121
|
-
Cooper
|
3122
|
-
Brayden
|
3123
|
-
Roman
|
3124
|
-
Evan
|
3125
|
-
Ezekiel
|
3126
|
-
Xaviar
|
3127
|
-
Jose
|
3128
|
-
Jace
|
3129
|
-
Jameson
|
3130
|
-
Leonardo
|
3131
|
-
Axel
|
3132
|
-
Everett
|
3133
|
-
Kayden
|
3134
|
-
Miles
|
3135
|
-
Sawyer
|
3136
|
-
Jason
|
3137
|
-
Emma
|
3138
|
-
Olivia
|
3139
|
-
]
|
3140
|
-
NAMES_LAST = %w[
|
3141
|
-
Smith
|
3142
|
-
Johnson
|
3143
|
-
Williams
|
3144
|
-
Brown
|
3145
|
-
Jones
|
3146
|
-
Miller
|
3147
|
-
Davis
|
3148
|
-
Wilson
|
3149
|
-
Anderson
|
3150
|
-
Taylor
|
3151
|
-
]
|
3152
|
-
def initialize(contacts = nil)
|
3153
|
-
@contacts = contacts || 100.times.map do |n|
|
3154
|
-
random_first_name_index = (rand*NAMES_FIRST.size).to_i
|
3155
|
-
random_last_name_index = (rand*NAMES_LAST.size).to_i
|
3156
|
-
first_name = NAMES_FIRST[random_first_name_index]
|
3157
|
-
last_name = NAMES_LAST[random_last_name_index]
|
3158
|
-
email = "#{first_name}@#{last_name}.com".downcase
|
3159
|
-
Contact.new(
|
3160
|
-
first_name: first_name,
|
3161
|
-
last_name: last_name,
|
3162
|
-
email: email
|
3163
|
-
)
|
3164
|
-
end
|
3165
|
-
end
|
3166
|
-
|
3167
|
-
def find(attribute_filter_map)
|
3168
|
-
@contacts.find_all do |contact|
|
3169
|
-
match = true
|
3170
|
-
attribute_filter_map.keys.each do |attribute_name|
|
3171
|
-
contact_value = contact.send(attribute_name).downcase
|
3172
|
-
filter_value = attribute_filter_map[attribute_name].downcase
|
3173
|
-
match = false unless contact_value.match(filter_value)
|
3174
|
-
end
|
3175
|
-
match
|
3176
|
-
end
|
3177
|
-
end
|
3178
|
-
end
|
3179
|
-
end
|
3180
|
-
|
3181
|
-
class ContactManager
|
3182
|
-
class ContactManagerPresenter
|
3183
|
-
attr_accessor :results
|
3184
|
-
@@contact_attributes = [:first_name, :last_name, :email]
|
3185
|
-
@@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
|
3186
|
-
|
3187
|
-
def initialize(contact_repository = nil)
|
3188
|
-
@contact_repository = contact_repository || ContactRepository.new
|
3189
|
-
@results = []
|
3190
|
-
end
|
3191
|
-
|
3192
|
-
def list
|
3193
|
-
self.results = @contact_repository.find({})
|
3194
|
-
end
|
3195
|
-
|
3196
|
-
def find
|
3197
|
-
filter_map = {}
|
3198
|
-
@@contact_attributes.each do |attribute_name|
|
3199
|
-
filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
|
3200
|
-
end
|
3201
|
-
self.results = @contact_repository.find(filter_map)
|
3202
|
-
@sort_attribute_name = nil
|
3203
|
-
@sort_direction_ascending = nil
|
3204
|
-
end
|
3205
|
-
|
3206
|
-
def toggle_sort(attribute_name)
|
3207
|
-
@sort_attribute_name = attribute_name
|
3208
|
-
@sort_direction_ascending = !@sort_direction_ascending
|
3209
|
-
sorted_results = self.results.sort_by {|contact| contact.send(attribute_name).downcase}
|
3210
|
-
sorted_results = sorted_results.reverse unless @sort_direction_ascending
|
3211
|
-
self.results = sorted_results
|
3212
|
-
end
|
3213
|
-
end
|
3214
|
-
end
|
3215
|
-
|
3216
|
-
class ContactManager
|
3217
|
-
include Glimmer
|
3218
|
-
|
3219
|
-
def initialize
|
3220
|
-
@contact_manager_presenter = ContactManagerPresenter.new
|
3221
|
-
@contact_manager_presenter.list
|
3222
|
-
end
|
3223
|
-
|
3224
|
-
def launch
|
3225
|
-
shell {
|
3226
|
-
text "Contact Manager"
|
3227
|
-
composite {
|
3228
|
-
group {
|
3229
|
-
grid_layout(2, false) {
|
3230
|
-
margin_width 0
|
3231
|
-
margin_height 0
|
3232
|
-
}
|
3233
|
-
layout_data :fill, :center, true, false
|
3234
|
-
text 'Lookup Contacts'
|
3235
|
-
font height: 24
|
3236
|
-
|
3237
|
-
label {
|
3238
|
-
layout_data :right, :center, false, false
|
3239
|
-
text "First &Name: "
|
3240
|
-
font height: 16
|
3241
|
-
}
|
3242
|
-
text {
|
3243
|
-
layout_data :fill, :center, true, false
|
3244
|
-
text bind(@contact_manager_presenter, :first_name)
|
3245
|
-
on_key_pressed {|key_event|
|
3246
|
-
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
|
3247
|
-
}
|
3248
|
-
}
|
3249
|
-
|
3250
|
-
label {
|
3251
|
-
layout_data :right, :center, false, false
|
3252
|
-
text "&Last Name: "
|
3253
|
-
font height: 16
|
3254
|
-
}
|
3255
|
-
text {
|
3256
|
-
layout_data :fill, :center, true, false
|
3257
|
-
text bind(@contact_manager_presenter, :last_name)
|
3258
|
-
on_key_pressed {|key_event|
|
3259
|
-
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
|
3260
|
-
}
|
3261
|
-
}
|
3262
|
-
|
3263
|
-
label {
|
3264
|
-
layout_data :right, :center, false, false
|
3265
|
-
text "&Email: "
|
3266
|
-
font height: 16
|
3267
|
-
}
|
3268
|
-
text {
|
3269
|
-
layout_data :fill, :center, true, false
|
3270
|
-
text bind(@contact_manager_presenter, :email)
|
3271
|
-
on_key_pressed {|key_event|
|
3272
|
-
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
|
3273
|
-
}
|
3274
|
-
}
|
3275
|
-
|
3276
|
-
composite {
|
3277
|
-
row_layout {
|
3278
|
-
margin_width 0
|
3279
|
-
margin_height 0
|
3280
|
-
}
|
3281
|
-
layout_data(:right, :center, false, false) {
|
3282
|
-
horizontal_span 2
|
3283
|
-
}
|
3284
|
-
|
3285
|
-
button {
|
3286
|
-
text "&Find"
|
3287
|
-
on_widget_selected { @contact_manager_presenter.find }
|
3288
|
-
on_key_pressed {|key_event|
|
3289
|
-
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
|
3290
|
-
}
|
3291
|
-
}
|
3292
|
-
|
3293
|
-
button {
|
3294
|
-
text "&List All"
|
3295
|
-
on_widget_selected { @contact_manager_presenter.list }
|
3296
|
-
on_key_pressed {|key_event|
|
3297
|
-
@contact_manager_presenter.list if key_event.keyCode == swt(:cr)
|
3298
|
-
}
|
3299
|
-
}
|
3300
|
-
}
|
3301
|
-
}
|
3302
|
-
|
3303
|
-
table(:multi) { |table_proxy|
|
3304
|
-
layout_data {
|
3305
|
-
horizontal_alignment :fill
|
3306
|
-
vertical_alignment :fill
|
3307
|
-
grab_excess_horizontal_space true
|
3308
|
-
grab_excess_vertical_space true
|
3309
|
-
height_hint 200
|
3310
|
-
}
|
3311
|
-
table_column {
|
3312
|
-
text "First Name"
|
3313
|
-
width 80
|
3314
|
-
}
|
3315
|
-
table_column {
|
3316
|
-
text "Last Name"
|
3317
|
-
width 80
|
3318
|
-
}
|
3319
|
-
table_column {
|
3320
|
-
text "Email"
|
3321
|
-
width 200
|
3322
|
-
}
|
3323
|
-
items bind(@contact_manager_presenter, :results),
|
3324
|
-
column_properties(:first_name, :last_name, :email)
|
3325
|
-
on_mouse_up { |event|
|
3326
|
-
table_proxy.edit_table_item(event.table_item, event.column_index)
|
3327
|
-
}
|
3328
|
-
}
|
3329
|
-
}
|
3330
|
-
}.open
|
3331
|
-
end
|
3332
|
-
end
|
3333
|
-
|
3334
|
-
ContactManager.new.launch
|
3335
|
-
```
|
3336
2212
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
3337
2213
|
|
3338
2214
|
Glimmer DSL for SWT Contact Manager
|
@@ -3386,6 +2262,41 @@ Glimmer DSL for Opal Contact Manager Edit Done
|
|
3386
2262
|
|
3387
2263
|
![Glimmer DSL for Opal Contact Manager Edit Done](images/glimmer-dsl-opal-contact-manager-edit-done.png)
|
3388
2264
|
|
2265
|
+
#### Weather
|
2266
|
+
|
2267
|
+
Code: [lib/glimmer-dsl-opal/samples/elaborate/weather](lib/glimmer-dsl-opal/samples/elaborate/weather.rb)
|
2268
|
+
|
2269
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
2270
|
+
|
2271
|
+
```ruby
|
2272
|
+
require 'glimmer-dsl-opal/samples/elaborate/weather'
|
2273
|
+
```
|
2274
|
+
|
2275
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
2276
|
+
|
2277
|
+
![Weather Montreal C](https://github.com/AMaleh/glimmer-dsl-swt/raw/master/images/glimmer-weather-montreal-celsius.png)
|
2278
|
+
|
2279
|
+
![Weather Montreal F](https://github.com/AMaleh/glimmer-dsl-swt/raw/master/images/glimmer-weather-montreal-fahrenheit.png)
|
2280
|
+
|
2281
|
+
![Weather Atlanta F](https://github.com/AMaleh/glimmer-dsl-swt/raw/master/images/glimmer-weather-atlanta-fahrenheit.png)
|
2282
|
+
|
2283
|
+
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
2284
|
+
|
2285
|
+
Start the Rails server:
|
2286
|
+
```
|
2287
|
+
rails s
|
2288
|
+
```
|
2289
|
+
|
2290
|
+
Visit `http://localhost:3000`
|
2291
|
+
|
2292
|
+
You should see "Weather"
|
2293
|
+
|
2294
|
+
![Opal Weather Montreal C](/images/glimmer-dsl-opal-weather-montreal-celsius.png)
|
2295
|
+
|
2296
|
+
![Opal Weather Montreal F](/images/glimmer-dsl-opal-weather-montreal-fahrenheit.png)
|
2297
|
+
|
2298
|
+
![Opal Weather Atlanta F](/images/glimmer-dsl-opal-weather-atlanta-fahrenheit.png)
|
2299
|
+
|
3389
2300
|
### External Samples
|
3390
2301
|
|
3391
2302
|
#### Glimmer Calculator
|