glimmer-dsl-libui 0.4.8 → 0.4.9
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 +5 -0
- data/README.md +84 -19
- data/VERSION +1 -1
- data/examples/snake.rb +19 -10
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/libui/control_proxy/checkbox_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/entry_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +5 -1
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/multiline_entry_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/slider_proxy.rb +1 -2
- data/lib/glimmer/libui/control_proxy/spinbox_proxy.rb +1 -2
- data/lib/glimmer/libui/data_bindable.rb +27 -2
- 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: 755dfde419aa3c77d0ca7229f9962d63b7aa139adbc1d5543e93acbf0c1917db
|
4
|
+
data.tar.gz: f4d753f109947eafeea727804ee871923948a0a262cde11a58dfd2f2fbe893ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96f4f5b7ddbf09a9543cea439ce74b1c5c545e2e6c240533e4d283ffba2bea16778a826601e2350392253d39edd21c8a6cb60d22fa1ee4107084c2cdd9155f70
|
7
|
+
data.tar.gz: 65b9fdb359801bdd1e4c6e9df74f3cc1d49f7012a5fc6b7dfc8cb4f6fbc16732cc6e4119a05d6c0a26eb559d60e3c72b263b3376f0775d4ff1ff5dd3ec52435d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.4.9
|
4
|
+
|
5
|
+
- Support unidirectional data-binding on all control properties that support bidirectional data-binding
|
6
|
+
- Fix issue in examples/snake.rb with double-turn causing instant death due to snake illogically going back against itself
|
7
|
+
|
3
8
|
## 0.4.8
|
4
9
|
|
5
10
|
- Support `checkbox` `checked` bidirectional data-binding (with `<=>` sign)
|
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.9
|
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)
|
@@ -373,7 +373,7 @@ gem install glimmer-dsl-libui
|
|
373
373
|
Or install via Bundler `Gemfile`:
|
374
374
|
|
375
375
|
```ruby
|
376
|
-
gem 'glimmer-dsl-libui', '~> 0.4.
|
376
|
+
gem 'glimmer-dsl-libui', '~> 0.4.9'
|
377
377
|
```
|
378
378
|
|
379
379
|
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.
|
@@ -1398,6 +1398,7 @@ Data-binding supports utilizing the [MVP (Model View Presenter)](https://en.wiki
|
|
1398
1398
|
- `search_entry`: `text`
|
1399
1399
|
- `slider`: `value`
|
1400
1400
|
- `spinbox`: `value`
|
1401
|
+
- `table`: `cell_rows` (explicit data-binding using `<=>` and [implicit data-binding](#table-api) by assigning value directly)
|
1401
1402
|
- `time_picker`: `time`
|
1402
1403
|
|
1403
1404
|
Example of bidirectional data-binding:
|
@@ -3268,7 +3269,62 @@ Mac | Windows | Linux
|
|
3268
3269
|
----|---------|------
|
3269
3270
|
  |   |  
|
3270
3271
|
|
3271
|
-
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
3272
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version (with explicit [data-binding](#data-binding)):
|
3273
|
+
|
3274
|
+
```ruby
|
3275
|
+
# frozen_string_literal: true
|
3276
|
+
|
3277
|
+
require 'glimmer-dsl-libui'
|
3278
|
+
|
3279
|
+
class BasicTableButton
|
3280
|
+
include Glimmer
|
3281
|
+
|
3282
|
+
attr_accessor :data
|
3283
|
+
|
3284
|
+
def initialize
|
3285
|
+
@data = [
|
3286
|
+
%w[cat meow delete],
|
3287
|
+
%w[dog woof delete],
|
3288
|
+
%w[chicken cock-a-doodle-doo delete],
|
3289
|
+
%w[horse neigh delete],
|
3290
|
+
%w[cow moo delete]
|
3291
|
+
]
|
3292
|
+
end
|
3293
|
+
|
3294
|
+
def launch
|
3295
|
+
window('Animal sounds', 400, 200) {
|
3296
|
+
horizontal_box {
|
3297
|
+
table {
|
3298
|
+
text_column('Animal')
|
3299
|
+
text_column('Description')
|
3300
|
+
button_column('Action') {
|
3301
|
+
on_clicked do |row|
|
3302
|
+
# Option 1: direct data deletion is the simpler solution
|
3303
|
+
# @data.delete_at(row) # automatically deletes actual table row due to explicit data-binding
|
3304
|
+
|
3305
|
+
# Option 2: cloning only to demonstrate table row deletion upon explicit setting of data attribute (cloning is not recommended beyond demonstrating this point)
|
3306
|
+
new_data = @data.clone
|
3307
|
+
new_data.delete_at(row)
|
3308
|
+
self.data = new_data # automatically loses deleted table row due to explicit data-binding
|
3309
|
+
end
|
3310
|
+
}
|
3311
|
+
|
3312
|
+
cell_rows <=> [self, :data] # explicit data-binding of table cell_rows to self.data
|
3313
|
+
|
3314
|
+
on_changed do |row, type, row_data|
|
3315
|
+
puts "Row #{row} #{type}: #{row_data}"
|
3316
|
+
$stdout.flush
|
3317
|
+
end
|
3318
|
+
}
|
3319
|
+
}
|
3320
|
+
}.show
|
3321
|
+
end
|
3322
|
+
end
|
3323
|
+
|
3324
|
+
BasicTableButton.new.launch
|
3325
|
+
```
|
3326
|
+
|
3327
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version 2 (with implicit [data-binding](#data-binding)):
|
3272
3328
|
|
3273
3329
|
```ruby
|
3274
3330
|
require 'glimmer-dsl-libui'
|
@@ -6449,7 +6505,7 @@ require 'glimmer-dsl-libui'
|
|
6449
6505
|
class FormTable
|
6450
6506
|
include Glimmer
|
6451
6507
|
|
6452
|
-
attr_accessor :name, :email, :phone, :city, :state, :filter_value
|
6508
|
+
attr_accessor :data, :name, :email, :phone, :city, :state, :filter_value
|
6453
6509
|
|
6454
6510
|
def initialize
|
6455
6511
|
@data = [
|
@@ -6520,10 +6576,10 @@ class FormTable
|
|
6520
6576
|
after_write: ->(filter_value) { # execute after write to self.filter_value
|
6521
6577
|
@unfiltered_data ||= @data.dup
|
6522
6578
|
# Unfilter first to remove any previous filters
|
6523
|
-
|
6579
|
+
self.data = @unfiltered_data # affects table indirectly through explicit data-binding
|
6524
6580
|
# Now, apply filter if entered
|
6525
6581
|
unless filter_value.empty?
|
6526
|
-
@data.filter
|
6582
|
+
self.data = @data.filter do |row_data| # affects table indirectly through explicit data-binding
|
6527
6583
|
row_data.any? do |cell|
|
6528
6584
|
cell.to_s.downcase.include?(filter_value.downcase)
|
6529
6585
|
end
|
@@ -6540,7 +6596,7 @@ class FormTable
|
|
6540
6596
|
text_column('City')
|
6541
6597
|
text_column('State')
|
6542
6598
|
|
6543
|
-
cell_rows
|
6599
|
+
cell_rows <=> [self, :data] # explicit data-binding
|
6544
6600
|
|
6545
6601
|
on_changed do |row, type, row_data|
|
6546
6602
|
puts "Row #{row} #{type}: #{row_data}"
|
@@ -8195,6 +8251,7 @@ class Snake
|
|
8195
8251
|
@game = Model::Game.new
|
8196
8252
|
@grid = Presenter::Grid.new(@game)
|
8197
8253
|
@game.start
|
8254
|
+
@keypress_queue = []
|
8198
8255
|
create_gui
|
8199
8256
|
register_observers
|
8200
8257
|
end
|
@@ -8214,14 +8271,30 @@ class Snake
|
|
8214
8271
|
end
|
8215
8272
|
|
8216
8273
|
Glimmer::LibUI.timer(SNAKE_MOVE_DELAY) do
|
8217
|
-
|
8274
|
+
unless @game.over?
|
8275
|
+
process_queued_keypress
|
8276
|
+
@game.snake.move
|
8277
|
+
end
|
8278
|
+
end
|
8279
|
+
end
|
8280
|
+
|
8281
|
+
def process_queued_keypress
|
8282
|
+
# key press queue ensures one turn per snake move to avoid a double-turn resulting in instant death (due to snake illogically going back against itself)
|
8283
|
+
key = @keypress_queue.shift
|
8284
|
+
case [@game.snake.head.orientation, key]
|
8285
|
+
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
|
8286
|
+
@game.snake.turn_right
|
8287
|
+
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
|
8288
|
+
@game.snake.turn_left
|
8289
|
+
else
|
8290
|
+
# No Op
|
8218
8291
|
end
|
8219
8292
|
end
|
8220
8293
|
|
8221
8294
|
def create_gui
|
8222
8295
|
@main_window = window {
|
8223
8296
|
# data-bind window title to game score, converting it to a title string on read from the model
|
8224
|
-
title <= [@game, :score, on_read: -> (score) {"
|
8297
|
+
title <= [@game, :score, on_read: -> (score) {"Snake (Score: #{@game.score})"}]
|
8225
8298
|
content_size @game.width * CELL_SIZE, @game.height * CELL_SIZE
|
8226
8299
|
resizable false
|
8227
8300
|
|
@@ -8239,15 +8312,7 @@ class Snake
|
|
8239
8312
|
}
|
8240
8313
|
|
8241
8314
|
on_key_up do |area_key_event|
|
8242
|
-
|
8243
|
-
case orientation_and_key
|
8244
|
-
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
|
8245
|
-
@game.snake.turn_right
|
8246
|
-
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
|
8247
|
-
@game.snake.turn_left
|
8248
|
-
else
|
8249
|
-
# No Op
|
8250
|
-
end
|
8315
|
+
@keypress_queue << area_key_event[:ext_key]
|
8251
8316
|
end
|
8252
8317
|
}
|
8253
8318
|
end
|
@@ -9115,7 +9180,7 @@ These features have been planned or suggested. You might see them in a future ve
|
|
9115
9180
|
is fine, but please isolate to its own commit so I can cherry-pick
|
9116
9181
|
around it.
|
9117
9182
|
|
9118
|
-
Note that the latest development sometimes takes place in [development](https://github.com/AndyObtiva/glimmer-dsl-libui/tree/development) branch (
|
9183
|
+
Note that the latest development sometimes takes place in the [development](https://github.com/AndyObtiva/glimmer-dsl-libui/tree/development) branch (usually deleted once merged back to [master](https://github.com/AndyObtiva/glimmer-dsl-libui)).
|
9119
9184
|
|
9120
9185
|
## Contributors
|
9121
9186
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.9
|
data/examples/snake.rb
CHANGED
@@ -12,6 +12,7 @@ class Snake
|
|
12
12
|
@game = Model::Game.new
|
13
13
|
@grid = Presenter::Grid.new(@game)
|
14
14
|
@game.start
|
15
|
+
@keypress_queue = []
|
15
16
|
create_gui
|
16
17
|
register_observers
|
17
18
|
end
|
@@ -31,7 +32,23 @@ class Snake
|
|
31
32
|
end
|
32
33
|
|
33
34
|
Glimmer::LibUI.timer(SNAKE_MOVE_DELAY) do
|
34
|
-
|
35
|
+
unless @game.over?
|
36
|
+
process_queued_keypress
|
37
|
+
@game.snake.move
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_queued_keypress
|
43
|
+
# key press queue ensures one turn per snake move to avoid a double-turn resulting in instant death (due to snake illogically going back against itself)
|
44
|
+
key = @keypress_queue.shift
|
45
|
+
case [@game.snake.head.orientation, key]
|
46
|
+
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
|
47
|
+
@game.snake.turn_right
|
48
|
+
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
|
49
|
+
@game.snake.turn_left
|
50
|
+
else
|
51
|
+
# No Op
|
35
52
|
end
|
36
53
|
end
|
37
54
|
|
@@ -56,15 +73,7 @@ class Snake
|
|
56
73
|
}
|
57
74
|
|
58
75
|
on_key_up do |area_key_event|
|
59
|
-
|
60
|
-
case orientation_and_key
|
61
|
-
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
|
62
|
-
@game.snake.turn_right
|
63
|
-
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
|
64
|
-
@game.snake.turn_left
|
65
|
-
else
|
66
|
-
# No Op
|
67
|
-
end
|
76
|
+
@keypress_queue << area_key_event[:ext_key]
|
68
77
|
end
|
69
78
|
}
|
70
79
|
end
|
data/glimmer-dsl-libui.gemspec
CHANGED
Binary file
|
@@ -30,8 +30,7 @@ module Glimmer
|
|
30
30
|
class CheckboxProxy < ControlProxy
|
31
31
|
DEFAULT_TEXT = ''
|
32
32
|
|
33
|
-
def
|
34
|
-
super
|
33
|
+
def data_bind_write(property, model_binding)
|
35
34
|
handle_listener('on_toggled') { model_binding.call(checked) } if property == 'checked'
|
36
35
|
end
|
37
36
|
|
@@ -64,8 +64,7 @@ module Glimmer
|
|
64
64
|
alias set_selected_item selected_item
|
65
65
|
alias selected_item= selected_item
|
66
66
|
|
67
|
-
def
|
68
|
-
super # model to view data-binding
|
67
|
+
def data_bind_write(property, model_binding)
|
69
68
|
case property
|
70
69
|
when 'selected'
|
71
70
|
handle_listener('on_selected') { model_binding.call(selected) }
|
@@ -40,8 +40,7 @@ module Glimmer
|
|
40
40
|
alias set_items items
|
41
41
|
alias items= items
|
42
42
|
|
43
|
-
def
|
44
|
-
super
|
43
|
+
def data_bind_write(property, model_binding)
|
45
44
|
handle_listener('on_changed') { model_binding.call(text) } if property == 'text'
|
46
45
|
end
|
47
46
|
end
|
@@ -28,8 +28,7 @@ module Glimmer
|
|
28
28
|
#
|
29
29
|
# Follows the Proxy Design Pattern
|
30
30
|
class EntryProxy < ControlProxy
|
31
|
-
def
|
32
|
-
super
|
31
|
+
def data_bind_write(property, model_binding)
|
33
32
|
handle_listener('on_changed') { model_binding.call(text) } if property == 'text'
|
34
33
|
end
|
35
34
|
|
@@ -65,7 +65,11 @@ module Glimmer
|
|
65
65
|
super
|
66
66
|
end
|
67
67
|
|
68
|
-
def
|
68
|
+
def data_bind_read(property, model_binding)
|
69
|
+
# No Op
|
70
|
+
end
|
71
|
+
|
72
|
+
def data_bind_write(property, model_binding)
|
69
73
|
handle_listener('on_changed') { model_binding.call(font) } if property == 'font'
|
70
74
|
end
|
71
75
|
end
|
@@ -29,8 +29,7 @@ module Glimmer
|
|
29
29
|
#
|
30
30
|
# Follows the Proxy Design Pattern
|
31
31
|
class CheckMenuItemProxy < MenuItemProxy
|
32
|
-
def
|
33
|
-
super
|
32
|
+
def data_bind_write(property, model_binding)
|
34
33
|
handle_listener('on_clicked') { model_binding.call(checked) } if property == 'checked'
|
35
34
|
end
|
36
35
|
|
@@ -28,8 +28,7 @@ module Glimmer
|
|
28
28
|
#
|
29
29
|
# Follows the Proxy Design Pattern
|
30
30
|
class MultilineEntryProxy < ControlProxy
|
31
|
-
def
|
32
|
-
super
|
31
|
+
def data_bind_write(property, model_binding)
|
33
32
|
handle_listener('on_changed') { model_binding.call(text) } if property == 'text'
|
34
33
|
end
|
35
34
|
|
@@ -50,8 +50,7 @@ module Glimmer
|
|
50
50
|
alias set_selected_item selected_item
|
51
51
|
alias selected_item= selected_item
|
52
52
|
|
53
|
-
def
|
54
|
-
super # model to view data-binding
|
53
|
+
def data_bind_write(property, model_binding)
|
55
54
|
case property
|
56
55
|
when 'selected'
|
57
56
|
handle_listener('on_selected') { model_binding.call(selected) }
|
@@ -28,8 +28,7 @@ module Glimmer
|
|
28
28
|
#
|
29
29
|
# Follows the Proxy Design Pattern
|
30
30
|
class SliderProxy < ControlProxy
|
31
|
-
def
|
32
|
-
super
|
31
|
+
def data_bind_write(property, model_binding)
|
33
32
|
handle_listener('on_changed') { model_binding.call(value) } if property == 'value'
|
34
33
|
end
|
35
34
|
end
|
@@ -28,8 +28,7 @@ module Glimmer
|
|
28
28
|
#
|
29
29
|
# Follows the Proxy Design Pattern
|
30
30
|
class SpinboxProxy < ControlProxy
|
31
|
-
def
|
32
|
-
super
|
31
|
+
def data_bind_write(property, model_binding)
|
33
32
|
handle_listener('on_changed') { model_binding.call(value) } if property == 'value'
|
34
33
|
end
|
35
34
|
end
|
@@ -23,9 +23,25 @@ module Glimmer
|
|
23
23
|
module LibUI
|
24
24
|
# Parent controls and shapes who have children and add child post_initialize_child
|
25
25
|
module DataBindable
|
26
|
-
#
|
27
|
-
#
|
26
|
+
# Sets up read/write (bidirectional) data-binding
|
27
|
+
#
|
28
|
+
# classes are expected to implement `data_bind_write(property, model_binding)` to setup write data-binding
|
29
|
+
# by observing view property for changes and writing to model attribute via model binding accordingly
|
30
|
+
#
|
31
|
+
# classes can override data_bind_read to disable read data-binding in rare scenarios that might need it
|
32
|
+
#
|
33
|
+
# returns model attribute reading observer by default
|
28
34
|
def data_bind(property, model_binding)
|
35
|
+
data_bind_read(property, model_binding).tap do
|
36
|
+
data_bind_write(property, model_binding) unless model_binding.binding_options[:read_only]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sets up read data-binding (reading from model to update view)
|
41
|
+
#
|
42
|
+
# Default implementation observes model attribute for changes via model binding
|
43
|
+
# and updates view property accordingly
|
44
|
+
def data_bind_read(property, model_binding)
|
29
45
|
model_attribute_observer = Glimmer::DataBinding::Observer.proc do
|
30
46
|
new_value = model_binding.evaluate_property
|
31
47
|
send("#{property}=", new_value) unless send(property) == new_value
|
@@ -34,6 +50,15 @@ module Glimmer
|
|
34
50
|
model_attribute_observer.call # initial update
|
35
51
|
model_attribute_observer
|
36
52
|
end
|
53
|
+
|
54
|
+
# Sets up write data-binding (writing to model from view)
|
55
|
+
#
|
56
|
+
# Has no implementation by default. Classes are expected
|
57
|
+
# to implement this method by observing view property
|
58
|
+
# for changes and writing them to model accordingly via model binding
|
59
|
+
def data_bind_write(property, model_binding)
|
60
|
+
# No Op by default
|
61
|
+
end
|
37
62
|
end
|
38
63
|
end
|
39
64
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-libui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|