glimmer-dsl-libui 0.1.2 → 0.1.6

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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/README.md +1127 -65
  4. data/VERSION +1 -1
  5. data/examples/area_gallery.rb +50 -0
  6. data/examples/area_gallery2.rb +111 -0
  7. data/examples/area_gallery3.rb +52 -0
  8. data/examples/area_gallery4.rb +113 -0
  9. data/examples/basic_area2.rb +1 -1
  10. data/examples/basic_button.rb +2 -2
  11. data/examples/basic_entry.rb +2 -2
  12. data/examples/basic_table_progress_bar.rb +13 -3
  13. data/examples/basic_transform.rb +27 -0
  14. data/examples/control_gallery.rb +3 -3
  15. data/examples/dynamic_area.rb +1 -1
  16. data/examples/form.rb +2 -2
  17. data/examples/histogram.rb +118 -0
  18. data/examples/meta_example.rb +71 -20
  19. data/examples/midi_player.rb +8 -10
  20. data/glimmer-dsl-libui.gemspec +0 -0
  21. data/lib/glimmer/dsl/libui/control_expression.rb +1 -3
  22. data/lib/glimmer/dsl/libui/dsl.rb +1 -0
  23. data/lib/glimmer/dsl/libui/file_expression.rb +5 -1
  24. data/lib/glimmer/dsl/libui/property_expression.rb +5 -1
  25. data/lib/glimmer/{libui/box.rb → dsl/libui/shape_expression.rb} +26 -29
  26. data/lib/glimmer/dsl/libui/tab_item_expression.rb +2 -2
  27. data/lib/glimmer/libui/control_proxy/area_proxy.rb +117 -0
  28. data/lib/glimmer/libui/{menu_item_proxy.rb → control_proxy/box/horizontal_box_proxy.rb} +9 -12
  29. data/lib/glimmer/libui/{vertical_box_proxy.rb → control_proxy/box/vertical_box_proxy.rb} +10 -6
  30. data/lib/glimmer/libui/control_proxy/box.rb +61 -0
  31. data/lib/glimmer/libui/{button_proxy.rb → control_proxy/button_proxy.rb} +14 -12
  32. data/lib/glimmer/libui/{checkbox_proxy.rb → control_proxy/checkbox_proxy.rb} +14 -12
  33. data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +118 -0
  34. data/lib/glimmer/libui/control_proxy/column/button_column_proxy.rb +76 -0
  35. data/lib/glimmer/libui/control_proxy/column/checkbox_column_proxy.rb +46 -0
  36. data/lib/glimmer/libui/control_proxy/column/checkbox_text_column_proxy.rb +80 -0
  37. data/lib/glimmer/libui/{radio_buttons_proxy.rb → control_proxy/column/image_column_proxy.rb} +14 -13
  38. data/lib/glimmer/libui/control_proxy/column/image_text_column_proxy.rb +48 -0
  39. data/lib/glimmer/libui/{progress_bar_column_proxy.rb → control_proxy/column/progress_bar_column_proxy.rb} +14 -10
  40. data/lib/glimmer/libui/control_proxy/column/text_column_proxy.rb +46 -0
  41. data/lib/glimmer/libui/control_proxy/column.rb +55 -0
  42. data/lib/glimmer/libui/{checkbox_column_proxy.rb → control_proxy/combobox_proxy.rb} +16 -13
  43. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy/date_picker_proxy.rb +43 -0
  44. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy/time_picker_proxy.rb +43 -0
  45. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +72 -0
  46. data/lib/glimmer/libui/control_proxy/dual_column.rb +40 -0
  47. data/lib/glimmer/libui/control_proxy/editable_column.rb +46 -0
  48. data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +45 -0
  49. data/lib/glimmer/libui/{dual_column.rb → control_proxy/enableable_column.rb} +18 -10
  50. data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +70 -0
  51. data/lib/glimmer/libui/{form_proxy.rb → control_proxy/form_proxy.rb} +26 -24
  52. data/lib/glimmer/libui/{grid_proxy.rb → control_proxy/grid_proxy.rb} +29 -27
  53. data/lib/glimmer/libui/{group_proxy.rb → control_proxy/group_proxy.rb} +24 -22
  54. data/lib/glimmer/libui/{image_part_proxy.rb → control_proxy/image_part_proxy.rb} +20 -18
  55. data/lib/glimmer/libui/{image_proxy.rb → control_proxy/image_proxy.rb} +32 -30
  56. data/lib/glimmer/libui/{combobox_proxy.rb → control_proxy/label_proxy.rb} +13 -13
  57. data/lib/glimmer/libui/control_proxy/matrix_proxy.rb +147 -0
  58. data/lib/glimmer/libui/{editable_column.rb → control_proxy/menu_item_proxy/about_menu_item_proxy.rb} +13 -16
  59. data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +41 -0
  60. data/lib/glimmer/libui/{preferences_menu_item_proxy.rb → control_proxy/menu_item_proxy/preferences_menu_item_proxy.rb} +11 -9
  61. data/lib/glimmer/libui/control_proxy/menu_item_proxy/quit_menu_item_proxy.rb +66 -0
  62. data/lib/glimmer/libui/control_proxy/menu_item_proxy/separator_menu_item_proxy.rb +41 -0
  63. data/lib/glimmer/libui/control_proxy/menu_item_proxy.rb +45 -0
  64. data/lib/glimmer/libui/{editable_combobox_proxy.rb → control_proxy/menu_proxy.rb} +13 -13
  65. data/lib/glimmer/libui/{horizontal_box_proxy.rb → control_proxy/message_box/msg_box_error_proxy.rb} +9 -6
  66. data/lib/glimmer/libui/{multiline_entry_proxy.rb → control_proxy/message_box/msg_box_proxy.rb} +8 -6
  67. data/lib/glimmer/libui/{check_menu_item_proxy.rb → control_proxy/message_box.rb} +11 -10
  68. data/lib/glimmer/libui/control_proxy/multiline_entry_proxy/non_wrapping_multiline_entry_proxy.rb +34 -0
  69. data/lib/glimmer/libui/{image_column_proxy.rb → control_proxy/multiline_entry_proxy.rb} +10 -11
  70. data/lib/glimmer/libui/control_proxy/path_proxy.rb +169 -0
  71. data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +45 -0
  72. data/lib/glimmer/libui/{button_column_proxy.rb → control_proxy/tab_item_proxy.rb} +37 -40
  73. data/lib/glimmer/libui/control_proxy/table_proxy.rb +182 -0
  74. data/lib/glimmer/libui/control_proxy/transformable.rb +74 -0
  75. data/lib/glimmer/libui/control_proxy/window_proxy.rb +128 -0
  76. data/lib/glimmer/libui/control_proxy.rb +41 -22
  77. data/lib/glimmer/libui/{enableable_column.rb → parent.rb} +7 -15
  78. data/lib/glimmer/libui/shape/arc.rb +43 -0
  79. data/lib/glimmer/libui/{date_picker_proxy.rb → shape/bezier.rb} +8 -9
  80. data/lib/glimmer/libui/{quit_menu_item_proxy.rb → shape/figure.rb} +24 -32
  81. data/lib/glimmer/libui/{non_wrapping_multiline_entry_proxy.rb → shape/line.rb} +11 -5
  82. data/lib/glimmer/libui/{time_picker_proxy.rb → shape/rectangle.rb} +8 -9
  83. data/lib/glimmer/libui/{about_menu_item_proxy.rb → shape/square.rb} +9 -8
  84. data/lib/glimmer/libui/shape.rb +145 -0
  85. data/lib/glimmer/libui.rb +92 -0
  86. data/lib/glimmer-dsl-libui.rb +2 -0
  87. metadata +82 -48
  88. data/lib/glimmer/libui/area_proxy.rb +0 -105
  89. data/lib/glimmer/libui/checkbox_text_column_proxy.rb +0 -76
  90. data/lib/glimmer/libui/color_button_proxy.rb +0 -64
  91. data/lib/glimmer/libui/column.rb +0 -51
  92. data/lib/glimmer/libui/date_time_picker_proxy.rb +0 -68
  93. data/lib/glimmer/libui/font_button_proxy.rb +0 -68
  94. data/lib/glimmer/libui/image_text_column_proxy.rb +0 -44
  95. data/lib/glimmer/libui/label_proxy.rb +0 -41
  96. data/lib/glimmer/libui/menu_proxy.rb +0 -41
  97. data/lib/glimmer/libui/path_proxy.rb +0 -167
  98. data/lib/glimmer/libui/rectangle_proxy.rb +0 -100
  99. data/lib/glimmer/libui/separator_menu_item_proxy.rb +0 -37
  100. data/lib/glimmer/libui/tab_item_proxy.rb +0 -67
  101. data/lib/glimmer/libui/table_proxy.rb +0 -180
  102. data/lib/glimmer/libui/text_column_proxy.rb +0 -42
  103. data/lib/glimmer/libui/window_proxy.rb +0 -119
@@ -26,10 +26,10 @@ module Glimmer
26
26
  # Follows the Proxy Design Pattern
27
27
  class ControlProxy
28
28
  class << self
29
- def control_exists?(keyword)
29
+ def exists?(keyword)
30
30
  ::LibUI.respond_to?("new_#{keyword}") ||
31
31
  ::LibUI.respond_to?(keyword) ||
32
- Glimmer::LibUI.constants.include?("#{keyword.camelcase(:upper)}Proxy".to_sym)
32
+ descendant_keyword_constant_map.keys.include?(keyword)
33
33
  end
34
34
 
35
35
  def create(keyword, parent, args, &block)
@@ -37,12 +37,8 @@ module Glimmer
37
37
  end
38
38
 
39
39
  def widget_proxy_class(keyword)
40
- begin
41
- class_name = "#{keyword.camelcase(:upper)}Proxy".to_sym
42
- Glimmer::LibUI.const_get(class_name)
43
- rescue
44
- Glimmer::LibUI::ControlProxy
45
- end
40
+ class_name = constant_symbol(keyword)
41
+ descendant_keyword_constant_map[keyword] || ControlProxy
46
42
  end
47
43
 
48
44
  # autosave all controls in this array to avoid garbage collection
@@ -52,15 +48,7 @@ module Glimmer
52
48
  end
53
49
 
54
50
  def main_window_proxy
55
- control_proxies.find {|c| c.is_a?(Glimmer::LibUI::WindowProxy)}
56
- end
57
-
58
- def integer_to_boolean(int)
59
- int.nil? ? nil : int == 1
60
- end
61
-
62
- def boolean_to_integer(bool)
63
- bool.nil? ? nil : (bool ? 1 : 0)
51
+ control_proxies.find {|c| c.is_a?(WindowProxy)}
64
52
  end
65
53
 
66
54
  def menu_proxies
@@ -74,6 +62,35 @@ module Glimmer
74
62
  def new_control(keyword, args)
75
63
  ::LibUI.send("new_#{keyword}", *args)
76
64
  end
65
+
66
+ def constant_symbol(keyword)
67
+ "#{keyword.camelcase(:upper)}Proxy".to_sym
68
+ end
69
+
70
+ def keyword(constant_symbol)
71
+ constant_symbol.to_s.underscore.sub(/_proxy$/, '')
72
+ end
73
+
74
+ def descendant_keyword_constant_map
75
+ @descendant_keyword_constant_map ||= map_descendant_keyword_constants_for(self)
76
+ end
77
+
78
+ def reset_descendant_keyword_constant_map
79
+ @descendant_keyword_constant_map = nil
80
+ descendant_keyword_constant_map
81
+ end
82
+
83
+ def map_descendant_keyword_constants_for(klass, accumulator: {})
84
+ klass.constants.map do |constant_symbol|
85
+ [constant_symbol, klass.const_get(constant_symbol)]
86
+ end.select do |constant_symbol, constant|
87
+ constant.is_a?(Module) && !accumulator.values.include?(constant)
88
+ end.each do |constant_symbol, constant|
89
+ accumulator[keyword(constant_symbol)] = constant
90
+ map_descendant_keyword_constants_for(constant, accumulator: accumulator)
91
+ end
92
+ accumulator
93
+ end
77
94
  end
78
95
 
79
96
  BOOLEAN_PROPERTIES = %w[
@@ -92,7 +109,7 @@ module Glimmer
92
109
  ]
93
110
 
94
111
  # libui returns the contained LibUI object
95
- attr_reader :parent_proxy, :libui, :args, :keyword
112
+ attr_reader :parent_proxy, :libui, :args, :keyword, :block
96
113
 
97
114
  def initialize(keyword, parent, args, &block)
98
115
  @keyword = keyword
@@ -173,7 +190,7 @@ module Glimmer
173
190
  handle_string_property(property, handle_boolean_property(property, value))
174
191
  elsif ::LibUI.respond_to?("#{libui_api_keyword}_set_#{method_name.to_s.sub(/=$/, '')}") && !args.empty?
175
192
  property = method_name.to_s.sub(/=$/, '')
176
- args[0] = ControlProxy.boolean_to_integer(args.first) if BOOLEAN_PROPERTIES.include?(property) && (args.first.is_a?(TrueClass) || args.first.is_a?(FalseClass))
193
+ args[0] = Glimmer::LibUI.boolean_to_integer(args.first) if BOOLEAN_PROPERTIES.include?(property) && (args.first.is_a?(TrueClass) || args.first.is_a?(FalseClass))
177
194
  ::LibUI.send("#{libui_api_keyword}_set_#{property}", @libui, *args)
178
195
  elsif ::LibUI.respond_to?("#{libui_api_keyword}_#{method_name}") && !args.empty?
179
196
  ::LibUI.send("#{libui_api_keyword}_#{method_name}", @libui, *args)
@@ -183,7 +200,7 @@ module Glimmer
183
200
  handle_string_property(property, handle_boolean_property(property, value))
184
201
  elsif ::LibUI.respond_to?("control_set_#{method_name.to_s.sub(/=$/, '')}")
185
202
  property = method_name.to_s.sub(/=$/, '')
186
- args[0] = ControlProxy.boolean_to_integer(args.first) if BOOLEAN_PROPERTIES.include?(property) && (args.first.is_a?(TrueClass) || args.first.is_a?(FalseClass))
203
+ args[0] = Glimmer::LibUI.boolean_to_integer(args.first) if BOOLEAN_PROPERTIES.include?(property) && (args.first.is_a?(TrueClass) || args.first.is_a?(FalseClass))
187
204
  ::LibUI.send("control_set_#{method_name.to_s.sub(/=$/, '')}", @libui, *args)
188
205
  elsif ::LibUI.respond_to?("control_#{method_name}") && !args.empty?
189
206
  ::LibUI.send("control_#{method_name}", @libui, *args)
@@ -201,7 +218,7 @@ module Glimmer
201
218
  value = @append_property_hash[property]
202
219
  handle_string_property(property, handle_boolean_property(property, value))
203
220
  else
204
- value = ControlProxy.boolean_to_integer(value) if BOOLEAN_PROPERTIES.include?(property) && (value.is_a?(TrueClass) || value.is_a?(FalseClass))
221
+ value = Glimmer::LibUI.boolean_to_integer(value) if BOOLEAN_PROPERTIES.include?(property) && (value.is_a?(TrueClass) || value.is_a?(FalseClass))
205
222
  @append_property_hash[property] = value
206
223
  end
207
224
  end
@@ -274,7 +291,7 @@ module Glimmer
274
291
  end
275
292
 
276
293
  def handle_boolean_property(property, value)
277
- BOOLEAN_PROPERTIES.include?(property) ? ControlProxy.integer_to_boolean(value) : value
294
+ BOOLEAN_PROPERTIES.include?(property) ? Glimmer::LibUI.integer_to_boolean(value) : value
278
295
  end
279
296
 
280
297
  def handle_string_property(property, value)
@@ -283,3 +300,5 @@ module Glimmer
283
300
  end
284
301
  end
285
302
  end
303
+
304
+ Dir[File.expand_path('./control_proxy/*.rb', __dir__)].each {|f| require f}
@@ -21,23 +21,15 @@
21
21
 
22
22
  module Glimmer
23
23
  module LibUI
24
- module EnableableColumn
25
- def enabled(value = nil)
26
- if value.nil?
27
- @enabled = true if @enabled.nil?
28
- @enabled
29
- else
30
- @enabled = !!value
31
- end
24
+ # Parent controls and shapes who have children and add child post_initialize_child
25
+ module Parent
26
+ # Subclasses can override and must call super (passing add_child: false to cancel adding child to children)
27
+ def post_initialize_child(child, add_child: true)
28
+ children << child if add_child
32
29
  end
33
- alias enabled= enabled
34
- alias set_enabled enabled
35
- alias enabled? enabled
36
-
37
- private
38
30
 
39
- def enabled_value
40
- enabled? ? -2 : -1
31
+ def children
32
+ @children ||= []
41
33
  end
42
34
  end
43
35
  end
@@ -0,0 +1,43 @@
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/libui/shape'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ class Shape
27
+ class Arc < Shape
28
+ parameters :x_center, :y_center, :radius, :start_angle, :sweep, :is_negative
29
+ parameter_defaults 0, 0, 0, 0, 360, false
30
+
31
+ def draw(area_draw_params)
32
+ @args[5] ||= Glimmer::LibUI.boolean_to_integer(@args[5], allow_nil: false)
33
+ if parent.is_a?(Figure) && parent.x.nil? && parent.y.nil?
34
+ ::LibUI.draw_path_new_figure_with_arc(path_proxy.libui, *@args)
35
+ else
36
+ ::LibUI.draw_path_arc_to(path_proxy.libui, *@args)
37
+ end
38
+ super
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -19,18 +19,17 @@
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/libui/date_time_picker_proxy'
22
+ require 'glimmer/libui/shape'
23
23
 
24
24
  module Glimmer
25
25
  module LibUI
26
- # Proxy for LibUI date picker objects
27
- #
28
- # Follows the Proxy Design Pattern
29
- class DatePickerProxy < DateTimePickerProxy
30
- def time(value = nil)
31
- if value.nil?
32
- super.slice(:mday, :mon, :year, :wday, :yday)
33
- else
26
+ class Shape
27
+ class Bezier < Shape
28
+ parameters :c1_x, :c1_y, :c2_x, :c2_y, :end_x, :end_y
29
+ parameter_defaults 0, 0, 0, 0, 0, 0
30
+
31
+ def draw(area_draw_params)
32
+ ::LibUI.draw_path_bezier_to(path_proxy.libui, *@args)
34
33
  super
35
34
  end
36
35
  end
@@ -19,43 +19,35 @@
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/libui/menu_item_proxy'
22
+ require 'glimmer/libui/shape'
23
23
 
24
24
  module Glimmer
25
25
  module LibUI
26
- # Proxy for LibUI quit menu item object
27
- #
28
- # Follows the Proxy Design Pattern
29
- class QuitMenuItemProxy < MenuItemProxy
30
- def can_handle_listener?(listener_name)
31
- listener_name == 'on_clicked' || super
32
- end
33
-
34
- def handle_listener(listener_name, &listener)
35
- if listener_name == 'on_clicked'
36
- @default_behavior_listener = Proc.new do
37
- return_value = listener.call(self)
38
- if return_value.is_a?(Numeric)
39
- return_value
40
- else
41
- destroy
42
- ::LibUI.quit
43
- 0
44
- end
45
- end
46
- ::LibUI.on_should_quit(&@default_behavior_listener)
47
- end
48
- end
49
-
50
- private
26
+ class Shape
27
+ # Represents a figure consisting of shapes (nested under path)
28
+ # Can optionally have `closed true` property (connecting last point to first point automatically)
29
+ class Figure < Shape
30
+ parameters :x, :y
31
+ parameter_defaults nil, nil
51
32
 
52
- def build_control
53
- @libui = @parent_proxy.append_quit_item(*@args)
54
- handle_listener('on_clicked') do
55
- ControlProxy.main_window_proxy&.destroy
56
- ::LibUI.quit
57
- 0
33
+ def draw(area_draw_params)
34
+ ::LibUI.draw_path_new_figure(path_proxy.libui, *@args) unless @args.compact.empty? # TODO if args empty then wait till there is an arc child and it starts the figure
35
+ children.dup.each {|child| child.draw(area_draw_params)}
36
+ ::LibUI.draw_path_close_figure(path_proxy.libui) if closed?
37
+ super
38
+ end
39
+
40
+ def closed(value = nil)
41
+ if value.nil?
42
+ @closed
43
+ else
44
+ @closed = value
45
+ area_proxy&.queue_redraw_all
46
+ end
58
47
  end
48
+ alias closed= closed
49
+ alias set_closed closed
50
+ alias closed? closed
59
51
  end
60
52
  end
61
53
  end
@@ -19,14 +19,20 @@
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/libui/multiline_entry_proxy'
22
+ require 'glimmer/libui/shape'
23
23
 
24
24
  module Glimmer
25
25
  module LibUI
26
- # Proxy for LibUI non wrapping multiline entry objects
27
- #
28
- # Follows the Proxy Design Pattern
29
- class NonWrappingMultilineEntryProxy < MultilineEntryProxy
26
+ class Shape
27
+ class Line < Shape
28
+ parameters :x, :y
29
+ parameter_defaults 0, 0
30
+
31
+ def draw(area_draw_params)
32
+ ::LibUI.draw_path_line_to(path_proxy.libui, *@args)
33
+ super
34
+ end
35
+ end
30
36
  end
31
37
  end
32
38
  end
@@ -19,18 +19,17 @@
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/libui/date_time_picker_proxy'
22
+ require 'glimmer/libui/shape'
23
23
 
24
24
  module Glimmer
25
25
  module LibUI
26
- # Proxy for LibUI time picker objects
27
- #
28
- # Follows the Proxy Design Pattern
29
- class TimePickerProxy < DateTimePickerProxy
30
- def time(value = nil)
31
- if value.nil?
32
- super.slice(:sec, :min, :hour)
33
- else
26
+ class Shape
27
+ class Rectangle < Shape
28
+ parameters :x, :y, :width, :height
29
+ parameter_defaults 0, 0, 0, 0
30
+
31
+ def draw(area_draw_params)
32
+ ::LibUI.draw_path_add_rectangle(path_proxy.libui, *@args)
34
33
  super
35
34
  end
36
35
  end
@@ -19,18 +19,19 @@
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/libui/menu_item_proxy'
22
+ require 'glimmer/libui/shape'
23
23
 
24
24
  module Glimmer
25
25
  module LibUI
26
- # Proxy for LibUI about menu item object
27
- #
28
- # Follows the Proxy Design Pattern
29
- class AboutMenuItemProxy < MenuItemProxy
30
- private
26
+ class Shape
27
+ class Square < Shape
28
+ parameters :x, :y, :length
29
+ parameter_defaults 0, 0, 0
31
30
 
32
- def build_control
33
- @libui = @parent_proxy.append_about_item(*@args)
31
+ def draw(area_draw_params)
32
+ ::LibUI.draw_path_add_rectangle(path_proxy.libui, *@args, length)
33
+ super
34
+ end
34
35
  end
35
36
  end
36
37
  end
@@ -0,0 +1,145 @@
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/libui/parent'
23
+ require 'glimmer/libui/control_proxy/area_proxy'
24
+ require 'glimmer/libui/control_proxy/path_proxy'
25
+
26
+ module Glimmer
27
+ module LibUI
28
+ # Represents LibUI lightweight shape objects nested under path (e.g. line, rectangle, arc, bezier)
29
+ class Shape
30
+ class << self
31
+ def exists?(keyword)
32
+ Shape.constants.include?(constant_symbol(keyword)) and
33
+ shape_class(keyword).respond_to?(:ancestors) and
34
+ shape_class(keyword).ancestors.include?(Shape)
35
+ end
36
+
37
+ def create(keyword, parent, args, &block)
38
+ shape_class(keyword).new(keyword, parent, args, &block)
39
+ end
40
+
41
+ def shape_class(keyword)
42
+ Shape.const_get(constant_symbol(keyword))
43
+ end
44
+
45
+ def parameters(*params)
46
+ if params.empty?
47
+ @parameters
48
+ else
49
+ @parameters = params
50
+ end
51
+ end
52
+
53
+ def parameter_defaults(*defaults)
54
+ if defaults.empty?
55
+ @parameter_defaults
56
+ else
57
+ @parameter_defaults = defaults
58
+ end
59
+ end
60
+
61
+ def constant_symbol(keyword)
62
+ "#{keyword.camelcase(:upper)}".to_sym
63
+ end
64
+ end
65
+
66
+ include Parent
67
+
68
+ attr_reader :parent, :args, :keyword, :block
69
+
70
+ def initialize(keyword, parent, args, &block)
71
+ @keyword = keyword
72
+ @parent = parent
73
+ @args = args
74
+ @block = block
75
+ set_parameter_defaults
76
+ post_add_content if @block.nil?
77
+ end
78
+
79
+ # Subclasses may override to perform post add_content work (normally must call super)
80
+ def post_add_content
81
+ @parent&.post_initialize_child(self)
82
+ end
83
+
84
+ # Subclasses must override to perform draw work and call super afterwards to ensure calling destroy when semi-declarative in an on_draw method
85
+ def draw(area_draw_params)
86
+ destroy if area_proxy.nil?
87
+ end
88
+
89
+ def redraw
90
+ area_proxy&.queue_redraw_all
91
+ end
92
+
93
+ def destroy
94
+ @parent.children.delete(self)
95
+ end
96
+
97
+ def area_proxy
98
+ find_parent_in_ancestors { |parent| parent.nil? || parent.is_a?(ControlProxy::AreaProxy) }
99
+ end
100
+
101
+ def path_proxy
102
+ find_parent_in_ancestors { |parent| parent.nil? || parent.is_a?(ControlProxy::PathProxy) }
103
+ end
104
+
105
+ def respond_to?(method_name, *args, &block)
106
+ self.class.parameters.include?(method_name.to_s.sub(/=$/, '').sub(/^set_/, '').to_sym) or
107
+ super(method_name, true)
108
+ end
109
+
110
+ def method_missing(method_name, *args, &block)
111
+ method_name_parameter = method_name.to_s.sub(/=$/, '').sub(/^set_/, '').to_sym
112
+ if self.class.parameters.include?(method_name_parameter)
113
+ method_name = method_name.to_s
114
+ parameter_index = self.class.parameters.index(method_name_parameter)
115
+ if method_name.start_with?('set_') || method_name.end_with?('=') || !args.empty?
116
+ @args[parameter_index] = args.first
117
+ area_proxy&.queue_redraw_all
118
+ else
119
+ @args[parameter_index]
120
+ end
121
+ else
122
+ super
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ def set_parameter_defaults
129
+ self.class.parameter_defaults.each_with_index do |default, i|
130
+ @args[i] ||= default
131
+ end
132
+ end
133
+
134
+ def find_parent_in_ancestors(&condition)
135
+ found = self
136
+ until condition.call(found)
137
+ found = found.respond_to?(:parent_proxy) ? found.parent_proxy : found.parent
138
+ end
139
+ found
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ Dir[File.expand_path("./#{File.basename(__FILE__, '.rb')}/*.rb", __dir__)].each {|f| require f}
@@ -0,0 +1,92 @@
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
+ module Glimmer
23
+ module LibUI
24
+ class << self
25
+ def integer_to_boolean(int, allow_nil: true)
26
+ int.nil? ? (allow_nil ? nil : false) : int == 1
27
+ end
28
+
29
+ def boolean_to_integer(bool, allow_nil: true)
30
+ bool.nil? ? (allow_nil ? nil : 0) : (bool ? 1 : 0)
31
+ end
32
+
33
+ def interpret_color(value)
34
+ if value.is_a?(Array) && value.last.is_a?(Hash)
35
+ options = value.last
36
+ value = value[0...-1]
37
+ end
38
+ value = value.first if value.is_a?(Array) && value.size == 1
39
+ value = value.to_s if value.is_a?(Symbol)
40
+ value = value[:color] if value.is_a?(Hash) && value[:color]
41
+ result = if value.is_a?(Array)
42
+ old_value = value
43
+ value = {
44
+ r: value[0],
45
+ g: value[1],
46
+ b: value[2],
47
+ }
48
+ value[:a] = value[3] unless value[3].nil?
49
+ value
50
+ elsif value.is_a?(Hash)
51
+ old_value = value
52
+ value = old_value.dup
53
+ value[:r] = value.delete(:red) if value[:red]
54
+ value[:g] = value.delete(:green) if value[:green]
55
+ value[:b] = value.delete(:blue) if value[:blue]
56
+ value[:a] = value.delete(:alpha) if value[:alpha]
57
+ value
58
+ elsif value.is_a?(String) && !value.start_with?('0x') && !value.downcase.match(/^((([1-9a-f]){6})|(([1-9a-f]){3}))$/)
59
+ color = Color::RGB.extract_colors(value).first
60
+ color.nil? ? {} : {
61
+ r: color.red,
62
+ g: color.green,
63
+ b: color.blue,
64
+ }
65
+ else
66
+ hex_to_rgb(value)
67
+ end
68
+ result.merge!(options) if options
69
+ result
70
+ end
71
+
72
+ def hex_to_rgb(value)
73
+ if value.is_a?(String)
74
+ if !value.start_with?('0x')
75
+ value = value.chars.map {|char| [char, char]}.flatten.join if value.length == 3
76
+ value = "0x#{value}"
77
+ end
78
+ value = value.to_i(16)
79
+ end
80
+ if value.is_a?(Integer)
81
+ hex_value = value
82
+ value = {
83
+ r: ((hex_value >> 16) & 0xFF),
84
+ g: ((hex_value >> 8) & 0xFF),
85
+ b: (hex_value & 0xFF),
86
+ }
87
+ end
88
+ value
89
+ end
90
+ end
91
+ end
92
+ end
@@ -26,6 +26,7 @@ require 'glimmer'
26
26
  # require 'logging'
27
27
  # require 'puts_debuggerer' if ENV['pd'].to_s.downcase == 'true'
28
28
  # require 'super_module'
29
+ require 'color'
29
30
  require 'os'
30
31
  require 'array_include_methods'
31
32
  require 'libui'
@@ -34,6 +35,7 @@ require 'libui'
34
35
  # require 'ext/glimmer/config'
35
36
  # require 'ext/glimmer'
36
37
  require 'glimmer/dsl/libui/dsl'
38
+ require 'glimmer/libui'
37
39
  Glimmer::Config.loop_max_count = -1
38
40
  Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
39
41
  method = method_symbol.to_s