glimmer-dsl-libui 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +75 -10
- data/VERSION +1 -1
- data/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md +28 -0
- data/examples/button_counter.rb +18 -11
- data/examples/dynamic_form.rb +69 -0
- data/examples/snake/model/snake.rb +43 -17
- data/examples/snake.rb +6 -2
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/content_expression.rb +41 -0
- data/lib/glimmer/dsl/libui/dsl.rb +1 -0
- data/lib/glimmer/libui/control_proxy.rb +13 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: effb65102f9db3aa2977bac55edd4f67f91f1eafdae26403b8c044c714048a03
|
4
|
+
data.tar.gz: 3923d80a19afd62a0220026f33720ee953ad166880e17d60883aed53f9977d86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e123f42fd61ce49b126e7f51caf738e0c769eca12b177c879007cedaba6ec38974d16ca864e8d8922546f79cfe2dc8946056935684f0bab9d88892e425c5d79
|
7
|
+
data.tar.gz: 8d0d79d7632e30568f747a3db5d9bbdef387e854f55e0cf6559a4d8d242075bc8c1836e00e2554a30eb5eded934bb23c267a764b127cfe768c39e679ff47671e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.11.0
|
4
|
+
|
5
|
+
- Control `content` data-binding to generate nested controls dynamically based on a model attribute change
|
6
|
+
- `examples/dynamic_form.rb` to demonstrate control `content` data-binding
|
7
|
+
|
8
|
+
## 0.10.2
|
9
|
+
|
10
|
+
- In Snake example, change snake direction on key press instead of key release to be more responsive for players who are not used to releasing pressed keys quickly
|
11
|
+
- In Snake example, fix issue with detecting collision too soon if a snake fills the entire space horizontally or vertically
|
12
|
+
- In Snake example, fix issue of hearing beeps on every direction change because of not properly informing LibUI when the area key down event is handled
|
13
|
+
- In Snake example, refactor `Snake::Model::Snake` to be more readable like high-level game domain rules (especially `move` method)
|
14
|
+
|
3
15
|
## 0.10.1
|
4
16
|
|
5
17
|
- Scaffold custom shape
|
@@ -8,7 +20,7 @@
|
|
8
20
|
|
9
21
|
## 0.10.0
|
10
22
|
|
11
|
-
- Support Custom Shapes
|
23
|
+
- Support Custom Shapes by mixing in `Glimmer::LibUI::CustomShape` to abstract composite shapes/text/image concepts inside an `area`
|
12
24
|
- `examples/basic_custom_shape.rb` example
|
13
25
|
- Support nesting listeners under a Custom Shape that will automatically get added to its `body_root` control
|
14
26
|
- Support nesting listeners under a Custom Control that will automatically get added to its `body_root` control
|
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.
|
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.11.0
|
2
2
|
## Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library ([Fukuoka Award Winning](http://www.digitalfukuoka.jp/topics/187?locale=ja))
|
3
3
|
### The Quickest Way From Zero To GUI
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
|
@@ -431,7 +431,7 @@ gem install glimmer-dsl-libui
|
|
431
431
|
Or install via Bundler `Gemfile`:
|
432
432
|
|
433
433
|
```ruby
|
434
|
-
gem 'glimmer-dsl-libui', '~> 0.
|
434
|
+
gem 'glimmer-dsl-libui', '~> 0.11.0'
|
435
435
|
```
|
436
436
|
|
437
437
|
Test that installation worked by running the [Glimmer Meta-Example](#examples):
|
@@ -452,8 +452,19 @@ Mac | Windows | Linux
|
|
452
452
|
|
453
453
|
## Usage
|
454
454
|
|
455
|
-
|
456
|
-
|
455
|
+
Start by requiring the [glimmer-dsl-libui](https://rubygems.org/gems/glimmer-dsl-libui) Ruby gem, whether through a Ruby `require 'glimmer-dsl-libui` statement or `Bundler`.
|
456
|
+
|
457
|
+
Afterwards, to access the Glimmer GUI DSL:
|
458
|
+
- If you are learning/experimenting/prototyping with Glimmer DSL for LibUI, include the `Glimmer` module into the top-level scope or a Ruby class.
|
459
|
+
- If you are building a serious application, include `Glimmer::LibUI::Application` into the main view Ruby class
|
460
|
+
- If you are building a custom control, include [`Glimmer::LibUI::CustomControl`](#custom-components) into a Ruby class
|
461
|
+
- If you are building a cusotm window, include [`Glimmer::LibUI::CustomWindow`](#custom-components) into a Ruby class
|
462
|
+
- If you are building a custom shape, include [`Glimmer::LibUI::CustomShape`](#custom-components) into a Ruby class.
|
463
|
+
|
464
|
+
You may learn more about the different options above with basic examples in the following subsections: [Experimentation Usage](#experimentation-usage), [Prototyping Usage](#prototyping-usage), [Serious Usage](#serious-usage).
|
465
|
+
|
466
|
+
If you are new to [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) (beginner), after going through the subsections below, check out the RubyConf 2022 talk ["Building Native GUI Apps in Ruby"](https://andymaleh.blogspot.com/2023/02/rubyconf-2022-talk-video-for-building.html), [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts), [Glimmer Command](#glimmer-command) (just the basics, how to run an app, and how to run examples to start), [Girb](#girb-glimmer-irb) and [Examples](#examples) to quickly learn through copy/paste. It is very important for beginners to go through all the [Examples](#examples) from the most basic to the most advanced while reading the README topics that relate to the examples. You may refer to the [API](#api) on once you have gotten your feet wet with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) and need more detailed reference information.
|
467
|
+
|
457
468
|
### Experimentation Usage
|
458
469
|
|
459
470
|
For experimenting and learning, add `include Glimmer` into the top-level main object and start using the Glimmer GUI DSL directly.
|
@@ -534,9 +545,6 @@ SomeGlimmerApp.launch
|
|
534
545
|
|
535
546
|
(note: `Glimmer::LibUI::Application` is an alias for `Glimmer::LibUI::CustomWindow` since that is what it represents)
|
536
547
|
|
537
|
-
If you are new to [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui), check out the [Glimmer GUI DSL Concepts](#glimmer-gui-dsl-concepts), [Glimmer Command](#glimmer-command), [Girb](#girb-glimmer-irb) and [Examples](#examples) to quickly learn through copy/paste. You may refer to the [API](#api) later on once you have gotten your feet wet with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) and need more detailed reference information.
|
538
|
-
|
539
|
-
|
540
548
|
## Glimmer Command
|
541
549
|
|
542
550
|
The `glimmer` command allows you to conveniently run applications (`glimmer app_path`), run examples (`glimmer examples`), and scaffold applications (`glimmer "scaffold[app_name]"`).
|
@@ -548,7 +556,6 @@ glimmer
|
|
548
556
|
```
|
549
557
|
|
550
558
|
```
|
551
|
-
% bin/glimmer
|
552
559
|
Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library) - Ruby Gem: glimmer-dsl-libui v0.8.0
|
553
560
|
|
554
561
|
Usage: glimmer [--bundler] [--pd] [--quiet] [--debug] [--log-level=VALUE] [[ENV_VAR=VALUE]...] [[-ruby-option]...] (application.rb or task[task_args])
|
@@ -1592,6 +1599,43 @@ button('greet') { |b|
|
|
1592
1599
|
}
|
1593
1600
|
```
|
1594
1601
|
|
1602
|
+
If there is ever a need to add more content to a control, you can re-open its content with the `control.content { ... }` method.
|
1603
|
+
|
1604
|
+
Example:
|
1605
|
+
|
1606
|
+
```ruby
|
1607
|
+
box1 = vertical_box {
|
1608
|
+
label('First Name')
|
1609
|
+
}
|
1610
|
+
# re-open content of box1 and add another control
|
1611
|
+
box1.content {
|
1612
|
+
entry {
|
1613
|
+
text 'fill in your first name'
|
1614
|
+
}
|
1615
|
+
}
|
1616
|
+
```
|
1617
|
+
|
1618
|
+
You can also use [data-binding](#data-binding) with content blocks to generate content dynamically based on changes in a model attribute. The only difference in syntax in this case would be to wrap the content with an explicit `content(*binding_args) { ... }` block that includes data-binding arguments for a model attribute.
|
1619
|
+
|
1620
|
+
Example:
|
1621
|
+
|
1622
|
+
```ruby
|
1623
|
+
form {
|
1624
|
+
stretchy false
|
1625
|
+
|
1626
|
+
content(@user, :customizable_attributes) {
|
1627
|
+
@user.customizable_attributes.each do |attribute|
|
1628
|
+
entry {
|
1629
|
+
label attribute.to_s.split('_').map(&:capitalize).join(' ')
|
1630
|
+
text <=> [@user, attribute]
|
1631
|
+
}
|
1632
|
+
end
|
1633
|
+
}
|
1634
|
+
}
|
1635
|
+
```
|
1636
|
+
|
1637
|
+
The form above will only display fields for a model's customizable attributes, so if they change, the form content will change too. Learn more at the [Dynamic Form](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#dynamic-form) example.
|
1638
|
+
|
1595
1639
|
**Property**: Control properties may be declared inside keyword blocks with lower-case underscored name followed by property value args (e.g. `title "hello world"` inside `group`). Behind the scenes, properties correspond to `LibUI.control_set_property` methods.
|
1596
1640
|
|
1597
1641
|
**Listener**: Control listeners may be declared inside keyword blocks with listener lower-case underscored name beginning with `on_` and receiving required block handler (always followed by a `do; end` style block to signify logic).
|
@@ -3388,11 +3432,11 @@ Another example of bidirectional data-binding with an option:
|
|
3388
3432
|
|
3389
3433
|
```ruby
|
3390
3434
|
entry {
|
3391
|
-
text <=> [
|
3435
|
+
text <=> [model, :entered_text, after_write: ->(text) {puts text}]
|
3392
3436
|
}
|
3393
3437
|
```
|
3394
3438
|
|
3395
|
-
That is data-binding `entered_text` attribute on `
|
3439
|
+
That is data-binding `entered_text` attribute on `model` to `entry` `text` property and printing text after write to the model.
|
3396
3440
|
|
3397
3441
|
##### Table Data-Binding
|
3398
3442
|
|
@@ -3574,6 +3618,27 @@ window {
|
|
3574
3618
|
|
3575
3619
|
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`.
|
3576
3620
|
|
3621
|
+
You can also use unidirectional [data-binding](#data-binding) with content blocks to generate content dynamically based on changes in a model attribute. The only difference in syntax in this case would be to wrap the content with an explicit `content(*binding_args) { ... }` block that includes data-binding arguments for a model attribute.
|
3622
|
+
|
3623
|
+
Example:
|
3624
|
+
|
3625
|
+
```ruby
|
3626
|
+
form {
|
3627
|
+
stretchy false
|
3628
|
+
|
3629
|
+
content(@user, :customizable_attributes) {
|
3630
|
+
@user.customizable_attributes.each do |attribute|
|
3631
|
+
entry {
|
3632
|
+
label attribute.to_s.split('_').map(&:capitalize).join(' ')
|
3633
|
+
text <=> [@user, attribute]
|
3634
|
+
}
|
3635
|
+
end
|
3636
|
+
}
|
3637
|
+
}
|
3638
|
+
```
|
3639
|
+
|
3640
|
+
The form above will only display fields for a model's customizable attributes, so if they change, the form content will change too. Learn more at the [Dynamic Form](/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#dynamic-form) example.
|
3641
|
+
|
3577
3642
|
#### Data-Binding API
|
3578
3643
|
|
3579
3644
|
To summarize the data-binding API:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
@@ -8,6 +8,7 @@
|
|
8
8
|
- [CPU Percentage](#cpu-percentage)
|
9
9
|
- [Custom Draw Text](#custom-draw-text)
|
10
10
|
- [Dynamic Area](#dynamic-area)
|
11
|
+
- [Dynamic Form](#dynamic-form)
|
11
12
|
- [Editable Column Table](#editable-column-table)
|
12
13
|
- [Editable Table](#editable-table)
|
13
14
|
- [Form Table](#form-table)
|
@@ -211,6 +212,33 @@ Version 4 (declarative stable `path` approach without [data-binding](#data-bindi
|
|
211
212
|
|
212
213
|
[examples/dynamic_area4.rb](/examples/dynamic_area4.rb)
|
213
214
|
|
215
|
+
|
216
|
+
## Dynamic Form
|
217
|
+
|
218
|
+
[examples/dynamic_form.rb](/examples/dynamic_form.rb)
|
219
|
+
|
220
|
+
Run with this command from the root of the project if you cloned the project:
|
221
|
+
|
222
|
+
```
|
223
|
+
ruby -r './lib/glimmer-dsl-libui' examples/dynamic_form.rb
|
224
|
+
```
|
225
|
+
|
226
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
227
|
+
|
228
|
+
```
|
229
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/dynamic_form'"
|
230
|
+
```
|
231
|
+
|
232
|
+
![glimmer-dsl-libui-mac-dynamic-form.png](/images/glimmer-dsl-libui-mac-dynamic-form.png)
|
233
|
+
|
234
|
+
![glimmer-dsl-libui-mac-dynamic-form-filled.png](/images/glimmer-dsl-libui-mac-dynamic-form-filled.png)
|
235
|
+
|
236
|
+
![glimmer-dsl-libui-mac-dynamic-form-summarized.png](/images/glimmer-dsl-libui-mac-dynamic-form-summarized.png)
|
237
|
+
|
238
|
+
![glimmer-dsl-libui-mac-dynamic-form-without-some-fields.png](/images/glimmer-dsl-libui-mac-dynamic-form-without-some-fields.png)
|
239
|
+
|
240
|
+
![glimmer-dsl-libui-mac-dynamic-form-without-some-fields-summarized.png](/images/glimmer-dsl-libui-mac-dynamic-form-without-some-fields-summarized.png)
|
241
|
+
|
214
242
|
## Editable Column Table
|
215
243
|
|
216
244
|
[examples/editable_column_table.rb](/examples/editable_column_table.rb)
|
data/examples/button_counter.rb
CHANGED
@@ -1,28 +1,35 @@
|
|
1
1
|
require 'glimmer-dsl-libui'
|
2
2
|
|
3
|
-
class
|
4
|
-
include Glimmer
|
5
|
-
|
3
|
+
class Counter
|
6
4
|
attr_accessor :count
|
7
|
-
|
5
|
+
|
8
6
|
def initialize
|
9
7
|
self.count = 0
|
10
8
|
end
|
9
|
+
end
|
11
10
|
|
12
|
-
|
11
|
+
class ButtonCounter
|
12
|
+
include Glimmer::LibUI::Application
|
13
|
+
|
14
|
+
before_body do
|
15
|
+
@counter = Counter.new
|
16
|
+
end
|
17
|
+
|
18
|
+
body {
|
13
19
|
window('Hello, Button!', 190, 20) {
|
14
20
|
vertical_box {
|
15
21
|
button {
|
16
|
-
# data-bind button text to
|
17
|
-
text <= [
|
22
|
+
# data-bind button text to @counter count, converting to string on read from model.
|
23
|
+
text <= [@counter, :count, on_read: ->(count) {"Count: #{count}"}]
|
18
24
|
|
19
25
|
on_clicked do
|
20
|
-
|
26
|
+
# This change will automatically propagate to button text through data-binding above
|
27
|
+
@counter.count += 1
|
21
28
|
end
|
22
29
|
}
|
23
30
|
}
|
24
|
-
}
|
25
|
-
|
31
|
+
}
|
32
|
+
}
|
26
33
|
end
|
27
34
|
|
28
|
-
ButtonCounter.
|
35
|
+
ButtonCounter.launch
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'glimmer-dsl-libui'
|
2
|
+
|
3
|
+
class User
|
4
|
+
ALL_ATTRIBUTES = [:first_name, :last_name, :email, :street, :city, :state, :zip_code, :country]
|
5
|
+
|
6
|
+
attr_accessor :customizable_attributes, *ALL_ATTRIBUTES
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
# allow customizing all attributes by default
|
10
|
+
self.customizable_attributes = ALL_ATTRIBUTES.dup
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class DynamicForm
|
15
|
+
include Glimmer::LibUI::Application
|
16
|
+
|
17
|
+
before_body do
|
18
|
+
@user = User.new
|
19
|
+
end
|
20
|
+
|
21
|
+
body {
|
22
|
+
window('Dynamic Form') {
|
23
|
+
margined true
|
24
|
+
|
25
|
+
vertical_box {
|
26
|
+
horizontal_box {
|
27
|
+
User::ALL_ATTRIBUTES.each do |attribute|
|
28
|
+
checkbox(attribute.to_s) {
|
29
|
+
checked <=> [@user, :customizable_attributes,
|
30
|
+
on_read: -> (attributes) { @user.customizable_attributes.include?(attribute) },
|
31
|
+
on_write: -> (checked_value) {
|
32
|
+
if checked_value
|
33
|
+
@user.customizable_attributes.push(attribute)
|
34
|
+
else
|
35
|
+
@user.customizable_attributes.delete(attribute)
|
36
|
+
end
|
37
|
+
@user.customizable_attributes.sort_by {|attribute| User::ALL_ATTRIBUTES.index(attribute)}
|
38
|
+
},
|
39
|
+
]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
}
|
43
|
+
|
44
|
+
form {
|
45
|
+
stretchy false
|
46
|
+
|
47
|
+
# Control content data-binding allows dynamically changing content based on changes in a model attribute
|
48
|
+
content(@user, :customizable_attributes) {
|
49
|
+
@user.customizable_attributes.each do |attribute|
|
50
|
+
entry {
|
51
|
+
label attribute.to_s.split('_').map(&:capitalize).join(' ')
|
52
|
+
text <=> [@user, attribute]
|
53
|
+
}
|
54
|
+
end
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
button('Summarize') {
|
59
|
+
on_clicked do
|
60
|
+
summary = @user.customizable_attributes.map { |attribute| @user.send(attribute) }.join(', ')
|
61
|
+
msg_box('Summary', summary)
|
62
|
+
end
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
DynamicForm.launch
|
@@ -47,10 +47,33 @@ class Snake
|
|
47
47
|
self.joins.clear
|
48
48
|
end
|
49
49
|
|
50
|
+
def turn_right
|
51
|
+
head.orientation = RIGHT_TURN_MAP[head.orientation]
|
52
|
+
end
|
53
|
+
|
54
|
+
def turn_left
|
55
|
+
head.orientation = LEFT_TURN_MAP[head.orientation]
|
56
|
+
end
|
57
|
+
|
50
58
|
def move
|
51
|
-
|
59
|
+
create_new_head
|
60
|
+
remove_old_tail
|
61
|
+
if detect_collision?
|
62
|
+
collide_and_die
|
63
|
+
else
|
64
|
+
append_new_head
|
65
|
+
eat_apple if detect_apple?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def remove_old_tail
|
70
|
+
@old_tail = tail.dup # save in case of growing and keeping old tail
|
71
|
+
@vertebrae.delete(tail)
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_new_head
|
52
75
|
@new_head = head.dup
|
53
|
-
case
|
76
|
+
case head.orientation
|
54
77
|
when :east
|
55
78
|
@new_head.column = (@new_head.column + 1) % @game.width
|
56
79
|
when :west
|
@@ -60,25 +83,28 @@ class Snake
|
|
60
83
|
when :north
|
61
84
|
@new_head.row = (@new_head.row - 1) % @game.height
|
62
85
|
end
|
63
|
-
if @vertebrae.map {|v| [v.row, v.column]}.include?([@new_head.row, @new_head.column])
|
64
|
-
self.collided = true
|
65
|
-
@game.over = true
|
66
|
-
else
|
67
|
-
@vertebrae.append(@new_head)
|
68
|
-
@vertebrae.delete(tail)
|
69
|
-
if head.row == @game.apple.row && head.column == @game.apple.column
|
70
|
-
grow
|
71
|
-
@game.apple.generate
|
72
|
-
end
|
73
|
-
end
|
74
86
|
end
|
75
87
|
|
76
|
-
def
|
77
|
-
|
88
|
+
def append_new_head
|
89
|
+
@vertebrae.append(@new_head)
|
78
90
|
end
|
79
91
|
|
80
|
-
def
|
81
|
-
|
92
|
+
def detect_collision?
|
93
|
+
@vertebrae.map {|v| [v.row, v.column]}.include?([@new_head.row, @new_head.column])
|
94
|
+
end
|
95
|
+
|
96
|
+
def collide_and_die
|
97
|
+
self.collided = true
|
98
|
+
@game.over = true
|
99
|
+
end
|
100
|
+
|
101
|
+
def detect_apple?
|
102
|
+
head.row == @game.apple.row && head.column == @game.apple.column
|
103
|
+
end
|
104
|
+
|
105
|
+
def eat_apple
|
106
|
+
grow
|
107
|
+
@game.apple.generate
|
82
108
|
end
|
83
109
|
|
84
110
|
def grow
|
data/examples/snake.rb
CHANGED
@@ -72,12 +72,16 @@ class Snake
|
|
72
72
|
fill <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
|
73
73
|
}
|
74
74
|
|
75
|
-
|
75
|
+
on_key_down do |area_key_event|
|
76
|
+
handled = true # assume we will handle the event
|
76
77
|
if area_key_event[:key] == ' '
|
77
78
|
@game.toggle_pause
|
78
|
-
|
79
|
+
elsif %i[up right down left].include?(area_key_event[:ext_key])
|
79
80
|
@keypress_queue << area_key_event[:ext_key]
|
81
|
+
else
|
82
|
+
handled = false # we won't handle the event after all
|
80
83
|
end
|
84
|
+
handled
|
81
85
|
end
|
82
86
|
}
|
83
87
|
end
|
data/glimmer-dsl-libui.gemspec
CHANGED
Binary file
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright (c) 2021-2023 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer/dsl/static_expression'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module DSL
|
26
|
+
module Libui
|
27
|
+
class ContentExpression < StaticExpression
|
28
|
+
def can_interpret?(parent, keyword, *args, &block)
|
29
|
+
keyword == 'content' &&
|
30
|
+
block_given? &&
|
31
|
+
args.size > 0 &&
|
32
|
+
parent&.respond_to?(:bind_content)
|
33
|
+
end
|
34
|
+
|
35
|
+
def interpret(parent, keyword, *args, &block)
|
36
|
+
parent.bind_content(*args, &block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -384,6 +384,19 @@ module Glimmer
|
|
384
384
|
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Libui::ControlExpression.new, @keyword, {post_add_content: @content_added}, &block)
|
385
385
|
end
|
386
386
|
|
387
|
+
# Data-binds the generation of nested content to a model/property (in binding args)
|
388
|
+
# consider providing an option to avoid initial rendering without any changes happening
|
389
|
+
def bind_content(*binding_args, &content_block)
|
390
|
+
# TODO in the future, consider optimizing code by diffing content if that makes sense
|
391
|
+
content_binding_work = proc do |*values|
|
392
|
+
children.dup.each { |child| child.destroy }
|
393
|
+
content(&content_block)
|
394
|
+
end
|
395
|
+
content_binding_observer = Glimmer::DataBinding::Observer.proc(&content_binding_work)
|
396
|
+
content_binding_observer.observe(*binding_args)
|
397
|
+
content_binding_work.call # TODO inspect if we need to pass args here (from observed attributes) [but it's simpler not to pass anything at first]
|
398
|
+
end
|
399
|
+
|
387
400
|
private
|
388
401
|
|
389
402
|
def build_control
|
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
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -437,6 +437,7 @@ files:
|
|
437
437
|
- examples/dynamic_area2.rb
|
438
438
|
- examples/dynamic_area3.rb
|
439
439
|
- examples/dynamic_area4.rb
|
440
|
+
- examples/dynamic_form.rb
|
440
441
|
- examples/editable_column_table.rb
|
441
442
|
- examples/editable_table.rb
|
442
443
|
- examples/font_button.rb
|
@@ -500,6 +501,7 @@ files:
|
|
500
501
|
- lib/glimmer-dsl-libui/ext/rouge/theme/glimmer.rb
|
501
502
|
- lib/glimmer/Rakefile
|
502
503
|
- lib/glimmer/dsl/libui/bind_expression.rb
|
504
|
+
- lib/glimmer/dsl/libui/content_expression.rb
|
503
505
|
- lib/glimmer/dsl/libui/control_expression.rb
|
504
506
|
- lib/glimmer/dsl/libui/custom_control_expression.rb
|
505
507
|
- lib/glimmer/dsl/libui/custom_shape_expression.rb
|