glimmer-dsl-libui 0.3.5 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +4364 -3406
  4. data/VERSION +1 -1
  5. data/examples/basic_entry.rb +27 -24
  6. data/examples/basic_entry2.rb +31 -0
  7. data/examples/button_counter.rb +27 -0
  8. data/examples/color_the_circles.rb +2 -2
  9. data/examples/form.rb +42 -30
  10. data/examples/form2.rb +37 -0
  11. data/examples/form_table.rb +100 -85
  12. data/examples/form_table2.rb +95 -0
  13. data/examples/login.rb +45 -39
  14. data/examples/login2.rb +55 -0
  15. data/examples/login3.rb +65 -0
  16. data/examples/login4.rb +61 -0
  17. data/examples/login5.rb +43 -0
  18. data/examples/meta_example.rb +10 -7
  19. data/examples/method_based_custom_keyword.rb +8 -15
  20. data/examples/method_based_custom_keyword2.rb +97 -0
  21. data/examples/midi_player.rb +2 -6
  22. data/examples/snake/model/game.rb +2 -2
  23. data/examples/snake/presenter/grid.rb +5 -3
  24. data/examples/snake.rb +11 -21
  25. data/examples/tetris.rb +12 -12
  26. data/examples/tic_tac_toe.rb +3 -12
  27. data/examples/timer.rb +2 -6
  28. data/glimmer-dsl-libui.gemspec +0 -0
  29. data/lib/glimmer/dsl/libui/bind_expression.rb +36 -0
  30. data/lib/glimmer/dsl/libui/data_binding_expression.rb +45 -0
  31. data/lib/glimmer/dsl/libui/dsl.rb +3 -0
  32. data/lib/glimmer/dsl/libui/observe_expression.rb +35 -0
  33. data/lib/glimmer/dsl/libui/shine_data_binding_expression.rb +42 -0
  34. data/lib/glimmer/dsl/libui/string_expression.rb +4 -5
  35. data/lib/glimmer/libui/attributed_string.rb +19 -6
  36. data/lib/glimmer/libui/control_proxy/area_proxy.rb +52 -46
  37. data/lib/glimmer/libui/control_proxy/entry_proxy.rb +5 -0
  38. data/lib/glimmer/libui/control_proxy/image_proxy.rb +4 -5
  39. data/lib/glimmer/libui/control_proxy/multiline_entry_proxy.rb +5 -0
  40. data/lib/glimmer/libui/control_proxy/table_proxy.rb +1 -1
  41. data/lib/glimmer/libui/control_proxy.rb +16 -1
  42. data/lib/glimmer/libui/shape.rb +6 -3
  43. metadata +17 -4
data/examples/timer.rb CHANGED
@@ -19,12 +19,8 @@ class Timer
19
19
 
20
20
  def stop_alarm
21
21
  if @pid
22
- if @th.alive?
23
- Process.kill(:SIGKILL, @pid)
24
- @pid = nil
25
- else
26
- @pid = nil
27
- end
22
+ Process.kill(:SIGKILL, @pid) if @th.alive?
23
+ @pid = nil
28
24
  end
29
25
  end
30
26
 
Binary file
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2021 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
+ require 'glimmer/dsl/bind_expression'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Libui
28
+ # Responsible for setting up the return value of the bind keyword (command symbol)
29
+ # as a ModelBinding. It is then used by another command handler like
30
+ # DataBindingExpression
31
+ class BindExpression < StaticExpression
32
+ include Glimmer::DSL::BindExpression
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright (c) 2021 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/expression'
23
+ require 'glimmer/data_binding/model_binding'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Libui
28
+ # Responsible for wiring data-binding
29
+ # Depends on BindExpression
30
+ class DataBindingExpression < Expression
31
+ def can_interpret?(parent, keyword, *args, &block)
32
+ args.size == 1 and
33
+ args[0].is_a?(DataBinding::ModelBinding) and
34
+ parent.respond_to?(:data_bind)
35
+ end
36
+
37
+ def interpret(parent, keyword, *args, &block)
38
+ property = keyword
39
+ model_binding = args[0]
40
+ parent.data_bind(property, model_binding)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -37,7 +37,10 @@ module Glimmer
37
37
  Libui,
38
38
  %w[
39
39
  listener
40
+ data_binding
41
+ shine_data_binding
40
42
  property
43
+ string
41
44
  control
42
45
  shape
43
46
  ]
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2021 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
+ require 'glimmer/dsl/top_level_expression'
24
+ require 'glimmer/dsl/observe_expression'
25
+
26
+ module Glimmer
27
+ module DSL
28
+ module SWT
29
+ class ObserveExpression < StaticExpression
30
+ include TopLevelExpression
31
+ include Glimmer::DSL::ObserveExpression
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright (c) 2021 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/expression'
23
+ require 'glimmer/data_binding/model_binding'
24
+ require 'glimmer/data_binding/shine'
25
+
26
+ module Glimmer
27
+ module DSL
28
+ module Libui
29
+ class ShineDataBindingExpression < Expression
30
+ def can_interpret?(parent, keyword, *args, &block)
31
+ args.size == 0 and
32
+ block.nil? and
33
+ parent.respond_to?(keyword, *args, &block)
34
+ end
35
+
36
+ def interpret(parent, keyword, *args, &block)
37
+ Glimmer::DataBinding::Shine.new(parent, keyword)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -19,7 +19,6 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- require 'glimmer/dsl/static_expression'
23
22
  require 'glimmer/dsl/parent_expression'
24
23
  require 'glimmer/libui/control_proxy/text_proxy'
25
24
  require 'glimmer/libui/attributed_string'
@@ -27,14 +26,14 @@ require 'glimmer/libui/attributed_string'
27
26
  module Glimmer
28
27
  module DSL
29
28
  module Libui
30
- class StringExpression < StaticExpression
29
+ class StringExpression < Expression
31
30
  include ParentExpression
32
31
 
33
32
  def can_interpret?(parent, keyword, *args, &block)
34
- super and
33
+ keyword == 'string' and
35
34
  (
36
35
  parent.is_a?(Glimmer::LibUI::ControlProxy::TextProxy) or
37
- parent.is_a?(Glimmer::LibUI::AttributedString)
36
+ (parent.is_a?(Glimmer::LibUI::AttributedString) and !args.empty?)
38
37
  )
39
38
  end
40
39
 
@@ -47,7 +46,7 @@ module Glimmer
47
46
  end
48
47
 
49
48
  def add_content(parent, keyword, *args, &block)
50
- parent.post_add_content
49
+ parent.post_add_content(block)
51
50
  end
52
51
  end
53
52
  end
@@ -27,7 +27,8 @@ require 'glimmer/libui/control_proxy/transformable'
27
27
  module Glimmer
28
28
  module LibUI
29
29
  class AttributedString
30
- attr_reader :block, :keyword, :parent_proxy, :args
30
+ attr_reader :keyword, :parent_proxy, :args
31
+ attr_accessor :block
31
32
 
32
33
  def initialize(keyword, parent_proxy, args, &block)
33
34
  @keyword = keyword
@@ -115,10 +116,14 @@ module Glimmer
115
116
  alias open_type_features= open_type_features
116
117
  alias set_open_type_features open_type_features
117
118
 
118
- def post_add_content
119
- block_result = @block&.call
120
- @string = block_result if block_result.is_a?(String)
121
- @parent_proxy&.post_initialize_child(self)
119
+ def post_add_content(block = nil)
120
+ block ||= @block
121
+ block_result = block&.call
122
+ unless @content_added
123
+ @string = block_result if block_result.is_a?(String)
124
+ @parent_proxy&.post_initialize_child(self)
125
+ @content_added = true
126
+ end
122
127
  end
123
128
 
124
129
  def post_initialize_child(child)
@@ -185,12 +190,20 @@ module Glimmer
185
190
  end
186
191
 
187
192
  def redraw
188
- area_proxy&.queue_redraw_all
193
+ area_proxy&.redraw
194
+ end
195
+
196
+ def request_auto_redraw
197
+ area_proxy&.request_auto_redraw
189
198
  end
190
199
 
191
200
  def area_proxy
192
201
  @parent_proxy.parent_proxy
193
202
  end
203
+
204
+ def content(&block)
205
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Libui::StringExpression.new, @keyword, &block)
206
+ end
194
207
  end
195
208
  end
196
209
  end
@@ -86,14 +86,17 @@ module Glimmer
86
86
 
87
87
  def post_add_content
88
88
  unless parent_proxy.is_a?(Box)
89
- original_parent_proxy = @parent_proxy
90
- @vertical_box_parent_proxy = ControlProxy.create('vertical_box', parent_proxy, []) {} # block prevents calling post add content
91
- append_properties.each do |property|
92
- @vertical_box_parent_proxy.append_property(property, append_property(property))
89
+ unless @content_added
90
+ original_parent_proxy = @parent_proxy
91
+ @vertical_box_parent_proxy = ControlProxy.create('vertical_box', parent_proxy, []) {} # block prevents calling post add content
92
+ append_properties.each do |property|
93
+ @vertical_box_parent_proxy.append_property(property, append_property(property))
94
+ end
95
+ @vertical_box_parent_proxy.post_add_content
96
+ @parent_proxy = @vertical_box_parent_proxy
97
+ @vertical_box_parent_proxy.post_initialize_child(self)
98
+ @content_added = true
93
99
  end
94
- @vertical_box_parent_proxy.post_add_content
95
- @parent_proxy = @vertical_box_parent_proxy
96
- @vertical_box_parent_proxy.post_initialize_child(self)
97
100
  else
98
101
  super
99
102
  end
@@ -142,48 +145,51 @@ module Glimmer
142
145
  end
143
146
 
144
147
  def install_listeners
145
- @area_handler.Draw = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_draw_params|
146
- area_draw_params = ::LibUI::FFI::AreaDrawParams.new(area_draw_params)
147
- area_draw_params = area_draw_params_hash(area_draw_params)
148
- AreaProxy.current_area_draw_params = area_draw_params
149
- draw(area_draw_params)
150
- AreaProxy.current_area_draw_params = nil
151
- end
152
- @area_handler.MouseEvent = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_mouse_event|
153
- area_mouse_event = ::LibUI::FFI::AreaMouseEvent.new(area_mouse_event)
154
- area_mouse_event = area_mouse_event_hash(area_mouse_event)
155
- on_mouse_event.each { |listener| listener.call(area_mouse_event)}
156
- on_mouse_move.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:x].between?(0, area_mouse_event[:area_width]) && area_mouse_event[:y].between?(0, area_mouse_event[:area_height])
157
- unless @last_area_mouse_event.nil?
158
- on_mouse_down.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:down] > 0 && @last_area_mouse_event[:down] == 0
159
- on_mouse_up.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:up] > 0 && @last_area_mouse_event[:up] == 0
160
- on_mouse_drag_start.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] > 0 && @last_area_mouse_event[:held] == 0
161
- on_mouse_drag.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] > 0
162
- on_mouse_drop.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] == 0 && @last_area_mouse_event[:held] > 0
148
+ unless @listeners_installed
149
+ @area_handler.Draw = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_draw_params|
150
+ area_draw_params = ::LibUI::FFI::AreaDrawParams.new(area_draw_params)
151
+ area_draw_params = area_draw_params_hash(area_draw_params)
152
+ AreaProxy.current_area_draw_params = area_draw_params
153
+ draw(area_draw_params)
154
+ AreaProxy.current_area_draw_params = nil
163
155
  end
164
- @last_area_mouse_event = area_mouse_event
165
- end
166
- @area_handler.MouseCrossed = fiddle_closure_block_caller(0, [1, 1, 4]) do |_, _, left|
167
- left = Glimmer::LibUI.integer_to_boolean(left)
168
- on_mouse_crossed.each { |listener| listener.call(left) }
169
- if left
170
- on_mouse_exit.each { |listener| listener.call(left) }
171
- else
172
- on_mouse_enter.each { |listener| listener.call(left) }
156
+ @area_handler.MouseEvent = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_mouse_event|
157
+ area_mouse_event = ::LibUI::FFI::AreaMouseEvent.new(area_mouse_event)
158
+ area_mouse_event = area_mouse_event_hash(area_mouse_event)
159
+ on_mouse_event.each { |listener| listener.call(area_mouse_event)}
160
+ on_mouse_move.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:x].between?(0, area_mouse_event[:area_width]) && area_mouse_event[:y].between?(0, area_mouse_event[:area_height])
161
+ unless @last_area_mouse_event.nil?
162
+ on_mouse_down.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:down] > 0 && @last_area_mouse_event[:down] == 0
163
+ on_mouse_up.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:up] > 0 && @last_area_mouse_event[:up] == 0
164
+ on_mouse_drag_start.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] > 0 && @last_area_mouse_event[:held] == 0
165
+ on_mouse_drag.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] > 0
166
+ on_mouse_drop.each { |listener| listener.call(area_mouse_event)} if area_mouse_event[:held] == 0 && @last_area_mouse_event[:held] > 0
167
+ end
168
+ @last_area_mouse_event = area_mouse_event
173
169
  end
174
- end
175
- @area_handler.DragBroken = fiddle_closure_block_caller(0, [1, 1]) do |_, _|
176
- on_drag_broken.each { |listener| listener.call }
177
- end
178
- @area_handler.KeyEvent = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_key_event|
179
- area_key_event = ::LibUI::FFI::AreaKeyEvent.new(area_key_event)
180
- area_key_event = area_key_event_hash(area_key_event)
181
- on_key_event.each { |listener| listener.call(area_key_event) }
182
- if area_key_event[:up]
183
- on_key_up.each { |listener| listener.call(area_key_event) }
184
- else
185
- on_key_down.each { |listener| listener.call(area_key_event) }
170
+ @area_handler.MouseCrossed = fiddle_closure_block_caller(0, [1, 1, 4]) do |_, _, left|
171
+ left = Glimmer::LibUI.integer_to_boolean(left)
172
+ on_mouse_crossed.each { |listener| listener.call(left) }
173
+ if left
174
+ on_mouse_exit.each { |listener| listener.call(left) }
175
+ else
176
+ on_mouse_enter.each { |listener| listener.call(left) }
177
+ end
178
+ end
179
+ @area_handler.DragBroken = fiddle_closure_block_caller(0, [1, 1]) do |_, _|
180
+ on_drag_broken.each { |listener| listener.call }
181
+ end
182
+ @area_handler.KeyEvent = fiddle_closure_block_caller(0, [1, 1, 1]) do |_, _, area_key_event|
183
+ area_key_event = ::LibUI::FFI::AreaKeyEvent.new(area_key_event)
184
+ area_key_event = area_key_event_hash(area_key_event)
185
+ on_key_event.each { |listener| listener.call(area_key_event) }
186
+ if area_key_event[:up]
187
+ on_key_up.each { |listener| listener.call(area_key_event) }
188
+ else
189
+ on_key_down.each { |listener| listener.call(area_key_event) }
190
+ end
186
191
  end
192
+ @listeners_installed = true
187
193
  end
188
194
  end
189
195
 
@@ -28,6 +28,11 @@ module Glimmer
28
28
  #
29
29
  # Follows the Proxy Design Pattern
30
30
  class EntryProxy < ControlProxy
31
+ def data_bind(property, model_binding)
32
+ super
33
+ handle_listener('on_changed') { model_binding.call(text) } if property == 'text'
34
+ end
35
+
31
36
  def libui_api_keyword
32
37
  'entry'
33
38
  end
@@ -56,9 +56,8 @@ module Glimmer
56
56
  draw(AreaProxy.current_area_draw_params)
57
57
  destroy
58
58
  end
59
- @content_added = true
60
59
  else # image object not control
61
- build_control
60
+ build_control unless @content_added
62
61
  super
63
62
  end
64
63
  end
@@ -68,7 +67,7 @@ module Glimmer
68
67
  @args[0]
69
68
  else
70
69
  @args[0] = value
71
- if @content_added
70
+ if area_image? && @content_added
72
71
  post_add_content
73
72
  request_auto_redraw
74
73
  end
@@ -167,8 +166,8 @@ module Glimmer
167
166
  end
168
167
  canvas.resample_nearest_neighbor!(width, height) if width && height
169
168
  @data = canvas.to_rgba_stream
170
- self.width = canvas.width
171
- self.height = canvas.height
169
+ @args[1] = canvas.width
170
+ @args[2] = canvas.height
172
171
  [@data, width, height]
173
172
  end
174
173
 
@@ -28,6 +28,11 @@ module Glimmer
28
28
  #
29
29
  # Follows the Proxy Design Pattern
30
30
  class MultilineEntryProxy < ControlProxy
31
+ def data_bind(property, model_binding)
32
+ super
33
+ handle_listener('on_changed') { model_binding.call(text) } if property == 'text'
34
+ end
35
+
31
36
  def libui_api_keyword
32
37
  'multiline_entry'
33
38
  end
@@ -55,7 +55,7 @@ module Glimmer
55
55
  end
56
56
 
57
57
  def post_add_content
58
- build_control
58
+ build_control unless @content_added
59
59
  super
60
60
  end
61
61
 
@@ -136,7 +136,10 @@ module Glimmer
136
136
 
137
137
  # Subclasses may override to perform post add_content work (normally must call super)
138
138
  def post_add_content
139
- @parent_proxy&.post_initialize_child(self)
139
+ unless @content_added
140
+ @parent_proxy&.post_initialize_child(self)
141
+ @content_added = true
142
+ end
140
143
  end
141
144
 
142
145
  # Subclasses may override to perform post initialization work on an added child
@@ -329,6 +332,18 @@ module Glimmer
329
332
  alias set_visible visible
330
333
  alias visible= visible
331
334
 
335
+ # Data-binds model to update view.
336
+ # Subclasses can override to do inverse data-binding by observing view control for property changes and updating model binding accordingly
337
+ def data_bind(property, model_binding)
338
+ model_attribute_observer = Glimmer::DataBinding::Observer.proc do
339
+ new_value = model_binding.evaluate_property
340
+ send("#{property}=", new_value) unless send(property) == new_value
341
+ end
342
+ model_attribute_observer.observe(model_binding)
343
+ model_attribute_observer.call # initial update
344
+ model_attribute_observer
345
+ end
346
+
332
347
  def content(&block)
333
348
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Libui::ControlExpression.new, @keyword, &block)
334
349
  end
@@ -79,8 +79,11 @@ module Glimmer
79
79
 
80
80
  # Subclasses may override to perform post add_content work (normally must call super)
81
81
  def post_add_content
82
- @parent&.post_initialize_child(self)
83
- @parent.post_add_content if implicit_path? && dynamic?
82
+ unless @content_added
83
+ @parent&.post_initialize_child(self)
84
+ @parent.post_add_content if implicit_path? && dynamic?
85
+ @content_added = true
86
+ end
84
87
  end
85
88
 
86
89
  def post_initialize_child(child, add_child: true)
@@ -102,7 +105,7 @@ module Glimmer
102
105
  end
103
106
 
104
107
  def redraw
105
- area_proxy&.auto_redraw
108
+ area_proxy&.redraw
106
109
  end
107
110
 
108
111
  def request_auto_redraw
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.3.5
4
+ version: 0.4.3
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-21 00:00:00.000000000 Z
11
+ date: 2021-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -64,14 +64,14 @@ dependencies:
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 0.0.12
67
+ version: 0.0.13
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 0.0.12
74
+ version: 0.0.13
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: chunky_png
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -223,6 +223,7 @@ files:
223
223
  - examples/basic_draw_text.rb
224
224
  - examples/basic_draw_text2.rb
225
225
  - examples/basic_entry.rb
226
+ - examples/basic_entry2.rb
226
227
  - examples/basic_image.rb
227
228
  - examples/basic_image2.rb
228
229
  - examples/basic_image3.rb
@@ -244,6 +245,7 @@ files:
244
245
  - examples/basic_transform2.rb
245
246
  - examples/basic_window.rb
246
247
  - examples/basic_window2.rb
248
+ - examples/button_counter.rb
247
249
  - examples/color_button.rb
248
250
  - examples/color_the_circles.rb
249
251
  - examples/control_gallery.rb
@@ -256,12 +258,19 @@ files:
256
258
  - examples/editable_table.rb
257
259
  - examples/font_button.rb
258
260
  - examples/form.rb
261
+ - examples/form2.rb
259
262
  - examples/form_table.rb
263
+ - examples/form_table2.rb
260
264
  - examples/grid.rb
261
265
  - examples/histogram.rb
262
266
  - examples/login.rb
267
+ - examples/login2.rb
268
+ - examples/login3.rb
269
+ - examples/login4.rb
270
+ - examples/login5.rb
263
271
  - examples/meta_example.rb
264
272
  - examples/method_based_custom_keyword.rb
273
+ - examples/method_based_custom_keyword2.rb
265
274
  - examples/midi_player.rb
266
275
  - examples/simple_notepad.rb
267
276
  - examples/snake.rb
@@ -283,14 +292,18 @@ files:
283
292
  - glimmer-dsl-libui.gemspec
284
293
  - icons/glimmer.png
285
294
  - lib/glimmer-dsl-libui.rb
295
+ - lib/glimmer/dsl/libui/bind_expression.rb
286
296
  - lib/glimmer/dsl/libui/control_expression.rb
297
+ - lib/glimmer/dsl/libui/data_binding_expression.rb
287
298
  - lib/glimmer/dsl/libui/dsl.rb
288
299
  - lib/glimmer/dsl/libui/file_expression.rb
289
300
  - lib/glimmer/dsl/libui/listener_expression.rb
301
+ - lib/glimmer/dsl/libui/observe_expression.rb
290
302
  - lib/glimmer/dsl/libui/open_file_expression.rb
291
303
  - lib/glimmer/dsl/libui/property_expression.rb
292
304
  - lib/glimmer/dsl/libui/save_file_expression.rb
293
305
  - lib/glimmer/dsl/libui/shape_expression.rb
306
+ - lib/glimmer/dsl/libui/shine_data_binding_expression.rb
294
307
  - lib/glimmer/dsl/libui/string_expression.rb
295
308
  - lib/glimmer/dsl/libui/tab_item_expression.rb
296
309
  - lib/glimmer/fiddle_consumer.rb