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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21db2452d3dfbb5c34356de87e7c40380d4e887a25181854321a226cee7640b5
4
- data.tar.gz: 5f62aa411e6c890e0c8228d286f273d4ebb056af7b771313a49db0344340a773
3
+ metadata.gz: effb65102f9db3aa2977bac55edd4f67f91f1eafdae26403b8c044c714048a03
4
+ data.tar.gz: 3923d80a19afd62a0220026f33720ee953ad166880e17d60883aed53f9977d86
5
5
  SHA512:
6
- metadata.gz: fabf5fd00b7994fce070e6c200814381c3fbc7df0c38e7742e5d1207d76f0c0e9d1946d5b882ee5c372acd7cc6876e485596d760127a52ada556e6402de2dd31
7
- data.tar.gz: 37f4312b11de8d5f2678c2f31e966acfed33617224fcdd4217effdd169bcfd61721b1d1ff64236a4e0957d991f86127fc6c0db55170b3e0b92d5831c5cbc51ec
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, describing composite shapes/text/image concepts inside an `area`
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.10.1
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.10.1'
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
- Require [glimmer-dsl-libui](https://rubygems.org/gems/glimmer-dsl-libui) (whether through a Ruby `require` statement or `Bundler`) and then include the `Glimmer` or `Glimmer::LibUI::Application` module to enable access to the Glimmer GUI DSL in one of multiple approaches.
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 <=> [self, :entered_text, after_write: ->(text) {puts 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 `self` to `entry` `text` property and printing text after write to the model.
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.10.1
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)
@@ -1,28 +1,35 @@
1
1
  require 'glimmer-dsl-libui'
2
2
 
3
- class ButtonCounter
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
- def launch
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 self count, converting to string on read.
17
- text <= [self, :count, on_read: ->(count) {"Count: #{count}"}]
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
- self.count += 1
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
- }.show
25
- end
31
+ }
32
+ }
26
33
  end
27
34
 
28
- ButtonCounter.new.launch
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
- @old_tail = tail.dup
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 @new_head.orientation
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 turn_right
77
- head.orientation = RIGHT_TURN_MAP[head.orientation]
88
+ def append_new_head
89
+ @vertebrae.append(@new_head)
78
90
  end
79
91
 
80
- def turn_left
81
- head.orientation = LEFT_TURN_MAP[head.orientation]
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
- on_key_up do |area_key_event|
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
- else
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
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
@@ -40,6 +40,7 @@ module Glimmer
40
40
  data_binding
41
41
  shine_data_binding
42
42
  property
43
+ content
43
44
  string
44
45
  operation
45
46
  control
@@ -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.10.1
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-10-27 00:00:00.000000000 Z
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