glimmer 0.4.5 → 0.4.6
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/README.markdown +331 -71
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53c846877535c288cc80b8c2972b14f5fd961b6e3e51f744278e8c6da47cfe6d
|
4
|
+
data.tar.gz: 4be53a6c16f2a9ae9c6101ca4726b576bec5e17dae05f55d64c0714ab13ab6fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f717afdd64e347b706a3d909474b579031c4a235d4881c490958d7c743892f363b64ae29f40bf8401506f327764163c4d08660cb6a29d8507b7077f11e06c29
|
7
|
+
data.tar.gz: c2b5de327710faa1e6dde42e5ef011af9b5375b87c030edeea40a0e672c7abd8a848dd1f8f48da9deeee903be27c9cc8e79e4a8a404a31cbf522be11dad35ee3
|
data/README.markdown
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Glimmer (
|
1
|
+
# Glimmer (JRuby Desktop UI DSL + Data-Binding)
|
2
2
|
[](https://coveralls.io/github/AndyObtiva/glimmer?branch=master)
|
3
3
|
|
4
4
|
Glimmer is a cross-platform Ruby desktop development library. Glimmer's main innovation is a JRuby DSL that enables easy and efficient authoring of desktop application user-interfaces while relying on the robust platform-independent Eclipse SWT library. Glimmer additionally innovates by having built-in desktop UI data-binding support to greatly facilitate synchronizing the UI with domain models. As a result, that achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about UI concerns, or alternatively drive development UI-first, and then write clean business components test-first afterward.
|
@@ -83,10 +83,20 @@ Glimmer runs on the following platforms:
|
|
83
83
|
- Windows
|
84
84
|
- Linux
|
85
85
|
|
86
|
+
SWT uses Win32 on Windows, Cocoa on Mac, and GTK on Linux according to Eclipse WIKI:
|
87
|
+
|
88
|
+
https://wiki.eclipse.org/SWT/Devel/Gtk/Dev_guide#Win32.2FCocoa.2FGTK
|
89
|
+
|
90
|
+
The SWT FAQ has further details:
|
91
|
+
|
92
|
+
https://www.eclipse.org/swt/faq.php
|
93
|
+
|
94
|
+
|
86
95
|
## Pre-requisites
|
87
96
|
|
88
97
|
* Java SE Runtime Environment 7 or higher (find at https://www.oracle.com/java/technologies/javase-downloads.html)
|
89
98
|
* JRuby 9.2.10.0 (supporting Ruby 2.5.x syntax) (find at https://www.jruby.org/download)
|
99
|
+
* SWT 4.14 (comes included in Glimmer)
|
90
100
|
|
91
101
|
On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
|
92
102
|
|
@@ -102,14 +112,14 @@ Please follow these instructions to make the `glimmer` command available on your
|
|
102
112
|
|
103
113
|
Run this command to install directly:
|
104
114
|
```
|
105
|
-
jgem install glimmer -v 0.4.
|
115
|
+
jgem install glimmer -v 0.4.6
|
106
116
|
```
|
107
117
|
|
108
118
|
### Option 2: Bundler
|
109
119
|
|
110
120
|
Add the following to `Gemfile`:
|
111
121
|
```
|
112
|
-
gem 'glimmer', '~> 0.4.
|
122
|
+
gem 'glimmer', '~> 0.4.6'
|
113
123
|
```
|
114
124
|
|
115
125
|
And, then run:
|
@@ -137,21 +147,99 @@ This runs the Glimmer application hello_world.rb
|
|
137
147
|
|
138
148
|
### Widgets
|
139
149
|
|
140
|
-
Glimmer UIs (user interfaces) are modeled with widgets
|
150
|
+
Glimmer UIs (user interfaces) are modeled with widgets, which are wrappers around the SWT library widgets found here:
|
151
|
+
|
152
|
+
https://www.eclipse.org/swt/widgets/
|
153
|
+
|
154
|
+
This screenshot taken from the link above should give a glimpse of how SWT widgets look and feel:
|
155
|
+
|
156
|
+

|
141
157
|
|
142
|
-
In Glimmer DSL, widgets are declared with lowercase underscored
|
158
|
+
In Glimmer DSL, widgets are declared with lowercase underscored names mirroring their SWT names minus the package name:
|
143
159
|
|
144
|
-
|
160
|
+
- `shell` instantiates `org.eclipse.swt.widgets.Shell`
|
161
|
+
- `text` instantiates `org.eclipse.swt.widgets.Text`
|
162
|
+
- `button` instantiates `org.eclipse.swt.widgets.Button`
|
163
|
+
- `label` instantiates `org.eclipse.swt.widgets.Label`
|
164
|
+
- `composite` instantiates `org.eclipse.swt.widgets.Composite`
|
165
|
+
- `tab_folder` instantiates `org.eclipse.swt.widgets.TabFolder`
|
166
|
+
- `tab_item` instantiates `org.eclipse.swt.widgets.TabItem`
|
167
|
+
- `table` instantiates `org.eclipse.swt.widgets.Table`
|
168
|
+
- `table_column` instantiates `org.eclipse.swt.widgets.TableColumn`
|
169
|
+
- `tree` instantiates `org.eclipse.swt.widgets.Tree`
|
170
|
+
- `combo` instantiates `org.eclipse.swt.widgets.Combo`
|
171
|
+
- `list` instantiates `org.eclipse.swt.widgets.List`
|
145
172
|
|
146
|
-
|
147
|
-
- `button`: wrapper for `org.eclipse.swt.widgets.Button`
|
148
|
-
- `label`: wrapper for `org.eclipse.swt.widgets.Label`
|
149
|
-
- `tab_folder`: wrapper for `org.eclipse.swt.widgets.TabFolder`
|
150
|
-
- `tab_item`: wrapper for `org.eclipse.swt.widgets.TabItem`
|
151
|
-
- `table`: wrapper for `org.eclipse.swt.widgets.Table`
|
152
|
-
- `table_column`: wrapper for `org.eclipse.swt.widgets.TableColumn`
|
153
|
-
- `tree`: wrapper for `org.eclipse.swt.widgets.Tree`
|
173
|
+
A **widget** name is followed by a Ruby block that contains the widget **properties** and **content**. Optionally, an SWT **style** ***argument*** may also be passed (see [next section](#widget-styles) for details).
|
154
174
|
|
175
|
+
For example, if we were to revisit `hello_world.rb` above:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
include Glimmer
|
179
|
+
|
180
|
+
shell {
|
181
|
+
text "Glimmer"
|
182
|
+
label {
|
183
|
+
text "Hello World!"
|
184
|
+
}
|
185
|
+
}.open
|
186
|
+
```
|
187
|
+
|
188
|
+
Note that `shell` instantiates the outer shell **widget**, in other words, the window that houses all of the desktop graphical user interface.
|
189
|
+
|
190
|
+
`shell` is then followed by a ***block*** that contains
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
text "Glimmer" # text property of shell
|
194
|
+
label { # label widget declaration
|
195
|
+
text "Hello World!" # text property of label
|
196
|
+
}
|
197
|
+
```
|
198
|
+
|
199
|
+
The first line declares a **property** called `text`, which sets the title of the shell (window) to `"Glimmer"`. **Properties** always have ***arguments***, such as the text `"Glimmer"` in this case, and do **NOT** have a ***block***.
|
200
|
+
|
201
|
+
The second line declares the `label` **widget**, which is followed by a Ruby **content** ***block*** that contains its `text` **property** with value `"Hello World!"`
|
202
|
+
|
203
|
+
Note that The `shell` widget is always the outermost widget containing all others in a Glimmer desktop windowed application.
|
204
|
+
|
205
|
+
After it is declared, a `shell` must be opened with the `#open` method, which can be called on the block directly as in the example above, or by capturing `shell` in a `@shell` variable (shown in example below), and calling `#open` on it independently (recommended in actual apps)
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
@shell = shell {
|
209
|
+
# properties and content
|
210
|
+
}
|
211
|
+
@shell.open
|
212
|
+
```
|
213
|
+
|
214
|
+
It is centered upon initial display and has a minimum width of 130 (can be re-centered when needed with `@shell.center` method after capturing `shell` in a `@shell` variable as per samples)
|
215
|
+
|
216
|
+
Check out the [samples](https://github.com/AndyObtiva/glimmer/tree/master/samples) directory for more examples.
|
217
|
+
|
218
|
+
Example from [hello_tab.rb](https://github.com/AndyObtiva/glimmer/blob/master/samples/hello_tab.rb) sample:
|
219
|
+
|
220
|
+

|
221
|
+
|
222
|
+

|
223
|
+
|
224
|
+
```ruby
|
225
|
+
shell {
|
226
|
+
text "SWT"
|
227
|
+
tab_folder {
|
228
|
+
tab_item {
|
229
|
+
text "Tab 1"
|
230
|
+
label {
|
231
|
+
text "Hello World!"
|
232
|
+
}
|
233
|
+
}
|
234
|
+
tab_item {
|
235
|
+
text "Tab 2"
|
236
|
+
label {
|
237
|
+
text "Bonjour Univers!"
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}.open
|
242
|
+
```
|
155
243
|
|
156
244
|
**Browser Widget**
|
157
245
|
|
@@ -281,6 +369,65 @@ button {
|
|
281
369
|
|
282
370
|
In the above example, the `text` widget `enabled` property was data-bound to `#empty` method on `@tic_tac_toe_board.box(row, column)` (learn more about data-binding below)
|
283
371
|
|
372
|
+
#### Colors
|
373
|
+
|
374
|
+
Colors make up a subset of widget properties. SWT accepts color objects created with RGB (Red Green Blue) or RGBA (Red Green Blue Alpha). Glimmer supports constructing color objects using the `rgb` and `rgba` DSL methods.
|
375
|
+
|
376
|
+
Example:
|
377
|
+
|
378
|
+
```ruby
|
379
|
+
label {
|
380
|
+
background rgb(144, 240, 244)
|
381
|
+
foreground rgba(38, 92, 232, 255)
|
382
|
+
}
|
383
|
+
```
|
384
|
+
|
385
|
+
SWT also supports standard colors available as constants under the `SWT` namespace with the `COLOR_` prefix (e.g. `SWT::COLOR_BLUE`, `SWT::COLOR_WHITE`, `SWT::COLOR_RED`)
|
386
|
+
|
387
|
+
Glimmer accepts these constants as lowercase Ruby symbols with or without `color_` prefix.
|
388
|
+
|
389
|
+
Example:
|
390
|
+
|
391
|
+
```ruby
|
392
|
+
label {
|
393
|
+
background :black
|
394
|
+
foreground :yellow
|
395
|
+
}
|
396
|
+
label {
|
397
|
+
background :color_white
|
398
|
+
foreground :color_red
|
399
|
+
}
|
400
|
+
```
|
401
|
+
|
402
|
+
You may check out all available standard colors in `SWT` over here (having `COLOR_` prefix):
|
403
|
+
|
404
|
+
https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
|
405
|
+
|
406
|
+
#### Fonts
|
407
|
+
|
408
|
+
Fonts are represented in Glimmer as a hash of name, height, and style keys.
|
409
|
+
|
410
|
+
The style can be one (or more) of 3 values: `:normal`, `:bold`, and `:italic`
|
411
|
+
|
412
|
+
Example:
|
413
|
+
|
414
|
+
```ruby
|
415
|
+
label {
|
416
|
+
font name: 'Arial', height: 36, style: :normal
|
417
|
+
}
|
418
|
+
```
|
419
|
+
|
420
|
+
Keys are optional, so some of them may be left off.
|
421
|
+
When passing multiple styles, they are included in an array.
|
422
|
+
|
423
|
+
Example:
|
424
|
+
|
425
|
+
```ruby
|
426
|
+
label {
|
427
|
+
font style: [:bold, :italic]
|
428
|
+
}
|
429
|
+
```
|
430
|
+
|
284
431
|
### Layouts
|
285
432
|
|
286
433
|
Glimmer lays widgets out visually using SWT layouts, which can only be set on composite widget and subclasses.
|
@@ -452,97 +599,206 @@ Also, for a reference, check the SWT API:
|
|
452
599
|
|
453
600
|
https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
|
454
601
|
|
455
|
-
###
|
602
|
+
### Data-Binding
|
456
603
|
|
457
|
-
|
604
|
+
Data-binding is done with `bind` command following widget property to bind and taking model and bindable attribute as arguments.
|
458
605
|
|
459
|
-
|
606
|
+
Data-binding examples:
|
607
|
+
- `text bind(contact, :first_name)`
|
608
|
+
- `text bind(contact, 'address.street')`
|
609
|
+
- `text bind(contact, 'addresses[1].street')`
|
610
|
+
- `text bind(contact, :age, computed_by: :date_of_birth)`
|
611
|
+
- `text bind(contact, :name, computed_by: [:first_name, :last_name])`
|
612
|
+
- `text bind(contact, 'profiles[0].name', computed_by: ['profiles[0].first_name', 'profiles[0].last_name'])`
|
460
613
|
|
461
|
-
|
462
|
-
label {
|
463
|
-
background rgb(144, 240, 244)
|
464
|
-
foreground rgba(38, 92, 232, 255)
|
465
|
-
}
|
466
|
-
```
|
614
|
+
The 1st example binds the text property of a widget like `label` to the first name of a contact model.
|
467
615
|
|
468
|
-
|
616
|
+
The 2nd example binds the text property of a widget like `label` to the nested street of
|
617
|
+
the address of a contact. This is called nested property data binding.
|
469
618
|
|
470
|
-
|
619
|
+
The 3rd example binds the text property of a widget like `label` to the nested indexed address street of a contact. This is called nested indexed property data binding.
|
471
620
|
|
472
|
-
|
621
|
+
The 4th example demonstrates computed value data binding whereby the value of `age` depends on changes to `date_of_birth`.
|
622
|
+
|
623
|
+
The 5th example demonstrates computed value data binding whereby the value of `name` depends on changes to both `first_name` and `last_name`.
|
624
|
+
|
625
|
+
The 6th example demonstrates nested indexed computed value data binding whereby the value of `profiles[0].name` depends on changes to both nested `profiles[0].first_name` and `profiles[0].last_name`.
|
626
|
+
|
627
|
+
Example from [hello_combo.rb](https://github.com/AndyObtiva/glimmer/blob/master/samples/hello_combo.rb) sample:
|
628
|
+
|
629
|
+

|
630
|
+
|
631
|
+

|
473
632
|
|
474
633
|
```ruby
|
475
|
-
|
476
|
-
|
477
|
-
foreground :yellow
|
478
|
-
}
|
479
|
-
label {
|
480
|
-
background :color_white
|
481
|
-
foreground :color_red
|
482
|
-
}
|
483
|
-
```
|
634
|
+
class Person
|
635
|
+
attr_accessor :country, :country_options
|
484
636
|
|
485
|
-
|
637
|
+
def initialize
|
638
|
+
self.country_options=["", "Canada", "US", "Mexico"]
|
639
|
+
self.country = "Canada"
|
640
|
+
end
|
486
641
|
|
487
|
-
|
642
|
+
def reset_country
|
643
|
+
self.country = "Canada"
|
644
|
+
end
|
645
|
+
end
|
488
646
|
|
489
|
-
|
647
|
+
class HelloCombo
|
648
|
+
include Glimmer
|
649
|
+
def launch
|
650
|
+
person = Person.new
|
651
|
+
shell {
|
652
|
+
composite {
|
653
|
+
combo(:read_only) {
|
654
|
+
selection bind(person, :country)
|
655
|
+
}
|
656
|
+
button {
|
657
|
+
text "Reset"
|
658
|
+
on_widget_selected do
|
659
|
+
person.reset_country
|
660
|
+
end
|
661
|
+
}
|
662
|
+
}
|
663
|
+
}.open
|
664
|
+
end
|
665
|
+
end
|
490
666
|
|
491
|
-
|
667
|
+
HelloCombo.new.launch
|
668
|
+
```
|
492
669
|
|
493
|
-
|
670
|
+
`combo` widget is data-bound to the country of a person. Note that it expects `person` object to have `:country` attribute and `:country_options` attribute containing all available countries.
|
494
671
|
|
495
|
-
Example:
|
672
|
+
Example from [hello_list_single_selection.rb](https://github.com/AndyObtiva/glimmer/blob/master/samples/hello_list_single_selection.rb) sample:
|
673
|
+
|
674
|
+

|
496
675
|
|
497
676
|
```ruby
|
498
|
-
|
499
|
-
|
500
|
-
|
677
|
+
shell {
|
678
|
+
composite {
|
679
|
+
list {
|
680
|
+
selection bind(person, :country)
|
681
|
+
}
|
682
|
+
button {
|
683
|
+
text "Reset"
|
684
|
+
on_widget_selected do
|
685
|
+
person.reset_country
|
686
|
+
end
|
687
|
+
}
|
688
|
+
}
|
689
|
+
}.open
|
501
690
|
```
|
502
691
|
|
503
|
-
|
504
|
-
When passing multiple styles, they are included in an array.
|
692
|
+
`list` widget is also data-bound to the country of a person similarly to the combo widget. Not much difference here (the rest of the code not shown is the same).
|
505
693
|
|
506
|
-
|
694
|
+
Nonetheless, in the next example, a multi-selection list is declared instead allowing data-binding of multiple selection values to the bindable attribute on the model.
|
695
|
+
|
696
|
+

|
507
697
|
|
508
698
|
```ruby
|
509
|
-
|
510
|
-
|
511
|
-
|
699
|
+
class Person
|
700
|
+
attr_accessor :provinces, :provinces_options
|
701
|
+
|
702
|
+
def initialize
|
703
|
+
self.provinces_options=[
|
704
|
+
"",
|
705
|
+
"Quebec",
|
706
|
+
"Ontario",
|
707
|
+
"Manitoba",
|
708
|
+
"Saskatchewan",
|
709
|
+
"Alberta",
|
710
|
+
"British Columbia",
|
711
|
+
"Nova Skotia",
|
712
|
+
"Newfoundland"
|
713
|
+
]
|
714
|
+
self.provinces = ["Quebec", "Manitoba", "Alberta"]
|
715
|
+
end
|
716
|
+
|
717
|
+
def reset_provinces
|
718
|
+
self.provinces = ["Quebec", "Manitoba", "Alberta"]
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
class HelloListMultiSelection
|
723
|
+
include Glimmer
|
724
|
+
def launch
|
725
|
+
person = Person.new
|
726
|
+
shell {
|
727
|
+
composite {
|
728
|
+
list(:multi) {
|
729
|
+
selection bind(person, :provinces)
|
730
|
+
}
|
731
|
+
button {
|
732
|
+
text "Reset"
|
733
|
+
on_widget_selected do
|
734
|
+
person.reset_provinces
|
735
|
+
end
|
736
|
+
}
|
737
|
+
}
|
738
|
+
}.open
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
HelloListMultiSelection.new.launch
|
512
743
|
```
|
513
744
|
|
514
|
-
|
745
|
+
The Glimmer code is not much different from above except for passing the `:multi` style to the `list` widget. However, the model code behind the scenes is quite different as it is a `provinces` array bindable to the selection of multiple values on a `list` widget. `provinces_options` contains all available province values just as expected by a single selection `list` and `combo`.
|
515
746
|
|
516
|
-
|
747
|
+
Note that in all the data-binding examples above, there was also an observer attached to the `button` widget to trigger an action on the model, which in turn triggers a data-binding update on the `list` or `combo`. Observers will be discussed in more details in the [next section](#observer).
|
517
748
|
|
518
|
-
|
519
|
-
- `text bind(contact, :first_name)`
|
520
|
-
- `text bind(contact, 'address.street')`
|
521
|
-
- `text bind(contact, 'addresses[1].street')`
|
522
|
-
- `text bind(contact, :age, computed_by: :date_of_birth)`
|
523
|
-
- `text bind(contact, :name, computed_by: [:first_name, :last_name])`
|
524
|
-
- `text bind(contact, 'profiles[0].name', computed_by: ['profiles[0].first_name', 'profiles[0].last_name'])`
|
749
|
+
You may learn more about Glimmer's data-binding syntax by reading the [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer) mentioned in resources and opening up the samples under the [samples](https://github.com/AndyObtiva/glimmer/tree/master/samples) directory.
|
525
750
|
|
526
|
-
|
751
|
+
### Observer
|
527
752
|
|
528
|
-
|
529
|
-
the address of a contact. This is called nested property data binding.
|
753
|
+
Glimmer comes with `Observer` module, which is used internally for data-binding, but can also be used externally for custom use of the Observer Pattern. It is hidden when observing widgets, and used explicitly when observing models.
|
530
754
|
|
531
|
-
|
755
|
+
#### Observing Widgets
|
532
756
|
|
533
|
-
|
757
|
+
Glimmer supports observing widgets with an `on_*event*` declaration where the '*event*' part is replaced with the lowercase underscored name of an SWT listener event method.
|
534
758
|
|
535
|
-
|
759
|
+
To figure out what the available events for an SWT widget are, check out all of its API methods starting with `add` and ending with `Listener`, and then open the listener class to check its "event methods".
|
536
760
|
|
537
|
-
|
761
|
+
For example, if you look at the `Button` SWT API:
|
762
|
+
https://help.eclipse.org/2019-12/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fswt%2Fbrowser%2FBrowser.html
|
538
763
|
|
539
|
-
|
764
|
+
It has `addSelectionListener`. Additionally, under its `Control` super class, it has `addControlListener`, `addDragDetectListener`, `addFocusListener`, `addGestureListener`, `addHelpListener`, `addKeyListener`, `addMenuDetectListener`, `addMouseListener`, `addMouseMoveListener`, `addMouseTrackListener`, `addMouseWheelListener`, `addPaintListener`, `addTouchListener`, and `addTraverseListener`
|
540
765
|
|
541
|
-
|
766
|
+
Suppose, we select `addSelectionListener`, which is responsible for what happens when a user selects a button (clicks it). Then, open its argument `SelectionListener` SWT API, and you find the event (instance) methods: `widgetDefaultSelected` and `widgetSelected`. Let's select the second one, which is what gets invoked when a button is clicked.
|
767
|
+
|
768
|
+
Now, Glimmer simplifies the process of hooking into that listener (observer) by neither requiring you to call the `addSelectionListener` method nor requiring you to implement/extend the `SelectionListener` API.
|
769
|
+
|
770
|
+
Instead, simply add a `on_widget_selected` followed by a Ruby block containing the logic to perform. Glimmer figures out the rest.
|
771
|
+
|
772
|
+
Let's revisit the Tic Tac Toe example shown near the beginning of the page:
|
773
|
+
|
774
|
+
```ruby
|
775
|
+
shell {
|
776
|
+
text "Tic-Tac-Toe"
|
777
|
+
composite {
|
778
|
+
grid_layout 3, true
|
779
|
+
(1..3).each { |row|
|
780
|
+
(1..3).each { |column|
|
781
|
+
button {
|
782
|
+
layout_data :fill, :fill, true, true
|
783
|
+
text bind(@tic_tac_toe_board[row, column], :sign)
|
784
|
+
enabled bind(@tic_tac_toe_board[row, column], :empty)
|
785
|
+
on_widget_selected {
|
786
|
+
@tic_tac_toe_board.mark_box(row, column)
|
787
|
+
}
|
788
|
+
}
|
789
|
+
}
|
790
|
+
}
|
791
|
+
}
|
792
|
+
}
|
793
|
+
```
|
794
|
+
|
795
|
+
Note that every Tic Tac Toe grid cell has its `text` and `enabled` properties data-bound to the `sign` and `empty` attributes on the `TicTacToeBoard` model respectively.
|
542
796
|
|
543
|
-
|
797
|
+
Next however, each of these Tic Tac Toe grid cells, which are clickable buttons, have an `on_widget_selected` observer, which once triggered, marks the box (cell) on the `TicTacToeBoard` to make a move.
|
544
798
|
|
545
|
-
|
799
|
+
#### Observing Models
|
800
|
+
|
801
|
+
The class that needs to observe a model object must include (mix in) the `Observer` module and implement the `#call(new_value)` method. The class to be observed doesn't need to do anything. It will automatically be enhanced by Glimmer for observation.
|
546
802
|
|
547
803
|
To register observer, one has to call the `#observe` method and pass in the observable and the property(ies) to observe.
|
548
804
|
|
@@ -743,7 +999,11 @@ Here is the SWT API:
|
|
743
999
|
|
744
1000
|
https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
|
745
1001
|
|
746
|
-
Here is a list of SWT widgets:
|
1002
|
+
Here is a visual list of SWT widgets:
|
1003
|
+
|
1004
|
+
https://www.eclipse.org/swt/widgets/
|
1005
|
+
|
1006
|
+
Here is a textual list of SWT widgets:
|
747
1007
|
|
748
1008
|
https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
|
749
1009
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|