glimmer-dsl-libui 0.2.0 → 0.2.4

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/README.md +975 -23
  4. data/VERSION +1 -1
  5. data/examples/area_gallery.rb +7 -1
  6. data/examples/area_gallery2.rb +14 -4
  7. data/examples/area_gallery3.rb +8 -2
  8. data/examples/area_gallery4.rb +15 -5
  9. data/examples/basic_draw_text.rb +65 -0
  10. data/examples/basic_draw_text2.rb +68 -0
  11. data/examples/color_the_circles.rb +220 -0
  12. data/examples/custom_draw_text.rb +84 -0
  13. data/examples/custom_draw_text2.rb +95 -0
  14. data/examples/midi_player.rb +2 -2
  15. data/examples/timer.rb +135 -0
  16. data/glimmer-dsl-libui.gemspec +0 -0
  17. data/lib/glimmer/dsl/libui/control_expression.rb +0 -1
  18. data/lib/glimmer/dsl/libui/property_expression.rb +3 -1
  19. data/lib/glimmer/dsl/libui/string_expression.rb +48 -0
  20. data/lib/glimmer/libui/attributed_string.rb +135 -0
  21. data/lib/glimmer/libui/control_proxy/area_proxy.rb +14 -3
  22. data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +0 -1
  23. data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +18 -0
  24. data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +3 -3
  25. data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +69 -0
  26. data/lib/glimmer/libui/control_proxy/menu_proxy.rb +3 -0
  27. data/lib/glimmer/libui/control_proxy/path_proxy.rb +0 -2
  28. data/lib/glimmer/libui/control_proxy/text_proxy.rb +172 -0
  29. data/lib/glimmer/libui/control_proxy/window_proxy.rb +0 -6
  30. data/lib/glimmer/libui/control_proxy.rb +7 -1
  31. data/lib/glimmer/libui/shape/arc.rb +6 -3
  32. data/lib/glimmer/libui/shape/circle.rb +50 -0
  33. data/lib/glimmer/libui/shape/rectangle.rb +4 -0
  34. data/lib/glimmer/libui/shape/square.rb +4 -0
  35. data/lib/glimmer/libui.rb +73 -6
  36. metadata +13 -2
data/examples/timer.rb ADDED
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ class Timer
6
+ include Glimmer
7
+
8
+ SECOND_MAX = 59
9
+ MINUTE_MAX = 59
10
+ HOUR_MAX = 23
11
+
12
+ def initialize
13
+ @pid = nil
14
+ @alarm_file = File.expand_path('../sounds/AlanWalker-Faded.mid', __dir__)
15
+ at_exit { stop_alarm }
16
+ setup_timer
17
+ create_gui
18
+ end
19
+
20
+ def stop_alarm
21
+ if @pid
22
+ if @th.alive?
23
+ Process.kill(:SIGKILL, @pid)
24
+ @pid = nil
25
+ else
26
+ @pid = nil
27
+ end
28
+ end
29
+ end
30
+
31
+ def play_alarm
32
+ stop_alarm
33
+ if @pid.nil?
34
+ begin
35
+ @pid = spawn "timidity -G 0.0-10.0 #{@alarm_file}"
36
+ @th = Process.detach @pid
37
+ rescue Errno::ENOENT
38
+ warn 'Timidty++ not found. Please install Timidity++.'
39
+ warn 'https://sourceforge.net/projects/timidity/'
40
+ end
41
+ end
42
+ end
43
+
44
+ def setup_timer
45
+ unless @setup_timer
46
+ Glimmer::LibUI.timer(1) do
47
+ if @started
48
+ seconds = @sec_spinbox.value
49
+ minutes = @min_spinbox.value
50
+ hours = @hour_spinbox.value
51
+ if seconds > 0
52
+ @sec_spinbox.value = seconds -= 1
53
+ end
54
+ if seconds == 0
55
+ if minutes > 0
56
+ @min_spinbox.value = minutes -= 1
57
+ @sec_spinbox.value = seconds = SECOND_MAX
58
+ end
59
+ if minutes == 0
60
+ if hours > 0
61
+ @hour_spinbox.value = hours -= 1
62
+ @min_spinbox.value = minutes = MINUTE_MAX
63
+ @sec_spinbox.value = seconds = SECOND_MAX
64
+ end
65
+ if hours == 0 && minutes == 0 && seconds == 0
66
+ @start_button.enabled = true
67
+ @stop_button.enabled = false
68
+ @started = false
69
+ unless @played
70
+ play_alarm
71
+ msg_box('Alarm', 'Countdown Is Finished!')
72
+ @played = true
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ @setup_timer = true
80
+ end
81
+ end
82
+
83
+ def create_gui
84
+ window('Timer') {
85
+ margined true
86
+
87
+ group('Countdown') {
88
+ vertical_box {
89
+ horizontal_box {
90
+ @hour_spinbox = spinbox(0, HOUR_MAX) {
91
+ stretchy false
92
+ value 0
93
+ }
94
+ label(':') {
95
+ stretchy false
96
+ }
97
+ @min_spinbox = spinbox(0, MINUTE_MAX) {
98
+ stretchy false
99
+ value 0
100
+ }
101
+ label(':') {
102
+ stretchy false
103
+ }
104
+ @sec_spinbox = spinbox(0, SECOND_MAX) {
105
+ stretchy false
106
+ value 0
107
+ }
108
+ }
109
+ horizontal_box {
110
+ @start_button = button('Start') {
111
+ on_clicked do
112
+ @start_button.enabled = false
113
+ @stop_button.enabled = true
114
+ @started = true
115
+ @played = false
116
+ end
117
+ }
118
+
119
+ @stop_button = button('Stop') {
120
+ enabled false
121
+
122
+ on_clicked do
123
+ @start_button.enabled = true
124
+ @stop_button.enabled = false
125
+ @started = false
126
+ end
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }.show
132
+ end
133
+ end
134
+
135
+ Timer.new
Binary file
@@ -40,7 +40,6 @@ module Glimmer
40
40
  super
41
41
  parent.post_add_content
42
42
  end
43
-
44
43
  end
45
44
  end
46
45
  end
@@ -22,6 +22,7 @@
22
22
  require 'glimmer/dsl/expression'
23
23
  require 'glimmer/libui/control_proxy'
24
24
  require 'glimmer/libui/shape'
25
+ require 'glimmer/libui/attributed_string'
25
26
 
26
27
  module Glimmer
27
28
  module DSL
@@ -30,7 +31,8 @@ module Glimmer
30
31
  def can_interpret?(parent, keyword, *args, &block)
31
32
  (
32
33
  parent.is_a?(Glimmer::LibUI::ControlProxy) or
33
- parent.is_a?(Glimmer::LibUI::Shape)
34
+ parent.is_a?(Glimmer::LibUI::Shape) or
35
+ parent.is_a?(Glimmer::LibUI::AttributedString)
34
36
  ) and
35
37
  block.nil? and
36
38
  parent.respond_to?(keyword, *args)
@@ -0,0 +1,48 @@
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/parent_expression'
24
+ require 'glimmer/libui/control_proxy/text_proxy'
25
+ require 'glimmer/libui/attributed_string'
26
+
27
+ module Glimmer
28
+ module DSL
29
+ module Libui
30
+ class StringExpression < StaticExpression
31
+ include ParentExpression
32
+
33
+ def can_interpret?(parent, keyword, *args, &block)
34
+ super and
35
+ parent.is_a?(Glimmer::LibUI::ControlProxy::TextProxy)
36
+ end
37
+
38
+ def interpret(parent, keyword, *args, &block)
39
+ Glimmer::LibUI::AttributedString.new(keyword, parent, args, &block)
40
+ end
41
+
42
+ def add_content(parent, keyword, *args, &block)
43
+ parent.post_add_content
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,135 @@
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/control_proxy'
23
+ require 'glimmer/libui/control_proxy/area_proxy'
24
+ require 'glimmer/libui/parent'
25
+ require 'glimmer/libui/control_proxy/transformable'
26
+
27
+ module Glimmer
28
+ module LibUI
29
+ class AttributedString
30
+ attr_accessor :string
31
+ attr_reader :block, :keyword, :parent_proxy, :args
32
+
33
+ def initialize(keyword, parent_proxy, args, &block)
34
+ @keyword = keyword
35
+ @parent_proxy = parent_proxy
36
+ @args = args
37
+ @string = @args.first || ''
38
+ @block = block
39
+ post_add_content if @block.nil?
40
+ end
41
+
42
+ def font(value = nil)
43
+ if value.nil?
44
+ @font
45
+ else
46
+ @font = value
47
+ redraw
48
+ end
49
+ end
50
+ alias font= font
51
+ alias set_font font
52
+
53
+ def color(value = nil)
54
+ if value.nil?
55
+ @color
56
+ else
57
+ @color = Glimmer::LibUI.interpret_color(value)
58
+ redraw
59
+ end
60
+ end
61
+ alias color= color
62
+ alias set_color color
63
+
64
+ def background(value = nil)
65
+ if value.nil?
66
+ @background
67
+ else
68
+ @background = Glimmer::LibUI.interpret_color(value)
69
+ redraw
70
+ end
71
+ end
72
+ alias background= background
73
+ alias background background
74
+
75
+ def underline(value = nil)
76
+ if value.nil?
77
+ @underline
78
+ else
79
+ @underline = value
80
+ redraw
81
+ end
82
+ end
83
+ alias underline= underline
84
+ alias underline underline
85
+
86
+ def post_add_content
87
+ block_result = block&.call
88
+ @string = block_result if block_result.is_a?(String)
89
+ @parent_proxy&.post_initialize_child(self)
90
+ end
91
+
92
+ def draw(area_draw_params)
93
+ @start = ::LibUI.attributed_string_len(@parent_proxy.attributed_string)
94
+ ::LibUI.attributed_string_append_unattributed(@parent_proxy.attributed_string, @string)
95
+ unless color.nil?
96
+ color_attribute = ::LibUI.new_color_attribute(@color[:r].to_f / 255.0, @color[:g].to_f / 255.0, @color[:b].to_f / 255.0, @color[:a] || 1.0)
97
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, color_attribute, @start, @start + @string.size)
98
+ end
99
+ unless background.nil?
100
+ background_attribute = ::LibUI.new_background_attribute(@background[:r].to_f / 255.0, @background[:g].to_f / 255.0, @background[:b].to_f / 255.0, @background[:a] || 1.0)
101
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, background_attribute, @start, @start + @string.size)
102
+ end
103
+ unless underline.nil?
104
+ underline_attribute = ::LibUI.new_underline_attribute(Glimmer::LibUI.enum_symbol_to_value(:underline, @underline))
105
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, underline_attribute, @start, @start + @string.size)
106
+ end
107
+ unless font.nil?
108
+ family_attribute = ::LibUI.new_family_attribute(font[:family])
109
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, family_attribute, @start, @start + @string.size)
110
+ size_attribute = ::LibUI.new_size_attribute(font[:size])
111
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, size_attribute, @start, @start + @string.size)
112
+ weight_attribute = ::LibUI.new_weight_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_weight, font[:weight]))
113
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, weight_attribute, @start, @start + @string.size)
114
+ italic_attribute = ::LibUI.new_italic_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_italic, font[:italic]))
115
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, italic_attribute, @start, @start + @string.size)
116
+ stretch_attribute = ::LibUI.new_stretch_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_stretch, font[:stretch]))
117
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, stretch_attribute, @start, @start + @string.size)
118
+ end
119
+ destroy if area_proxy.nil?
120
+ end
121
+
122
+ def destroy
123
+ @parent_proxy&.children&.delete(self)
124
+ end
125
+
126
+ def redraw
127
+ area_proxy&.queue_redraw_all
128
+ end
129
+
130
+ def area_proxy
131
+ @parent_proxy.parent_proxy
132
+ end
133
+ end
134
+ end
135
+ end
@@ -60,7 +60,18 @@ module Glimmer
60
60
  end
61
61
 
62
62
  def post_add_content
63
- super
63
+ unless parent_proxy.is_a?(Box)
64
+ original_parent_proxy = @parent_proxy
65
+ @vertical_box_parent_proxy = ControlProxy.create('vertical_box', parent_proxy, []) {} # block prevents calling post add content
66
+ append_properties.each do |property|
67
+ @vertical_box_parent_proxy.append_property(property, append_property(property))
68
+ end
69
+ @vertical_box_parent_proxy.post_add_content
70
+ @parent_proxy = @vertical_box_parent_proxy
71
+ @vertical_box_parent_proxy.post_initialize_child(self)
72
+ else
73
+ super
74
+ end
64
75
  install_listeners
65
76
  end
66
77
 
@@ -72,7 +83,7 @@ module Glimmer
72
83
  def redraw
73
84
  queue_redraw_all
74
85
  end
75
-
86
+
76
87
  private
77
88
 
78
89
  def build_control
@@ -169,7 +180,7 @@ module Glimmer
169
180
  end
170
181
 
171
182
  def ext_key_to_symbol(ext_key_value)
172
- Glimmer::LibUI.enum_symbols(:ext_key)[ext_key_value - 1].to_s.to_sym if ext_key_value > 0
183
+ Glimmer::LibUI.enum_value_to_symbol(:ext_key, ext_key_value)
173
184
  end
174
185
 
175
186
  def modifiers_to_symbols(modifiers_value)
@@ -29,7 +29,6 @@ module Glimmer
29
29
  # Follows the Proxy Design Pattern
30
30
  class ColorButtonProxy < ControlProxy
31
31
  def color(value = nil)
32
- # TODO support hex color value
33
32
  if value.nil?
34
33
  @red ||= Fiddle::Pointer.malloc(8) # double
35
34
  @green ||= Fiddle::Pointer.malloc(8) # double
@@ -28,6 +28,20 @@ module Glimmer
28
28
  #
29
29
  # Follows the Proxy Design Pattern
30
30
  class ComboboxProxy < ControlProxy
31
+ def selected(value = nil)
32
+ if value.nil?
33
+ super()
34
+ else
35
+ if value.is_a?(String)
36
+ super(items.index(value).to_i)
37
+ else
38
+ super
39
+ end
40
+ end
41
+ end
42
+ alias selected= selected
43
+ alias set_selected selected
44
+
31
45
  def items(*values)
32
46
  values = values.first if values.first.is_a?(Array)
33
47
  if values.empty?
@@ -39,6 +53,10 @@ module Glimmer
39
53
  end
40
54
  alias set_items items
41
55
  alias items= items
56
+
57
+ def selected_item
58
+ items[selected]
59
+ end
42
60
  end
43
61
  end
44
62
  end
@@ -34,9 +34,9 @@ module Glimmer
34
34
  {
35
35
  family: @font_descriptor.Family.to_s,
36
36
  size: @font_descriptor.Size,
37
- weight: @font_descriptor.Weight,
38
- italic: @font_descriptor.Italic,
39
- stretch: @font_descriptor.Stretch
37
+ weight: Glimmer::LibUI.enum_value_to_symbol(:text_weight, @font_descriptor.Weight),
38
+ italic: Glimmer::LibUI.enum_value_to_symbol(:text_italic, @font_descriptor.Italic),
39
+ stretch: Glimmer::LibUI.enum_value_to_symbol(:text_stretch, @font_descriptor.Stretch),
40
40
  }
41
41
  end
42
42
 
@@ -0,0 +1,69 @@
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/control_proxy/menu_item_proxy'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ class ControlProxy
27
+ class MenuItemProxy < ControlProxy
28
+ # Proxy for LibUI radio menu item object
29
+ #
30
+ # Follows the Proxy Design Pattern
31
+ class RadioMenuItemProxy < MenuItemProxy
32
+ def checked(value = nil)
33
+ if !value.nil?
34
+ if Glimmer::LibUI.integer_to_boolean(value) != checked?
35
+ super
36
+ if Glimmer::LibUI.integer_to_boolean(value)
37
+ (@parent_proxy.children - [self]).select {|c| c.is_a?(MenuItemProxy)}.each do |menu_item|
38
+ menu_item.checked = false
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ alias checked? checked
45
+ alias set_checked checked
46
+ alias checked= checked
47
+
48
+ def handle_listener(listener_name, &listener)
49
+ if listener_name.to_s == 'on_clicked'
50
+ radio_listener = Proc.new do
51
+ self.checked = true if !checked?
52
+ listener.call(self)
53
+ end
54
+ super(listener_name, &radio_listener)
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def build_control
63
+ @libui = @parent_proxy.append_check_item(*@args)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -20,6 +20,7 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  require 'glimmer/libui/control_proxy'
23
+ require 'glimmer/libui/parent'
23
24
 
24
25
  module Glimmer
25
26
  module LibUI
@@ -28,6 +29,8 @@ module Glimmer
28
29
  #
29
30
  # Follows the Proxy Design Pattern
30
31
  class MenuProxy < ControlProxy
32
+ include Parent
33
+
31
34
  DEFAULT_TEXT = ''
32
35
 
33
36
  private
@@ -34,13 +34,11 @@ module Glimmer
34
34
  include Parent
35
35
  prepend Transformable
36
36
 
37
- # TODO support mode without parent proxy
38
37
  def initialize(keyword, parent, args, &block)
39
38
  @keyword = keyword
40
39
  @parent_proxy = parent
41
40
  @args = args
42
41
  @block = block
43
- @enabled = true
44
42
  post_add_content if @block.nil?
45
43
  end
46
44