glimmer-dsl-libui 0.4.0 → 0.4.1
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 +9 -0
- data/README.md +60 -27
- data/VERSION +1 -1
- data/examples/color_the_circles.rb +2 -2
- data/examples/method_based_custom_keyword.rb +2 -2
- data/examples/snake/presenter/grid.rb +5 -3
- data/examples/snake.rb +3 -3
- data/examples/tetris.rb +12 -12
- data/glimmer-dsl-libui.gemspec +0 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 979ea7d60d873acdbe09e6ae2ceb48318798fa41ed13bb3a6bc8dcb642933165
|
4
|
+
data.tar.gz: 7cc05757477a0a42b85a20a6b298c147b5fba948f9e1eedd21701ab392a2d78a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8feb498d6d9eae22df82c9c9e2b0bd12ef11eb1ec9e4f90ac94f7151be28225f7dce775b8352b25ef98e4bc36f2aedd56370a1265a313f0997161396034f16d0
|
7
|
+
data.tar.gz: f76393bfebc577d9ce5e5add450ee70e337b67e7a63be24f5f91e4180d65c0d72c7236680f5843c446161710961ec51aa6520f037fcdcc0fc617d21ac182b850
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.4.1
|
4
|
+
|
5
|
+
- Document `observe` keyword
|
6
|
+
- Document unidirectional data-binding in more detail (like `:before_read`, `:on_read`, and `:after_read` options)
|
7
|
+
- Simplify examples/tetris.rb with `observe` keyword
|
8
|
+
- Simplify examples/method_based_custom_keyword.rb with `observe` keyword
|
9
|
+
- Simplify examples/color_the_circles.rb with `observe` keyword
|
10
|
+
- Simplify examples/snake.rb with `observe` keyword
|
11
|
+
|
3
12
|
## 0.4.0
|
4
13
|
|
5
14
|
- Upgrade to LibUI 0.0.13
|
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 LibUI 0.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 LibUI 0.4.1
|
2
2
|
## Prerequisite-Free Ruby Desktop Development GUI Library
|
3
3
|
[](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
4
|
[](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
@@ -233,6 +233,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
233
233
|
- [Area Transform Matrix](#area-transform-matrix)
|
234
234
|
- [Smart Defaults and Conventions](#smart-defaults-and-conventions)
|
235
235
|
- [Custom Keywords](#custom-keywords)
|
236
|
+
- [Observer Pattern](#observer-pattern)
|
236
237
|
- [Data-Binding](#data-binding)
|
237
238
|
- [API Gotchas](#api-gotchas)
|
238
239
|
- [Original API](#original-api)
|
@@ -371,7 +372,7 @@ gem install glimmer-dsl-libui
|
|
371
372
|
Or install via Bundler `Gemfile`:
|
372
373
|
|
373
374
|
```ruby
|
374
|
-
gem 'glimmer-dsl-libui', '~> 0.4.
|
375
|
+
gem 'glimmer-dsl-libui', '~> 0.4.1'
|
375
376
|
```
|
376
377
|
|
377
378
|
Add `require 'glimmer-dsl-libui'` at the top, and then `include Glimmer` into the top-level main object for testing or into an actual class for serious usage.
|
@@ -1321,34 +1322,66 @@ window('Method-Based Custom Keyword') {
|
|
1321
1322
|
|
1322
1323
|

|
1323
1324
|
|
1325
|
+
### Observer Pattern
|
1326
|
+
|
1327
|
+
The [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) (a.k.a. Observer Pattern) is fundamental to building GUIs (Graphical User Interfaces) following the [MVC (Model View Controller) Architectural Pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) or any of its variations like [MVP (Model View Presenter)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter). In the original Smalltalk-MVC, the View observes the Model for changes and updates itself accordingly.
|
1328
|
+
|
1329
|
+

|
1330
|
+
|
1331
|
+
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) supports the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) via the `observe(model, attribute=nil)` keyword, which can observe `Object` models with attributes, `Hash`es, and `Array`s. It automatically enhances objects as needed to support automatically notifying observers of changes via `observable#notify_observers(attribute)` method:
|
1332
|
+
- `Object` becomes `Glimmer::DataBinding::ObservableModel`, which supports observing specified `Object` model attributes.
|
1333
|
+
- `Hash` becomes `Glimmer::DataBinding::ObservableHash`, which supports observing all `Hash` keys or a specific `Hash` key
|
1334
|
+
- `Array` becomes `Glimmer::DataBinding::ObservableArray`, which supports observing `Array` changes like those done with `push`, `<<`, `delete`, and `map!` methods (all mutation methods).
|
1335
|
+
|
1336
|
+
Example:
|
1337
|
+
|
1338
|
+
```ruby
|
1339
|
+
observe(person, :name) do |new_name|
|
1340
|
+
@name_label.text = new_name
|
1341
|
+
end
|
1342
|
+
```
|
1343
|
+
|
1344
|
+
That observes a person's name attribute for changes and updates the name `label` `text` property accordingly.
|
1345
|
+
|
1346
|
+
[Learn about Glimmer's Observer Pattern capabilities and options in more detail at the Glimmer project page.](https://github.com/AndyObtiva/glimmer#data-binding-library)
|
1347
|
+
|
1348
|
+
See examples of the `observe` keyword at [Color The Circles](#color-the-circles), [Method-Based Custom Keyword](#method-based-custom-keyword), [Snake](#snake), and [Tetris](#tetris).
|
1349
|
+
|
1324
1350
|
### Data-Binding
|
1325
1351
|
|
1326
1352
|
[Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) supports unidirectional (one-way) data-binding of any control/shape/attributed-string property via the `<=` symbol (indicating data is moving from the right side, which is the model, to the left side, which is the GUI view object).
|
1327
1353
|
|
1354
|
+
The data-binding API is more precisely: `view_property <= [model, attribute, *options]`
|
1355
|
+
|
1328
1356
|
This is also known as the [Glimmer Shine](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#shine) syntax for data-binding, a [Glimmer](https://github.com/AndyObtiva/glimmer)-only unique innovation.
|
1329
1357
|
|
1330
1358
|
Example:
|
1331
1359
|
|
1332
1360
|
```ruby
|
1333
|
-
|
1334
|
-
|
1361
|
+
square(0, 0, CELL_SIZE) {
|
1362
|
+
fill <= [@grid.cells[row][column], :color]
|
1335
1363
|
}
|
1336
1364
|
```
|
1337
1365
|
|
1338
|
-
That is data-binding
|
1366
|
+
That is data-binding a grid cell color to a `square` shape's `fill` property. That means if the `color` attribute of the grid cell is updated, the `fill` property of the `square` shape is automatically updated accordingly.
|
1339
1367
|
|
1340
1368
|
Another Example:
|
1341
1369
|
|
1342
1370
|
```ruby
|
1343
|
-
|
1344
|
-
|
1371
|
+
window {
|
1372
|
+
title <= [@game, :score, on_read: -> (score) {"Glimmer Snake (Score: #{@game.score})"}]
|
1345
1373
|
}
|
1346
1374
|
```
|
1347
1375
|
|
1348
|
-
That is data-binding
|
1376
|
+
That is data-binding the `window` `title` property to the `score` attribute of a `@game`, but converting on read from the Model to a `String`.
|
1349
1377
|
|
1350
1378
|
Data-binding enables writing very expressive, terse, and declarative code to synchronize View properties with Model attributes instead of pages of imperative code doing the same thing.
|
1351
1379
|
|
1380
|
+
Options include:
|
1381
|
+
- `before_read {|value| ...}`: performs an operation before reading data from Model to update the View.
|
1382
|
+
- `on_read {|value| ...}`: converts value read from Model to update the View.
|
1383
|
+
- `after_read {|converted_value| ...}`: performs an operation after read from Model and updating the View.
|
1384
|
+
|
1352
1385
|
Learn more from data-binding usage in [Snake](#snake) and [Tic Tac Toe](#tic_tac_toe) examples.
|
1353
1386
|
|
1354
1387
|
### API Gotchas
|
@@ -4451,7 +4484,8 @@ class ColorTheCircles
|
|
4451
4484
|
end
|
4452
4485
|
|
4453
4486
|
def register_observers
|
4454
|
-
|
4487
|
+
# observe automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer block of score attribute changes
|
4488
|
+
observe(self, :score) do |new_score|
|
4455
4489
|
Glimmer::LibUI.queue_main do
|
4456
4490
|
@score_label.text = new_score.to_s
|
4457
4491
|
if new_score == -20
|
@@ -4465,7 +4499,6 @@ class ColorTheCircles
|
|
4465
4499
|
end
|
4466
4500
|
end
|
4467
4501
|
end
|
4468
|
-
observer.observe(self, :score) # automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer on score attribute changes
|
4469
4502
|
end
|
4470
4503
|
|
4471
4504
|
def setup_circle_factory
|
@@ -6282,9 +6315,9 @@ def label_pair(model, attribute, value)
|
|
6282
6315
|
name_label = label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
|
6283
6316
|
value_label = label(value.to_s)
|
6284
6317
|
}
|
6285
|
-
|
6318
|
+
observe(model, attribute) do
|
6286
6319
|
value_label.text = model.send(attribute)
|
6287
|
-
end
|
6320
|
+
end
|
6288
6321
|
end
|
6289
6322
|
|
6290
6323
|
def address(address)
|
@@ -6591,14 +6624,14 @@ New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version
|
|
6591
6624
|
|
6592
6625
|
```ruby
|
6593
6626
|
require 'glimmer-dsl-libui'
|
6594
|
-
require 'glimmer/data_binding/observer'
|
6595
6627
|
|
6596
6628
|
require_relative 'snake/presenter/grid'
|
6597
6629
|
|
6598
6630
|
class Snake
|
6631
|
+
include Glimmer
|
6632
|
+
|
6599
6633
|
CELL_SIZE = 15
|
6600
6634
|
SNAKE_MOVE_DELAY = 0.1
|
6601
|
-
include Glimmer
|
6602
6635
|
|
6603
6636
|
def initialize
|
6604
6637
|
@game = Model::Game.new
|
@@ -6644,7 +6677,7 @@ class Snake
|
|
6644
6677
|
@game.width.times do |column|
|
6645
6678
|
area {
|
6646
6679
|
square(0, 0, CELL_SIZE) {
|
6647
|
-
fill <= [@grid.cells[row][column], :color]
|
6680
|
+
fill <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
|
6648
6681
|
}
|
6649
6682
|
|
6650
6683
|
on_key_up do |area_key_event|
|
@@ -6739,7 +6772,7 @@ class Tetris
|
|
6739
6772
|
end
|
6740
6773
|
|
6741
6774
|
def register_observers
|
6742
|
-
|
6775
|
+
observe(@game, :game_over) do |game_over|
|
6743
6776
|
if game_over
|
6744
6777
|
@pause_menu_item.enabled = false
|
6745
6778
|
show_game_over_dialog
|
@@ -6747,11 +6780,11 @@ class Tetris
|
|
6747
6780
|
@pause_menu_item.enabled = true
|
6748
6781
|
start_moving_tetrominos_down
|
6749
6782
|
end
|
6750
|
-
end
|
6783
|
+
end
|
6751
6784
|
|
6752
6785
|
Model::Game::PLAYFIELD_HEIGHT.times do |row|
|
6753
6786
|
Model::Game::PLAYFIELD_WIDTH.times do |column|
|
6754
|
-
|
6787
|
+
observe(@game.playfield[row][column], :color) do |new_color|
|
6755
6788
|
Glimmer::LibUI.queue_main do
|
6756
6789
|
color = Glimmer::LibUI.interpret_color(new_color)
|
6757
6790
|
block = @playfield_blocks[row][column]
|
@@ -6762,13 +6795,13 @@ class Tetris
|
|
6762
6795
|
block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6763
6796
|
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
|
6764
6797
|
end
|
6765
|
-
end
|
6798
|
+
end
|
6766
6799
|
end
|
6767
6800
|
end
|
6768
6801
|
|
6769
6802
|
Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
|
6770
6803
|
Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
|
6771
|
-
|
6804
|
+
observe(@game.preview_playfield[row][column], :color) do |new_color|
|
6772
6805
|
Glimmer::LibUI.queue_main do
|
6773
6806
|
color = Glimmer::LibUI.interpret_color(new_color)
|
6774
6807
|
block = @preview_playfield_blocks[row][column]
|
@@ -6779,27 +6812,27 @@ class Tetris
|
|
6779
6812
|
block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6780
6813
|
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
|
6781
6814
|
end
|
6782
|
-
end
|
6815
|
+
end
|
6783
6816
|
end
|
6784
6817
|
end
|
6785
6818
|
|
6786
|
-
|
6819
|
+
observe(@game, :score) do |new_score|
|
6787
6820
|
Glimmer::LibUI.queue_main do
|
6788
6821
|
@score_label.text = new_score.to_s
|
6789
6822
|
end
|
6790
|
-
end
|
6823
|
+
end
|
6791
6824
|
|
6792
|
-
|
6825
|
+
observe(@game, :lines) do |new_lines|
|
6793
6826
|
Glimmer::LibUI.queue_main do
|
6794
6827
|
@lines_label.text = new_lines.to_s
|
6795
6828
|
end
|
6796
|
-
end
|
6829
|
+
end
|
6797
6830
|
|
6798
|
-
|
6831
|
+
observe(@game, :level) do |new_level|
|
6799
6832
|
Glimmer::LibUI.queue_main do
|
6800
6833
|
@level_label.text = new_level.to_s
|
6801
6834
|
end
|
6802
|
-
end
|
6835
|
+
end
|
6803
6836
|
end
|
6804
6837
|
|
6805
6838
|
def menu_bar
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.1
|
@@ -26,7 +26,8 @@ class ColorTheCircles
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def register_observers
|
29
|
-
|
29
|
+
# observe automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer block of score attribute changes
|
30
|
+
observe(self, :score) do |new_score|
|
30
31
|
Glimmer::LibUI.queue_main do
|
31
32
|
@score_label.text = new_score.to_s
|
32
33
|
if new_score == -20
|
@@ -40,7 +41,6 @@ class ColorTheCircles
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
43
|
-
observer.observe(self, :score) # automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer on score attribute changes
|
44
44
|
end
|
45
45
|
|
46
46
|
def setup_circle_factory
|
@@ -34,9 +34,9 @@ def label_pair(model, attribute, value)
|
|
34
34
|
name_label = label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
|
35
35
|
value_label = label(value.to_s)
|
36
36
|
}
|
37
|
-
|
37
|
+
observe(model, attribute) do
|
38
38
|
value_label.text = model.send(attribute)
|
39
|
-
end
|
39
|
+
end
|
40
40
|
end
|
41
41
|
|
42
42
|
def address(address)
|
@@ -1,10 +1,12 @@
|
|
1
|
-
require 'glimmer
|
1
|
+
require 'glimmer'
|
2
2
|
require_relative '../model/game'
|
3
3
|
require_relative 'cell'
|
4
4
|
|
5
5
|
class Snake
|
6
6
|
module Presenter
|
7
7
|
class Grid
|
8
|
+
include Glimmer
|
9
|
+
|
8
10
|
attr_reader :game, :cells
|
9
11
|
|
10
12
|
def initialize(game = Model::Game.new)
|
@@ -14,7 +16,7 @@ class Snake
|
|
14
16
|
Cell.new(grid: self, row: row, column: column)
|
15
17
|
end
|
16
18
|
end
|
17
|
-
|
19
|
+
observe(@game.snake, :vertebrae) do |new_vertebrae|
|
18
20
|
occupied_snake_positions = @game.snake.vertebrae.map {|v| [v.row, v.column]}
|
19
21
|
@cells.each_with_index do |row_cells, row|
|
20
22
|
row_cells.each_with_index do |cell, column|
|
@@ -27,7 +29,7 @@ class Snake
|
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
30
|
-
end
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
def clear
|
data/examples/snake.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'glimmer-dsl-libui'
|
2
|
-
require 'glimmer/data_binding/observer'
|
3
2
|
|
4
3
|
require_relative 'snake/presenter/grid'
|
5
4
|
|
6
5
|
class Snake
|
6
|
+
include Glimmer
|
7
|
+
|
7
8
|
CELL_SIZE = 15
|
8
9
|
SNAKE_MOVE_DELAY = 0.1
|
9
|
-
include Glimmer
|
10
10
|
|
11
11
|
def initialize
|
12
12
|
@game = Model::Game.new
|
@@ -52,7 +52,7 @@ class Snake
|
|
52
52
|
@game.width.times do |column|
|
53
53
|
area {
|
54
54
|
square(0, 0, CELL_SIZE) {
|
55
|
-
fill <= [@grid.cells[row][column], :color]
|
55
|
+
fill <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
|
56
56
|
}
|
57
57
|
|
58
58
|
on_key_up do |area_key_event|
|
data/examples/tetris.rb
CHANGED
@@ -42,7 +42,7 @@ class Tetris
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def register_observers
|
45
|
-
|
45
|
+
observe(@game, :game_over) do |game_over|
|
46
46
|
if game_over
|
47
47
|
@pause_menu_item.enabled = false
|
48
48
|
show_game_over_dialog
|
@@ -50,11 +50,11 @@ class Tetris
|
|
50
50
|
@pause_menu_item.enabled = true
|
51
51
|
start_moving_tetrominos_down
|
52
52
|
end
|
53
|
-
end
|
53
|
+
end
|
54
54
|
|
55
55
|
Model::Game::PLAYFIELD_HEIGHT.times do |row|
|
56
56
|
Model::Game::PLAYFIELD_WIDTH.times do |column|
|
57
|
-
|
57
|
+
observe(@game.playfield[row][column], :color) do |new_color|
|
58
58
|
Glimmer::LibUI.queue_main do
|
59
59
|
color = Glimmer::LibUI.interpret_color(new_color)
|
60
60
|
block = @playfield_blocks[row][column]
|
@@ -65,13 +65,13 @@ class Tetris
|
|
65
65
|
block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
66
66
|
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
|
67
67
|
end
|
68
|
-
end
|
68
|
+
end
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
72
|
Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
|
73
73
|
Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
|
74
|
-
|
74
|
+
observe(@game.preview_playfield[row][column], :color) do |new_color|
|
75
75
|
Glimmer::LibUI.queue_main do
|
76
76
|
color = Glimmer::LibUI.interpret_color(new_color)
|
77
77
|
block = @preview_playfield_blocks[row][column]
|
@@ -82,27 +82,27 @@ class Tetris
|
|
82
82
|
block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
83
83
|
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
|
84
84
|
end
|
85
|
-
end
|
85
|
+
end
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
|
89
|
+
observe(@game, :score) do |new_score|
|
90
90
|
Glimmer::LibUI.queue_main do
|
91
91
|
@score_label.text = new_score.to_s
|
92
92
|
end
|
93
|
-
end
|
93
|
+
end
|
94
94
|
|
95
|
-
|
95
|
+
observe(@game, :lines) do |new_lines|
|
96
96
|
Glimmer::LibUI.queue_main do
|
97
97
|
@lines_label.text = new_lines.to_s
|
98
98
|
end
|
99
|
-
end
|
99
|
+
end
|
100
100
|
|
101
|
-
|
101
|
+
observe(@game, :level) do |new_level|
|
102
102
|
Glimmer::LibUI.queue_main do
|
103
103
|
@level_label.text = new_level.to_s
|
104
104
|
end
|
105
|
-
end
|
105
|
+
end
|
106
106
|
end
|
107
107
|
|
108
108
|
def menu_bar
|
data/glimmer-dsl-libui.gemspec
CHANGED
Binary file
|