glimmer-dsl-opal 0.0.5 → 0.1.0
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 +41 -0
- data/README.md +1003 -58
- data/VERSION +1 -1
- data/lib/glimmer-dsl-opal.rb +26 -8
- data/lib/glimmer/data_binding/element_binding.rb +1 -1
- data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
- data/lib/glimmer/data_binding/list_selection_binding.rb +1 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +70 -0
- data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
- data/lib/glimmer/dsl/opal/combo_selection_data_binding_expression.rb +2 -2
- data/lib/glimmer/dsl/opal/dsl.rb +10 -12
- data/lib/glimmer/dsl/opal/layout_data_expression.rb +2 -2
- data/lib/glimmer/dsl/opal/{text_expression.rb → layout_expression.rb} +5 -5
- data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +2 -3
- 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/shell_expression.rb +2 -2
- data/lib/glimmer/dsl/opal/{composite_expression.rb → table_column_expression.rb} +3 -3
- data/lib/glimmer/dsl/opal/{list_expression.rb → table_expression.rb} +3 -3
- data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
- data/lib/glimmer/dsl/opal/widget_expression.rb +23 -0
- data/lib/glimmer/opal/display_proxy.rb +23 -0
- data/lib/glimmer/opal/element_proxy.rb +48 -13
- data/lib/glimmer/swt/browser_proxy.rb +27 -0
- data/lib/glimmer/swt/button_proxy.rb +40 -0
- data/lib/glimmer/{opal/select_proxy.rb → swt/combo_proxy.rb} +15 -11
- data/lib/glimmer/swt/composite_proxy.rb +31 -0
- data/lib/glimmer/{opal → swt}/event_listener_proxy.rb +1 -1
- data/lib/glimmer/{opal → swt}/grid_layout_proxy.rb +7 -18
- data/lib/glimmer/swt/label_proxy.rb +30 -0
- data/lib/glimmer/swt/layout_data_proxy.rb +52 -0
- data/lib/glimmer/swt/layout_proxy.rb +60 -0
- data/lib/glimmer/{opal → swt}/list_proxy.rb +18 -15
- data/lib/glimmer/swt/message_box_proxy.rb +146 -0
- data/lib/glimmer/{opal → swt}/point.rb +1 -1
- data/lib/glimmer/{opal → swt}/property_owner.rb +1 -1
- data/lib/glimmer/swt/shell_proxy.rb +235 -0
- data/lib/glimmer/swt/tab_folder_proxy.rb +52 -0
- data/lib/glimmer/swt/tab_item_proxy.rb +101 -0
- data/lib/glimmer/swt/table_column_proxy.rb +56 -0
- data/lib/glimmer/swt/table_item_proxy.rb +147 -0
- data/lib/glimmer/swt/table_proxy.rb +177 -0
- data/lib/glimmer/swt/text_proxy.rb +46 -0
- data/lib/glimmer/swt/widget_proxy.rb +389 -0
- data/lib/jquery.js +2 -0
- data/lib/samples/elaborate/contact_manager.rb +2 -3
- data/lib/samples/elaborate/login.rb +0 -1
- data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
- data/lib/samples/hello/hello_computed.rb +19 -19
- data/lib/samples/hello/hello_tab.rb +2 -2
- metadata +92 -59
- 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/opal/browser_expression.rb +0 -17
- data/lib/glimmer/dsl/opal/button_expression.rb +0 -18
- data/lib/glimmer/dsl/opal/combo_expression.rb +0 -17
- data/lib/glimmer/dsl/opal/grid_layout_expression.rb +0 -17
- data/lib/glimmer/dsl/opal/label_expression.rb +0 -17
- 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
- data/lib/glimmer/opal/div_proxy.rb +0 -20
- data/lib/glimmer/opal/document_proxy.rb +0 -90
- data/lib/glimmer/opal/iframe_proxy.rb +0 -23
- data/lib/glimmer/opal/input_proxy.rb +0 -41
- data/lib/glimmer/opal/label_proxy.rb +0 -25
- data/lib/glimmer/opal/layout_data_proxy.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b86a4ab59fb47c8fd2e21c3f88d790942b19461e159b613edab602c250c0d9e7
|
4
|
+
data.tar.gz: 121b3220b1bdb4848ce065564f108bc03f0d8145a2e35d07936ed69f66d52e8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5a6fd8bb27c826ffbfa8baf5a0ab006f5756125eae25cea4fd08911c65736899520c8bbe1fafa6e1e9941ad1902dc90a62630170a2c0afec9f0420e4ec3911c
|
7
|
+
data.tar.gz: dfb9b7195d02486125efff51d9abb1c3c14ba62e9450f597d1508418155962eef0e00a7e2149f501de0f5fdf589fc4c71038392b743c42a43b9c83e914264462
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,46 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.1.0
|
4
|
+
|
5
|
+
- Code redesign to better match the glimmer-dsl-swt APIs
|
6
|
+
- opal-jquery refactoring
|
7
|
+
- opal-rspec test coverage
|
8
|
+
|
9
|
+
## 0.0.9
|
10
|
+
|
11
|
+
- Upgraded to glimmer gem v0.9.3
|
12
|
+
- Fixed issue with missing Glimmer::Opal::ElementProxy#id=(value) method breaking Contact Manager sample Find feature
|
13
|
+
|
14
|
+
## 0.0.8
|
15
|
+
|
16
|
+
- Contact Manager sample support
|
17
|
+
|
18
|
+
## 0.0.7
|
19
|
+
|
20
|
+
- Tic Tac Toe sample support
|
21
|
+
- Login sample support
|
22
|
+
|
23
|
+
## 0.0.6
|
24
|
+
|
25
|
+
- Hello, Tab! sample support
|
26
|
+
|
27
|
+
## 0.0.5
|
28
|
+
|
29
|
+
- Hello, Browser! sample support
|
30
|
+
|
31
|
+
## 0.0.4
|
32
|
+
|
33
|
+
- Hello, List Single Selection! sample support
|
34
|
+
- Hello, List Multi Selection! sample support
|
35
|
+
|
36
|
+
## 0.0.3
|
37
|
+
|
38
|
+
- Hello, Computed! sample support
|
39
|
+
|
40
|
+
## 0.0.2
|
41
|
+
|
42
|
+
- Hello, Combo! sample support
|
43
|
+
|
3
44
|
## 0.0.1
|
4
45
|
|
5
46
|
- Initial support for webifying Glimmer SWT apps
|
data/README.md
CHANGED
@@ -1,21 +1,30 @@
|
|
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.5 (Web GUI for Desktop Apps)
|
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.0.9 (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
|
-
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Opal is
|
5
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Opal](https://opalrb.com/) is an experimental proof-of-concept web GUI adaptor for [Glimmer](https://github.com/AndyObtiva/glimmer) desktop apps (i.e. apps built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)). It webifies them via [Rails](https://rubyonrails.org/) and [Opal](https://opalrb.com/), allowing Ruby desktop apps to run on the web without changing a line of code. Apps may then be custom-styled for the web via standard CSS.
|
7
6
|
|
8
|
-
|
7
|
+
Glimmer DSL for Opal successfully reuses the entire [Glimmer](https://github.com/AndyObtiva/glimmer) core DSL engine in [Opal](https://opalrb.com/) Ruby, and as such inherits the full range of powerful Glimmer DSL [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities, such as:
|
8
|
+
- `bind(model, property)` basic data-binding
|
9
|
+
- `bind(model, property, computed_by: procs)` computed data-binding
|
10
|
+
- `bind(model, property, on_read:, on_write:)` data-binding converters
|
11
|
+
- `bind(model, property), column_properties(columns)` `table` data-binding
|
12
|
+
- Automatically inferred `property_options` for `list` and `combo` data-binding
|
13
|
+
- `observe(model, property)` free-form observing
|
9
14
|
|
10
|
-
NOTE: Alpha Version 0.0
|
15
|
+
NOTE: Alpha Version 0.1.0 only supports bare-minimum capabilities for the following [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) [samples](https://github.com/AndyObtiva/glimmer#samples):
|
11
16
|
- [Hello, World!](#hello-world)
|
12
17
|
- [Hello, Combo!](#hello-combo)
|
13
18
|
- [Hello, Computed!](#hello-computed)
|
14
19
|
- [Hello, List Single Selection!](#hello-list-single-selection)
|
15
20
|
- [Hello, List Multi Selection!](#hello-list-multi-selection)
|
16
21
|
- [Hello, Browser!](#hello-browser)
|
22
|
+
- [Hello, Tab!](#hello-tab)
|
23
|
+
- [Login](#login)
|
24
|
+
- [Tic Tac Toe](#tic-tac-toe)
|
25
|
+
- [Contact Manager](#contact-manager)
|
17
26
|
|
18
|
-
Other Glimmer DSL gems:
|
27
|
+
Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
19
28
|
- [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
|
20
29
|
- [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
|
21
30
|
- [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
|
@@ -31,7 +40,16 @@ The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glim
|
|
31
40
|
- `text`
|
32
41
|
- `composite`
|
33
42
|
- `list` & `list(:multi)`
|
34
|
-
- `
|
43
|
+
- `tab_folder`
|
44
|
+
- `tab_item`
|
45
|
+
- `table`
|
46
|
+
- `table_column`
|
47
|
+
- `message_box`
|
48
|
+
- `on_widget_selected`
|
49
|
+
- `on_modify_text`
|
50
|
+
- `observe`
|
51
|
+
- `bind`
|
52
|
+
- `async_exec`
|
35
53
|
- `grid_layout`
|
36
54
|
- `layout_data`
|
37
55
|
|
@@ -39,40 +57,69 @@ The following keywords from [glimmer-dsl-swt](https://github.com/AndyObtiva/glim
|
|
39
57
|
|
40
58
|
- Rails 5: [https://github.com/rails/rails/tree/5-2-stable](https://github.com/rails/rails/tree/5-2-stable)
|
41
59
|
- Opal 1: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
|
60
|
+
- jQuery 3: [https://code.jquery.com/](https://code.jquery.com/) (jQuery 3.5.1 is included in the glimmer-dsl-opal rubygem)
|
42
61
|
|
43
62
|
## Setup
|
44
63
|
|
45
|
-
|
64
|
+
(NOTE: if you run into issues, keep in mind this is a very early experimental and incomplete alpha. Also, there is a slight chance issues you encounter are fixed in master or some other branch that you could check out instead)
|
65
|
+
|
66
|
+
Please install a Rails 5 gem (e.g. `gem install rails -v5.2.4.3` )
|
46
67
|
|
47
68
|
Start a new Rails 5 app:
|
48
69
|
|
49
70
|
```
|
50
|
-
rails new
|
71
|
+
rails new glimmer_app
|
51
72
|
```
|
52
73
|
|
53
|
-
|
74
|
+
Add the following to `Gemfile`:
|
54
75
|
|
55
|
-
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):
|
56
76
|
```
|
57
|
-
gem 'opal-rails'
|
58
|
-
gem 'opal-
|
59
|
-
gem '
|
77
|
+
gem 'opal-rails', '~> 1.1.2'
|
78
|
+
gem 'opal-async', '~> 1.1.0'
|
79
|
+
gem 'opal-jquery', '~> 0.4.4'
|
80
|
+
gem 'glimmer-dsl-opal', '~> 0.1.0', require: false
|
81
|
+
gem 'glimmer-dsl-xml', '~> 0.1.0', require: false
|
82
|
+
|
60
83
|
```
|
61
84
|
|
62
|
-
|
85
|
+
Follow (opal-rails)[https://github.com/opal/opal-rails] instructions, basically the configuration of: config/initializers/assets.rb
|
86
|
+
|
87
|
+
Edit `config/initializers/assets.rb` and add the following at the bottom:
|
63
88
|
```
|
64
89
|
Opal.use_gem 'glimmer-dsl-opal'
|
65
90
|
```
|
66
91
|
|
67
|
-
|
92
|
+
Add the following line to the top of an empty `app/assets/javascripts/application.rb` (replacing `application.js`)
|
68
93
|
|
69
|
-
|
94
|
+
```ruby
|
95
|
+
require 'glimmer-dsl-opal' # brings opal and opal browser too
|
96
|
+
```
|
97
|
+
|
98
|
+
Add more code to `app/assets/javascripts/application.rb` inside `Document.ready? do; end` block 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.
|
99
|
+
|
100
|
+
## Samples
|
70
101
|
|
71
|
-
|
102
|
+
Make sure to add any `require` statements or code below inside:
|
72
103
|
|
73
104
|
```ruby
|
74
|
-
|
105
|
+
Document.ready? do
|
106
|
+
# Code goes here.
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
### Hello Samples
|
111
|
+
|
112
|
+
#### Hello, World!
|
113
|
+
|
114
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
require 'samples/hello/hello_world'
|
118
|
+
```
|
119
|
+
|
120
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
75
121
|
|
122
|
+
```ruby
|
76
123
|
include Glimmer
|
77
124
|
|
78
125
|
shell {
|
@@ -80,12 +127,12 @@ shell {
|
|
80
127
|
label {
|
81
128
|
text 'Hello, World!'
|
82
129
|
}
|
83
|
-
}
|
130
|
+
}.open
|
84
131
|
```
|
85
132
|
|
86
133
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
87
134
|
|
88
|
-

|
89
136
|
|
90
137
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
91
138
|
|
@@ -100,13 +147,17 @@ You should see "Hello, World!"
|
|
100
147
|
|
101
148
|

|
102
149
|
|
103
|
-
|
150
|
+
#### Hello, Combo!
|
104
151
|
|
105
|
-
Add the following
|
152
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
106
153
|
|
107
154
|
```ruby
|
108
|
-
require '
|
155
|
+
require 'samples/hello/hello_combo'
|
156
|
+
```
|
157
|
+
|
158
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
109
159
|
|
160
|
+
```ruby
|
110
161
|
class Person
|
111
162
|
attr_accessor :country, :country_options
|
112
163
|
|
@@ -144,7 +195,7 @@ HelloCombo.new.launch
|
|
144
195
|
```
|
145
196
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
146
197
|
|
147
|
-

|
148
199
|
|
149
200
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
150
201
|
|
@@ -159,13 +210,18 @@ You should see "Hello, Combo!"
|
|
159
210
|
|
160
211
|

|
161
212
|
|
162
|
-
|
213
|
+
#### Hello, Computed!
|
214
|
+
|
215
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
163
216
|
|
164
|
-
Add the following Glimmer code to `app/assets/javascripts/application.js.rb`
|
165
217
|
|
166
218
|
```ruby
|
167
|
-
require '
|
219
|
+
require 'samples/hello/hello_computed'
|
220
|
+
```
|
221
|
+
|
222
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
168
223
|
|
224
|
+
```ruby
|
169
225
|
class HelloComputed
|
170
226
|
class Contact
|
171
227
|
attr_accessor :first_name, :last_name, :year_of_birth
|
@@ -193,15 +249,15 @@ class HelloComputed
|
|
193
249
|
|
194
250
|
def initialize
|
195
251
|
@contact = Contact.new(
|
196
|
-
first_name:
|
197
|
-
last_name:
|
252
|
+
first_name: 'Barry',
|
253
|
+
last_name: 'McKibbin',
|
198
254
|
year_of_birth: 1985
|
199
255
|
)
|
200
256
|
end
|
201
257
|
|
202
258
|
def launch
|
203
259
|
shell {
|
204
|
-
text
|
260
|
+
text 'Hello, Computed!'
|
205
261
|
composite {
|
206
262
|
grid_layout {
|
207
263
|
num_columns 2
|
@@ -209,44 +265,44 @@ class HelloComputed
|
|
209
265
|
horizontal_spacing 20
|
210
266
|
vertical_spacing 10
|
211
267
|
}
|
212
|
-
label {text
|
268
|
+
label {text 'First &Name: '}
|
213
269
|
text {
|
214
270
|
text bind(@contact, :first_name)
|
215
271
|
layout_data {
|
216
|
-
|
217
|
-
|
272
|
+
horizontal_alignment :fill
|
273
|
+
grab_excess_horizontal_space true
|
218
274
|
}
|
219
275
|
}
|
220
|
-
label {text
|
276
|
+
label {text '&Last Name: '}
|
221
277
|
text {
|
222
278
|
text bind(@contact, :last_name)
|
223
279
|
layout_data {
|
224
|
-
|
225
|
-
|
280
|
+
horizontal_alignment :fill
|
281
|
+
grab_excess_horizontal_space true
|
226
282
|
}
|
227
283
|
}
|
228
|
-
label {text
|
284
|
+
label {text '&Year of Birth: '}
|
229
285
|
text {
|
230
286
|
text bind(@contact, :year_of_birth)
|
231
287
|
layout_data {
|
232
|
-
|
233
|
-
|
288
|
+
horizontal_alignment :fill
|
289
|
+
grab_excess_horizontal_space true
|
234
290
|
}
|
235
291
|
}
|
236
|
-
label {text
|
292
|
+
label {text 'Name: '}
|
237
293
|
label {
|
238
294
|
text bind(@contact, :name, computed_by: [:first_name, :last_name])
|
239
295
|
layout_data {
|
240
|
-
|
241
|
-
|
296
|
+
horizontal_alignment :fill
|
297
|
+
grab_excess_horizontal_space true
|
242
298
|
}
|
243
299
|
}
|
244
|
-
label {text
|
300
|
+
label {text 'Age: '}
|
245
301
|
label {
|
246
302
|
text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
|
247
303
|
layout_data {
|
248
|
-
|
249
|
-
|
304
|
+
horizontal_alignment :fill
|
305
|
+
grab_excess_horizontal_space true
|
250
306
|
}
|
251
307
|
}
|
252
308
|
}
|
@@ -258,7 +314,7 @@ HelloComputed.new.launch
|
|
258
314
|
```
|
259
315
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
260
316
|
|
261
|
-

|
262
318
|
|
263
319
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
264
320
|
|
@@ -273,9 +329,16 @@ You should see "Hello, Computed!"
|
|
273
329
|
|
274
330
|

|
275
331
|
|
276
|
-
|
332
|
+
#### Hello, List Single Selection!
|
333
|
+
|
334
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
277
335
|
|
278
|
-
|
336
|
+
|
337
|
+
```ruby
|
338
|
+
require 'samples/hello/hello_list_single_selection'
|
339
|
+
```
|
340
|
+
|
341
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
279
342
|
|
280
343
|
```ruby
|
281
344
|
class Person
|
@@ -315,7 +378,7 @@ HelloListSingleSelection.new.launch
|
|
315
378
|
```
|
316
379
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
317
380
|
|
318
|
-

|
319
382
|
|
320
383
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
321
384
|
|
@@ -330,9 +393,15 @@ You should see "Hello, List Single Selection!"
|
|
330
393
|
|
331
394
|

|
332
395
|
|
333
|
-
|
396
|
+
#### Hello, List Multi Selection!
|
397
|
+
|
398
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
334
399
|
|
335
|
-
|
400
|
+
```ruby
|
401
|
+
require 'samples/hello/hello_list_multi_selection'
|
402
|
+
```
|
403
|
+
|
404
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
336
405
|
|
337
406
|
```ruby
|
338
407
|
class Person
|
@@ -382,7 +451,7 @@ HelloListMultiSelection.new.launch
|
|
382
451
|
```
|
383
452
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
384
453
|
|
385
|
-

|
386
455
|
|
387
456
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
388
457
|
|
@@ -397,9 +466,15 @@ You should see "Hello, List Multi Selection!"
|
|
397
466
|
|
398
467
|

|
399
468
|
|
400
|
-
|
469
|
+
#### Hello, Browser!
|
470
|
+
|
471
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
472
|
+
|
473
|
+
```ruby
|
474
|
+
require 'samples/hello/hello_browser'
|
475
|
+
```
|
401
476
|
|
402
|
-
|
477
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
403
478
|
|
404
479
|
```ruby
|
405
480
|
include Glimmer
|
@@ -413,7 +488,7 @@ shell {
|
|
413
488
|
```
|
414
489
|
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
415
490
|
|
416
|
-

|
417
492
|
|
418
493
|
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
419
494
|
|
@@ -428,6 +503,870 @@ You should see "Hello, Browser!"
|
|
428
503
|
|
429
504
|

|
430
505
|
|
506
|
+
#### Hello, Tab!
|
507
|
+
|
508
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
509
|
+
|
510
|
+
```ruby
|
511
|
+
require 'samples/hello/hello_tab'
|
512
|
+
```
|
513
|
+
|
514
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
515
|
+
|
516
|
+
```ruby
|
517
|
+
class HelloTab
|
518
|
+
include Glimmer
|
519
|
+
def launch
|
520
|
+
shell {
|
521
|
+
text "Hello, Tab!"
|
522
|
+
tab_folder {
|
523
|
+
tab_item {
|
524
|
+
text "English"
|
525
|
+
label {
|
526
|
+
text "Hello, World!"
|
527
|
+
}
|
528
|
+
}
|
529
|
+
tab_item {
|
530
|
+
text "French"
|
531
|
+
label {
|
532
|
+
text "Bonjour, Univers!"
|
533
|
+
}
|
534
|
+
}
|
535
|
+
}
|
536
|
+
}.open
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
HelloTab.new.launch
|
541
|
+
```
|
542
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
543
|
+
|
544
|
+

|
545
|
+

|
546
|
+
|
547
|
+
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
548
|
+
|
549
|
+
Start the Rails server:
|
550
|
+
```
|
551
|
+
rails s
|
552
|
+
```
|
553
|
+
|
554
|
+
Visit `http://localhost:3000`
|
555
|
+
|
556
|
+
You should see "Hello, Tab!"
|
557
|
+
|
558
|
+

|
559
|
+

|
560
|
+
|
561
|
+
### Elaborate Samples
|
562
|
+
|
563
|
+
#### Login
|
564
|
+
|
565
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
566
|
+
|
567
|
+
```ruby
|
568
|
+
require 'samples/elaborate/login'
|
569
|
+
```
|
570
|
+
|
571
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
572
|
+
|
573
|
+
```ruby
|
574
|
+
require "observer"
|
575
|
+
|
576
|
+
#Presents login screen data
|
577
|
+
class LoginPresenter
|
578
|
+
|
579
|
+
attr_accessor :user_name
|
580
|
+
attr_accessor :password
|
581
|
+
attr_accessor :status
|
582
|
+
|
583
|
+
def initialize
|
584
|
+
@user_name = ""
|
585
|
+
@password = ""
|
586
|
+
@status = "Logged Out"
|
587
|
+
end
|
588
|
+
|
589
|
+
def status=(status)
|
590
|
+
@status = status
|
591
|
+
|
592
|
+
#TODO add feature to bind dependent properties to master property (2017-07-25 nested data binding)
|
593
|
+
notify_observers("logged_in")
|
594
|
+
notify_observers("logged_out")
|
595
|
+
end
|
596
|
+
|
597
|
+
def logged_in
|
598
|
+
self.status == "Logged In"
|
599
|
+
end
|
600
|
+
|
601
|
+
def logged_out
|
602
|
+
!self.logged_in
|
603
|
+
end
|
604
|
+
|
605
|
+
def login
|
606
|
+
self.status = "Logged In"
|
607
|
+
end
|
608
|
+
|
609
|
+
def logout
|
610
|
+
self.user_name = ""
|
611
|
+
self.password = ""
|
612
|
+
self.status = "Logged Out"
|
613
|
+
end
|
614
|
+
|
615
|
+
end
|
616
|
+
|
617
|
+
#Login screen
|
618
|
+
class Login
|
619
|
+
include Glimmer
|
620
|
+
|
621
|
+
def launch
|
622
|
+
presenter = LoginPresenter.new
|
623
|
+
@shell = shell {
|
624
|
+
text "Login"
|
625
|
+
composite {
|
626
|
+
grid_layout 2, false #two columns with differing widths
|
627
|
+
|
628
|
+
label { text "Username:" } # goes in column 1
|
629
|
+
text { # goes in column 2
|
630
|
+
text bind(presenter, :user_name)
|
631
|
+
enabled bind(presenter, :logged_out)
|
632
|
+
}
|
633
|
+
|
634
|
+
label { text "Password:" }
|
635
|
+
text(:password, :border) {
|
636
|
+
text bind(presenter, :password)
|
637
|
+
enabled bind(presenter, :logged_out)
|
638
|
+
}
|
639
|
+
|
640
|
+
label { text "Status:" }
|
641
|
+
label { text bind(presenter, :status) }
|
642
|
+
|
643
|
+
button {
|
644
|
+
text "Login"
|
645
|
+
enabled bind(presenter, :logged_out)
|
646
|
+
on_widget_selected { presenter.login }
|
647
|
+
}
|
648
|
+
|
649
|
+
button {
|
650
|
+
text "Logout"
|
651
|
+
enabled bind(presenter, :logged_in)
|
652
|
+
on_widget_selected { presenter.logout }
|
653
|
+
}
|
654
|
+
}
|
655
|
+
}
|
656
|
+
@shell.open
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
Login.new.launch
|
661
|
+
```
|
662
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
663
|
+
|
664
|
+

|
665
|
+

|
666
|
+

|
667
|
+
|
668
|
+
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
669
|
+
|
670
|
+
Start the Rails server:
|
671
|
+
```
|
672
|
+
rails s
|
673
|
+
```
|
674
|
+
|
675
|
+
Visit `http://localhost:3000`
|
676
|
+
|
677
|
+
You should see "Login" dialog
|
678
|
+
|
679
|
+

|
680
|
+

|
681
|
+

|
682
|
+
|
683
|
+
#### Tic Tac Toe
|
684
|
+
|
685
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
686
|
+
|
687
|
+
```ruby
|
688
|
+
require 'samples/elaborate/tic_tac_toe'
|
689
|
+
```
|
690
|
+
|
691
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
692
|
+
|
693
|
+
```ruby
|
694
|
+
class TicTacToe
|
695
|
+
class Cell
|
696
|
+
EMPTY = ""
|
697
|
+
attr_accessor :sign, :empty
|
698
|
+
|
699
|
+
def initialize
|
700
|
+
reset
|
701
|
+
end
|
702
|
+
|
703
|
+
def mark(sign)
|
704
|
+
self.sign = sign
|
705
|
+
end
|
706
|
+
|
707
|
+
def reset
|
708
|
+
self.sign = EMPTY
|
709
|
+
end
|
710
|
+
|
711
|
+
def sign=(sign_symbol)
|
712
|
+
@sign = sign_symbol
|
713
|
+
self.empty = sign == EMPTY
|
714
|
+
end
|
715
|
+
|
716
|
+
def marked
|
717
|
+
!empty
|
718
|
+
end
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
class TicTacToe
|
723
|
+
class Board
|
724
|
+
DRAW = :draw
|
725
|
+
IN_PROGRESS = :in_progress
|
726
|
+
WIN = :win
|
727
|
+
attr :winning_sign
|
728
|
+
attr_accessor :game_status
|
729
|
+
|
730
|
+
def initialize
|
731
|
+
@sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
|
732
|
+
build_grid
|
733
|
+
@winning_sign = Cell::EMPTY
|
734
|
+
@game_status = IN_PROGRESS
|
735
|
+
end
|
736
|
+
|
737
|
+
#row and column numbers are 1-based
|
738
|
+
def mark(row, column)
|
739
|
+
self[row, column].mark(current_sign)
|
740
|
+
game_over? #updates winning sign
|
741
|
+
end
|
742
|
+
|
743
|
+
def current_sign
|
744
|
+
@current_sign = @sign_state_machine[@current_sign]
|
745
|
+
end
|
746
|
+
|
747
|
+
def [](row, column)
|
748
|
+
@grid[row-1][column-1]
|
749
|
+
end
|
750
|
+
|
751
|
+
def game_over?
|
752
|
+
win? or draw?
|
753
|
+
end
|
754
|
+
|
755
|
+
def win?
|
756
|
+
win = (row_win? or column_win? or diagonal_win?)
|
757
|
+
self.game_status=WIN if win
|
758
|
+
win
|
759
|
+
end
|
760
|
+
|
761
|
+
def reset
|
762
|
+
(1..3).each do |row|
|
763
|
+
(1..3).each do |column|
|
764
|
+
self[row, column].reset
|
765
|
+
end
|
766
|
+
end
|
767
|
+
@winning_sign = Cell::EMPTY
|
768
|
+
@current_sign = nil
|
769
|
+
self.game_status=IN_PROGRESS
|
770
|
+
end
|
771
|
+
|
772
|
+
private
|
773
|
+
|
774
|
+
def build_grid
|
775
|
+
@grid = []
|
776
|
+
3.times do |row_index| #0-based
|
777
|
+
@grid << []
|
778
|
+
3.times { @grid[row_index] << Cell.new }
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
def row_win?
|
783
|
+
(1..3).each do |row|
|
784
|
+
if row_has_same_sign(row)
|
785
|
+
@winning_sign = self[row, 1].sign
|
786
|
+
return true
|
787
|
+
end
|
788
|
+
end
|
789
|
+
false
|
790
|
+
end
|
791
|
+
|
792
|
+
def column_win?
|
793
|
+
(1..3).each do |column|
|
794
|
+
if column_has_same_sign(column)
|
795
|
+
@winning_sign = self[1, column].sign
|
796
|
+
return true
|
797
|
+
end
|
798
|
+
end
|
799
|
+
false
|
800
|
+
end
|
801
|
+
|
802
|
+
#needs refactoring if we ever decide to make the board size dynamic
|
803
|
+
def diagonal_win?
|
804
|
+
if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
|
805
|
+
@winning_sign = self[1, 1].sign
|
806
|
+
return true
|
807
|
+
end
|
808
|
+
if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
|
809
|
+
@winning_sign = self[3, 1].sign
|
810
|
+
return true
|
811
|
+
end
|
812
|
+
false
|
813
|
+
end
|
814
|
+
|
815
|
+
def draw?
|
816
|
+
@board_full = true
|
817
|
+
3.times do |x|
|
818
|
+
3.times do |y|
|
819
|
+
@board_full = false if self[x, y].empty
|
820
|
+
end
|
821
|
+
end
|
822
|
+
self.game_status = DRAW if @board_full
|
823
|
+
@board_full
|
824
|
+
end
|
825
|
+
|
826
|
+
def row_has_same_sign(number)
|
827
|
+
row_sign = self[number, 1].sign
|
828
|
+
[2, 3].each do |column|
|
829
|
+
return false unless row_sign == (self[number, column].sign)
|
830
|
+
end
|
831
|
+
true if self[number, 1].marked
|
832
|
+
end
|
833
|
+
|
834
|
+
def column_has_same_sign(number)
|
835
|
+
column_sign = self[1, number].sign
|
836
|
+
[2, 3].each do |row|
|
837
|
+
return false unless column_sign == (self[row, number].sign)
|
838
|
+
end
|
839
|
+
true if self[1, number].marked
|
840
|
+
end
|
841
|
+
|
842
|
+
end
|
843
|
+
end
|
844
|
+
|
845
|
+
class TicTacToe
|
846
|
+
include Glimmer
|
847
|
+
|
848
|
+
def initialize
|
849
|
+
@tic_tac_toe_board = Board.new
|
850
|
+
@shell = shell {
|
851
|
+
text "Tic-Tac-Toe"
|
852
|
+
composite {
|
853
|
+
grid_layout 3, true
|
854
|
+
(1..3).each { |row|
|
855
|
+
(1..3).each { |column|
|
856
|
+
button {
|
857
|
+
layout_data :fill, :fill, true, true
|
858
|
+
text bind(@tic_tac_toe_board[row, column], :sign)
|
859
|
+
enabled bind(@tic_tac_toe_board[row, column], :empty)
|
860
|
+
on_widget_selected {
|
861
|
+
@tic_tac_toe_board.mark(row, column)
|
862
|
+
}
|
863
|
+
}
|
864
|
+
}
|
865
|
+
}
|
866
|
+
}
|
867
|
+
}
|
868
|
+
observe(@tic_tac_toe_board, :game_status) { |game_status|
|
869
|
+
display_win_message if game_status == Board::WIN
|
870
|
+
display_draw_message if game_status == Board::DRAW
|
871
|
+
}
|
872
|
+
end
|
873
|
+
|
874
|
+
def display_win_message
|
875
|
+
display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
|
876
|
+
end
|
877
|
+
|
878
|
+
def display_draw_message
|
879
|
+
display_game_over_message("Draw!")
|
880
|
+
end
|
881
|
+
|
882
|
+
def display_game_over_message(message_text)
|
883
|
+
message_box(@shell) {
|
884
|
+
text 'Game Over'
|
885
|
+
message message_text
|
886
|
+
}.open
|
887
|
+
@tic_tac_toe_board.reset
|
888
|
+
end
|
889
|
+
|
890
|
+
def open
|
891
|
+
@shell.open
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
TicTacToe.new.open
|
896
|
+
```
|
897
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
898
|
+
|
899
|
+

|
900
|
+

|
901
|
+

|
902
|
+
|
903
|
+
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
904
|
+
|
905
|
+
Start the Rails server:
|
906
|
+
```
|
907
|
+
rails s
|
908
|
+
```
|
909
|
+
|
910
|
+
Visit `http://localhost:3000`
|
911
|
+
|
912
|
+
You should see "Tic Tac Toe"
|
913
|
+
|
914
|
+

|
915
|
+

|
916
|
+

|
917
|
+
|
918
|
+
#### Contact Manager
|
919
|
+
|
920
|
+
Add the following require statement to `app/assets/javascripts/application.rb`
|
921
|
+
|
922
|
+
```ruby
|
923
|
+
require 'samples/elaborate/contact_manager'
|
924
|
+
```
|
925
|
+
|
926
|
+
Or add the Glimmer code directly if you prefer to play around with it:
|
927
|
+
|
928
|
+
```ruby
|
929
|
+
class ContactManager
|
930
|
+
class Contact
|
931
|
+
attr_accessor :first_name, :last_name, :email
|
932
|
+
|
933
|
+
def initialize(attribute_map)
|
934
|
+
@first_name = attribute_map[:first_name]
|
935
|
+
@last_name = attribute_map[:last_name]
|
936
|
+
@email = attribute_map[:email]
|
937
|
+
end
|
938
|
+
end
|
939
|
+
end
|
940
|
+
|
941
|
+
class ContactManager
|
942
|
+
class ContactRepository
|
943
|
+
NAMES_FIRST = %w[
|
944
|
+
Liam
|
945
|
+
Noah
|
946
|
+
William
|
947
|
+
James
|
948
|
+
Oliver
|
949
|
+
Benjamin
|
950
|
+
Elijah
|
951
|
+
Lucas
|
952
|
+
Mason
|
953
|
+
Logan
|
954
|
+
Alexander
|
955
|
+
Ethan
|
956
|
+
Jacob
|
957
|
+
Michael
|
958
|
+
Daniel
|
959
|
+
Henry
|
960
|
+
Jackson
|
961
|
+
Sebastian
|
962
|
+
Aiden
|
963
|
+
Matthew
|
964
|
+
Samuel
|
965
|
+
David
|
966
|
+
Joseph
|
967
|
+
Carter
|
968
|
+
Owen
|
969
|
+
Wyatt
|
970
|
+
John
|
971
|
+
Jack
|
972
|
+
Luke
|
973
|
+
Jayden
|
974
|
+
Dylan
|
975
|
+
Grayson
|
976
|
+
Levi
|
977
|
+
Isaac
|
978
|
+
Gabriel
|
979
|
+
Julian
|
980
|
+
Mateo
|
981
|
+
Anthony
|
982
|
+
Jaxon
|
983
|
+
Lincoln
|
984
|
+
Joshua
|
985
|
+
Christopher
|
986
|
+
Andrew
|
987
|
+
Theodore
|
988
|
+
Caleb
|
989
|
+
Ryan
|
990
|
+
Asher
|
991
|
+
Nathan
|
992
|
+
Thomas
|
993
|
+
Leo
|
994
|
+
Isaiah
|
995
|
+
Charles
|
996
|
+
Josiah
|
997
|
+
Hudson
|
998
|
+
Christian
|
999
|
+
Hunter
|
1000
|
+
Connor
|
1001
|
+
Eli
|
1002
|
+
Ezra
|
1003
|
+
Aaron
|
1004
|
+
Landon
|
1005
|
+
Adrian
|
1006
|
+
Jonathan
|
1007
|
+
Nolan
|
1008
|
+
Jeremiah
|
1009
|
+
Easton
|
1010
|
+
Elias
|
1011
|
+
Colton
|
1012
|
+
Cameron
|
1013
|
+
Carson
|
1014
|
+
Robert
|
1015
|
+
Angel
|
1016
|
+
Maverick
|
1017
|
+
Nicholas
|
1018
|
+
Dominic
|
1019
|
+
Jaxson
|
1020
|
+
Greyson
|
1021
|
+
Adam
|
1022
|
+
Ian
|
1023
|
+
Austin
|
1024
|
+
Santiago
|
1025
|
+
Jordan
|
1026
|
+
Cooper
|
1027
|
+
Brayden
|
1028
|
+
Roman
|
1029
|
+
Evan
|
1030
|
+
Ezekiel
|
1031
|
+
Xaviar
|
1032
|
+
Jose
|
1033
|
+
Jace
|
1034
|
+
Jameson
|
1035
|
+
Leonardo
|
1036
|
+
Axel
|
1037
|
+
Everett
|
1038
|
+
Kayden
|
1039
|
+
Miles
|
1040
|
+
Sawyer
|
1041
|
+
Jason
|
1042
|
+
Emma
|
1043
|
+
Olivia
|
1044
|
+
Ava
|
1045
|
+
Isabella
|
1046
|
+
Sophia
|
1047
|
+
Charlotte
|
1048
|
+
Mia
|
1049
|
+
Amelia
|
1050
|
+
Harper
|
1051
|
+
Evelyn
|
1052
|
+
Abigail
|
1053
|
+
Emily
|
1054
|
+
Elizabeth
|
1055
|
+
Mila
|
1056
|
+
Ella
|
1057
|
+
Avery
|
1058
|
+
Sofia
|
1059
|
+
Camila
|
1060
|
+
Aria
|
1061
|
+
Scarlett
|
1062
|
+
Victoria
|
1063
|
+
Madison
|
1064
|
+
Luna
|
1065
|
+
Grace
|
1066
|
+
Chloe
|
1067
|
+
Penelope
|
1068
|
+
Layla
|
1069
|
+
Riley
|
1070
|
+
Zoey
|
1071
|
+
Nora
|
1072
|
+
Lily
|
1073
|
+
Eleanor
|
1074
|
+
Hannah
|
1075
|
+
Lillian
|
1076
|
+
Addison
|
1077
|
+
Aubrey
|
1078
|
+
Ellie
|
1079
|
+
Stella
|
1080
|
+
Natalie
|
1081
|
+
Zoe
|
1082
|
+
Leah
|
1083
|
+
Hazel
|
1084
|
+
Violet
|
1085
|
+
Aurora
|
1086
|
+
Savannah
|
1087
|
+
Audrey
|
1088
|
+
Brooklyn
|
1089
|
+
Bella
|
1090
|
+
Claire
|
1091
|
+
Skylar
|
1092
|
+
Lucy
|
1093
|
+
Paisley
|
1094
|
+
Everly
|
1095
|
+
Anna
|
1096
|
+
Caroline
|
1097
|
+
Nova
|
1098
|
+
Genesis
|
1099
|
+
Emilia
|
1100
|
+
Kennedy
|
1101
|
+
Samantha
|
1102
|
+
Maya
|
1103
|
+
Willow
|
1104
|
+
Kinsley
|
1105
|
+
Naomi
|
1106
|
+
Aaliyah
|
1107
|
+
Elena
|
1108
|
+
Sarah
|
1109
|
+
Ariana
|
1110
|
+
Allison
|
1111
|
+
Gabriella
|
1112
|
+
Alice
|
1113
|
+
Madelyn
|
1114
|
+
Cora
|
1115
|
+
Ruby
|
1116
|
+
Eva
|
1117
|
+
Serenity
|
1118
|
+
Autumn
|
1119
|
+
Adeline
|
1120
|
+
Hailey
|
1121
|
+
Gianna
|
1122
|
+
Valentina
|
1123
|
+
Isla
|
1124
|
+
Eliana
|
1125
|
+
Quinn
|
1126
|
+
Nevaeh
|
1127
|
+
Ivy
|
1128
|
+
Sadie
|
1129
|
+
Piper
|
1130
|
+
Lydia
|
1131
|
+
Alexa
|
1132
|
+
Josephine
|
1133
|
+
Emery
|
1134
|
+
Julia
|
1135
|
+
Delilah
|
1136
|
+
Arianna
|
1137
|
+
Vivian
|
1138
|
+
Kaylee
|
1139
|
+
Sophie
|
1140
|
+
Brielle
|
1141
|
+
Madeline
|
1142
|
+
]
|
1143
|
+
NAMES_LAST = %w[
|
1144
|
+
Smith
|
1145
|
+
Johnson
|
1146
|
+
Williams
|
1147
|
+
Brown
|
1148
|
+
Jones
|
1149
|
+
Miller
|
1150
|
+
Davis
|
1151
|
+
Wilson
|
1152
|
+
Anderson
|
1153
|
+
Taylor
|
1154
|
+
]
|
1155
|
+
def initialize(contacts = nil)
|
1156
|
+
@contacts = contacts || 1000.times.map do |n|
|
1157
|
+
random_first_name_index = (rand*NAMES_FIRST.size).to_i
|
1158
|
+
random_last_name_index = (rand*NAMES_LAST.size).to_i
|
1159
|
+
first_name = NAMES_FIRST[random_first_name_index]
|
1160
|
+
last_name = NAMES_LAST[random_last_name_index]
|
1161
|
+
email = "#{first_name}@#{last_name}.com".downcase
|
1162
|
+
Contact.new(
|
1163
|
+
first_name: first_name,
|
1164
|
+
last_name: last_name,
|
1165
|
+
email: email
|
1166
|
+
)
|
1167
|
+
end
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
def find(attribute_filter_map)
|
1171
|
+
@contacts.find_all do |contact|
|
1172
|
+
match = true
|
1173
|
+
attribute_filter_map.keys.each do |attribute_name|
|
1174
|
+
contact_value = contact.send(attribute_name).downcase
|
1175
|
+
filter_value = attribute_filter_map[attribute_name].downcase
|
1176
|
+
match = false unless contact_value.match(filter_value)
|
1177
|
+
end
|
1178
|
+
match
|
1179
|
+
end
|
1180
|
+
end
|
1181
|
+
end
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
class ContactManager
|
1185
|
+
class ContactManagerPresenter
|
1186
|
+
attr_accessor :results
|
1187
|
+
@@contact_attributes = [:first_name, :last_name, :email]
|
1188
|
+
@@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
|
1189
|
+
|
1190
|
+
def initialize(contact_repository = nil)
|
1191
|
+
@contact_repository = contact_repository || ContactRepository.new
|
1192
|
+
@results = []
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
def list
|
1196
|
+
self.results = @contact_repository.find({})
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
def find
|
1200
|
+
filter_map = {}
|
1201
|
+
@@contact_attributes.each do |attribute_name|
|
1202
|
+
filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
|
1203
|
+
end
|
1204
|
+
self.results = @contact_repository.find(filter_map)
|
1205
|
+
@sort_attribute_name = nil
|
1206
|
+
@sort_direction_ascending = nil
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
def toggle_sort(attribute_name)
|
1210
|
+
@sort_attribute_name = attribute_name
|
1211
|
+
@sort_direction_ascending = !@sort_direction_ascending
|
1212
|
+
sorted_results = self.results.sort_by {|contact| contact.send(attribute_name).downcase}
|
1213
|
+
sorted_results = sorted_results.reverse unless @sort_direction_ascending
|
1214
|
+
self.results = sorted_results
|
1215
|
+
end
|
1216
|
+
end
|
1217
|
+
end
|
1218
|
+
|
1219
|
+
class ContactManager
|
1220
|
+
include Glimmer
|
1221
|
+
|
1222
|
+
def initialize
|
1223
|
+
@contact_manager_presenter = ContactManagerPresenter.new
|
1224
|
+
@contact_manager_presenter.list
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
def launch
|
1228
|
+
shell {
|
1229
|
+
text "Contact Manager"
|
1230
|
+
composite {
|
1231
|
+
composite {
|
1232
|
+
grid_layout 2, false
|
1233
|
+
label {text "First &Name: "}
|
1234
|
+
text {
|
1235
|
+
text bind(@contact_manager_presenter, :first_name)
|
1236
|
+
on_key_pressed {|key_event|
|
1237
|
+
@contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
|
1238
|
+
}
|
1239
|
+
}
|
1240
|
+
label {text "&Last Name: "}
|
1241
|
+
text {
|
1242
|
+
text bind(@contact_manager_presenter, :last_name)
|
1243
|
+
on_key_pressed {|key_event|
|
1244
|
+
@contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
|
1245
|
+
}
|
1246
|
+
}
|
1247
|
+
label {text "&Email: "}
|
1248
|
+
text {
|
1249
|
+
text bind(@contact_manager_presenter, :email)
|
1250
|
+
on_key_pressed {|key_event|
|
1251
|
+
@contact_manager_presenter.find if key_event.keyCode == Glimmer::SWT::SWTProxy[:cr]
|
1252
|
+
}
|
1253
|
+
}
|
1254
|
+
composite {
|
1255
|
+
grid_layout 2, false
|
1256
|
+
button {
|
1257
|
+
text "&Find"
|
1258
|
+
on_widget_selected {
|
1259
|
+
@contact_manager_presenter.find
|
1260
|
+
}
|
1261
|
+
}
|
1262
|
+
button {
|
1263
|
+
text "&List All"
|
1264
|
+
on_widget_selected {
|
1265
|
+
@contact_manager_presenter.list
|
1266
|
+
}
|
1267
|
+
}
|
1268
|
+
}
|
1269
|
+
}
|
1270
|
+
|
1271
|
+
table(:multi) { |table_proxy|
|
1272
|
+
layout_data {
|
1273
|
+
horizontal_alignment :fill
|
1274
|
+
vertical_alignment :fill
|
1275
|
+
grab_excess_horizontal_space true
|
1276
|
+
grab_excess_vertical_space true
|
1277
|
+
height_hint 200
|
1278
|
+
}
|
1279
|
+
table_column {
|
1280
|
+
text "First Name"
|
1281
|
+
width 80
|
1282
|
+
on_widget_selected {
|
1283
|
+
@contact_manager_presenter.toggle_sort(:first_name)
|
1284
|
+
}
|
1285
|
+
}
|
1286
|
+
table_column {
|
1287
|
+
text "Last Name"
|
1288
|
+
width 80
|
1289
|
+
on_widget_selected {
|
1290
|
+
@contact_manager_presenter.toggle_sort(:last_name)
|
1291
|
+
}
|
1292
|
+
}
|
1293
|
+
table_column {
|
1294
|
+
text "Email"
|
1295
|
+
width 200
|
1296
|
+
on_widget_selected {
|
1297
|
+
@contact_manager_presenter.toggle_sort(:email)
|
1298
|
+
}
|
1299
|
+
}
|
1300
|
+
items bind(@contact_manager_presenter, :results), column_properties(:first_name, :last_name, :email)
|
1301
|
+
on_mouse_down { |event|
|
1302
|
+
table_proxy.edit_table_item(event.table_item, event.column_index)
|
1303
|
+
}
|
1304
|
+
}
|
1305
|
+
}
|
1306
|
+
}.open
|
1307
|
+
end
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
ContactManager.new.launch
|
1311
|
+
|
1312
|
+
```
|
1313
|
+
Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
|
1314
|
+
|
1315
|
+
Glimmer DSL for SWT Contact Manager
|
1316
|
+
|
1317
|
+

|
1318
|
+
|
1319
|
+
Glimmer DSL for SWT Contact Manager Find
|
1320
|
+
|
1321
|
+

|
1322
|
+
|
1323
|
+
Glimmer DSL for SWT Contact Manager Edit Started
|
1324
|
+
|
1325
|
+

|
1326
|
+
|
1327
|
+
Glimmer DSL for SWT Contact Manager Edit In Progress
|
1328
|
+
|
1329
|
+

|
1330
|
+
|
1331
|
+
Glimmer DSL for SWT Contact Manager Edit Done
|
1332
|
+
|
1333
|
+

|
1334
|
+
|
1335
|
+
Glimmer app on the web (using `glimmer-dsl-opal` gem):
|
1336
|
+
|
1337
|
+
Start the Rails server:
|
1338
|
+
```
|
1339
|
+
rails s
|
1340
|
+
```
|
1341
|
+
|
1342
|
+
Visit `http://localhost:3000`
|
1343
|
+
|
1344
|
+
You should see "Tic Tac Toe"
|
1345
|
+
|
1346
|
+
Glimmer DSL for Opal Contact Manager
|
1347
|
+
|
1348
|
+

|
1349
|
+
|
1350
|
+
Glimmer DSL for Opal Contact Manager Find
|
1351
|
+
|
1352
|
+

|
1353
|
+
|
1354
|
+
Glimmer DSL for Opal Contact Manager Edit Started
|
1355
|
+
|
1356
|
+

|
1357
|
+
|
1358
|
+
Glimmer DSL for Opal Contact Manager Edit In Progress
|
1359
|
+
|
1360
|
+

|
1361
|
+
|
1362
|
+
Glimmer DSL for Opal Contact Manager Edit Done
|
1363
|
+
|
1364
|
+

|
1365
|
+
|
1366
|
+
## Sample App
|
1367
|
+
|
1368
|
+
[https://github.com/AndyObtiva/sample-glimmer-dsl-opal-rails5-app](https://github.com/AndyObtiva/sample-glimmer-dsl-opal-rails5-app)
|
1369
|
+
|
431
1370
|
## Help
|
432
1371
|
|
433
1372
|
### Issues
|
@@ -462,5 +1401,11 @@ These features have been suggested. You might see them in a future version of Gl
|
|
462
1401
|
|
463
1402
|
## License
|
464
1403
|
|
465
|
-
|
466
|
-
|
1404
|
+
[MIT](https://opensource.org/licenses/MIT)
|
1405
|
+
|
1406
|
+
Copyright (c) 2020 - Andy Maleh.
|
1407
|
+
See [LICENSE.txt](LICENSE.txt) for further details.
|
1408
|
+
|
1409
|
+
--
|
1410
|
+
|
1411
|
+
[<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=40 />](https://github.com/AndyObtiva/glimmer) Built for [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library).
|