glimmer-dsl-libui 0.0.3 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/README.md +758 -24
  4. data/VERSION +1 -1
  5. data/examples/control_gallery.rb +168 -0
  6. data/examples/midi_player.rb +90 -0
  7. data/glimmer-dsl-libui.gemspec +0 -0
  8. data/lib/glimmer/dsl/libui/control_expression.rb +1 -3
  9. data/lib/glimmer/dsl/libui/dsl.rb +1 -1
  10. data/lib/glimmer/dsl/libui/file_expression.rb +33 -0
  11. data/lib/glimmer/dsl/libui/open_file_expression.rb +33 -0
  12. data/lib/glimmer/dsl/libui/save_file_expression.rb +33 -0
  13. data/lib/glimmer/dsl/libui/tab_item_expression.rb +35 -0
  14. data/lib/glimmer/libui/about_menu_item_proxy.rb +37 -0
  15. data/lib/glimmer/libui/box.rb +12 -0
  16. data/lib/glimmer/libui/check_menu_item_proxy.rb +37 -0
  17. data/lib/glimmer/libui/combobox_proxy.rb +43 -0
  18. data/lib/glimmer/libui/control_proxy.rb +87 -22
  19. data/lib/glimmer/libui/editable_combobox_proxy.rb +43 -0
  20. data/lib/glimmer/libui/group_proxy.rb +43 -0
  21. data/lib/glimmer/libui/horizontal_box_proxy.rb +1 -1
  22. data/lib/glimmer/libui/menu_item_proxy.rb +41 -0
  23. data/lib/glimmer/libui/multiline_entry_proxy.rb +35 -0
  24. data/lib/glimmer/libui/non_wrapping_multiline_entry_proxy.rb +32 -0
  25. data/lib/glimmer/libui/preferences_menu_item_proxy.rb +37 -0
  26. data/lib/glimmer/libui/quit_menu_item_proxy.rb +62 -0
  27. data/lib/glimmer/libui/radio_buttons_proxy.rb +43 -0
  28. data/lib/glimmer/libui/separator_menu_item_proxy.rb +37 -0
  29. data/lib/glimmer/libui/tab_item_proxy.rb +66 -0
  30. data/lib/glimmer/libui/vertical_box_proxy.rb +1 -1
  31. data/lib/glimmer/libui/window_proxy.rb +3 -3
  32. data/lib/glimmer-dsl-libui.rb +2 -0
  33. metadata +24 -5
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.7
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ include Glimmer
6
+
7
+ menu('File') {
8
+ menu_item('Open') {
9
+ on_clicked do
10
+ file = open_file(MAIN_WINDOW)
11
+ puts file unless file.nil?
12
+ end
13
+ }
14
+
15
+ menu_item('Save') {
16
+ on_clicked do
17
+ file = save_file(MAIN_WINDOW)
18
+ puts file unless file.nil?
19
+ end
20
+ }
21
+
22
+ quit_menu_item {
23
+ on_clicked do
24
+ puts 'Bye Bye'
25
+ end
26
+ }
27
+
28
+ preferences_menu_item # Can optionally contain an on_clicked listener
29
+ }
30
+
31
+ menu('Edit') {
32
+ check_menu_item('Checkable Item_')
33
+ separator_menu_item
34
+ menu_item('Disabled Item_') {
35
+ enabled 0
36
+ }
37
+ }
38
+
39
+ menu('Help') {
40
+ menu_item('Help')
41
+
42
+ about_menu_item # Can optionally contain an on_clicked listener
43
+ }
44
+
45
+ MAIN_WINDOW = window('Control Gallery', 600, 500, 1) {
46
+ margined 1
47
+
48
+ on_closing do
49
+ puts 'Bye Bye'
50
+ end
51
+
52
+ vertical_box {
53
+ horizontal_box {
54
+ group('Basic Controls') {
55
+ vertical_box {
56
+ button('Button') {
57
+ stretchy 0
58
+
59
+ on_clicked do
60
+ msg_box(MAIN_WINDOW, 'Information', 'You clicked the button')
61
+ end
62
+ }
63
+
64
+ checkbox('Checkbox') {
65
+ stretchy 0
66
+
67
+ on_toggled do |c|
68
+ checked = c.checked == 1
69
+ MAIN_WINDOW.title = "Checkbox is #{checked}"
70
+ c.text = "I am the checkbox (#{checked})"
71
+ end
72
+ }
73
+
74
+ label('Label') { stretchy 0 }
75
+
76
+ horizontal_separator { stretchy 0 }
77
+
78
+ date_picker { stretchy 0 }
79
+
80
+ time_picker { stretchy 0 }
81
+
82
+ date_time_picker { stretchy 0 }
83
+
84
+ font_button { stretchy 0 }
85
+
86
+ color_button { stretchy 0 }
87
+ }
88
+ }
89
+
90
+ vertical_box {
91
+ group('Numbers') {
92
+ stretchy 0
93
+
94
+ vertical_box {
95
+ spinbox(0, 100) {
96
+ stretchy 0
97
+ value 42
98
+
99
+ on_changed do |s|
100
+ puts "New Spinbox value: #{s.value}"
101
+ end
102
+ }
103
+
104
+ slider(0, 100) {
105
+ stretchy 0
106
+
107
+ on_changed do |s|
108
+ v = s.value
109
+ puts "New Slider value: #{v}"
110
+ @progress_bar.value = v
111
+ end
112
+ }
113
+
114
+ @progress_bar = progress_bar { stretchy 0 }
115
+ }
116
+ }
117
+
118
+ group('Lists') {
119
+ stretchy 0
120
+
121
+ vertical_box {
122
+ combobox {
123
+ stretchy 0
124
+ items 'combobox Item 1', 'combobox Item 2', 'combobox Item 3' # also accepts a single array argument
125
+
126
+ on_selected do |c|
127
+ puts "New combobox selection: #{c.selected}"
128
+ end
129
+ }
130
+
131
+ editable_combobox {
132
+ stretchy 0
133
+ items 'Editable Item 1', 'Editable Item 2', 'Editable Item 3' # also accepts a single array argument
134
+ }
135
+
136
+ radio_buttons {
137
+ items 'Radio Button 1', 'Radio Button 2', 'Radio Button 3' # also accepts a single array argument
138
+ }
139
+ }
140
+ }
141
+
142
+ tab {
143
+ tab_item('Page 1') {
144
+ horizontal_box {
145
+ entry {
146
+ text 'Please enter your feelings'
147
+
148
+ on_changed do |e|
149
+ puts "Current textbox data: '#{e.text}'"
150
+ end
151
+ }
152
+ }
153
+ }
154
+
155
+ tab_item('Page 2') {
156
+ horizontal_box
157
+ }
158
+
159
+ tab_item('Page 3') {
160
+ horizontal_box
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ MAIN_WINDOW.show
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ class TinyMidiPlayer
6
+ include Glimmer
7
+
8
+ VERSION = '0.0.1'
9
+
10
+ def initialize
11
+ @pid = nil
12
+ @music_directory = File.expand_path(ARGV[0] || '~/Music/')
13
+ @midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
14
+ .sort_by { |path| File.basename(path) }
15
+ at_exit { stop_midi }
16
+ create_gui
17
+ end
18
+
19
+ def stop_midi
20
+ if @pid
21
+ if @th.alive?
22
+ Process.kill(:SIGKILL, @pid)
23
+ @pid = nil
24
+ else
25
+ @pid = nil
26
+ end
27
+ end
28
+ end
29
+
30
+ def play_midi
31
+ stop_midi
32
+ if @pid.nil? && @selected_file
33
+ begin
34
+ @pid = spawn "timidity #{@selected_file}"
35
+ @th = Process.detach @pid
36
+ rescue Errno::ENOENT
37
+ warn 'Timidty++ not found. Please install Timidity++.'
38
+ warn 'https://sourceforge.net/projects/timidity/'
39
+ end
40
+ end
41
+ end
42
+
43
+ def show_version(main_window)
44
+ msg_box(main_window,
45
+ 'Tiny Midi Player',
46
+ "Written in Ruby\n" \
47
+ "https://github.com/kojix2/libui\n" \
48
+ "Version #{VERSION}")
49
+ end
50
+
51
+ def create_gui
52
+ menu('Help') { |m|
53
+ menu_item('Version') {
54
+ on_clicked do
55
+ show_version(@main_window)
56
+ end
57
+ }
58
+ }
59
+ @main_window = window('Tiny Midi Player', 200, 50, 1) {
60
+ horizontal_box {
61
+ vertical_box {
62
+ stretchy 0
63
+
64
+ button('▶') {
65
+ on_clicked do
66
+ play_midi
67
+ end
68
+ }
69
+ button('■') {
70
+ on_clicked do
71
+ stop_midi
72
+ end
73
+ }
74
+ }
75
+
76
+ combobox { |c|
77
+ items @midi_files.map { |path| File.basename(path) }
78
+
79
+ on_selected do
80
+ @selected_file = @midi_files[c.selected]
81
+ play_midi if @th&.alive?
82
+ end
83
+ }
84
+ }
85
+ }
86
+ @main_window.show
87
+ end
88
+ end
89
+
90
+ TinyMidiPlayer.new
Binary file
@@ -48,6 +48,4 @@ end
48
48
 
49
49
  # TODO Consider moving all controls underneath Control namespace
50
50
  require 'glimmer/libui/control_proxy'
51
- require 'glimmer/libui/window_proxy'
52
- require 'glimmer/libui/horizontal_box_proxy'
53
- require 'glimmer/libui/vertical_box_proxy'
51
+ Dir[File.expand_path('../../libui/*.rb', __dir__)].each {|f| require f}
@@ -20,7 +20,7 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  require 'glimmer/dsl/engine'
23
- Dir[File.expand_path('../*_expression.rb', __FILE__)].each {|f| require f}
23
+ Dir[File.expand_path('*_expression.rb', __dir__)].each {|f| require f}
24
24
 
25
25
  # Glimmer DSL expression configuration module
26
26
  #
@@ -0,0 +1,33 @@
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 DSL
24
+ module Libui
25
+ module FileExpression
26
+ def interpret(parent, keyword, *args, &block)
27
+ file_pointer = ::LibUI.send(self.class.name.underscore.split('::').last.sub(/_expression$/, ''), args.first.libui)
28
+ file_pointer.to_s unless file_pointer.null?
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
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/libui/file_expression'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Libui
28
+ class OpenFileExpression < StaticExpression
29
+ include FileExpression
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
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/libui/file_expression'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Libui
28
+ class SaveFileExpression < StaticExpression
29
+ include FileExpression
30
+ end
31
+ end
32
+ end
33
+ end
@@ -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/libui/tab_item_proxy'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Libui
28
+ class TabItemExpression < StaticExpression
29
+ def interpret(parent, keyword, *args, &block)
30
+ Glimmer::LibUI::TabItemProxy.create(keyword, parent, args, &block)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
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/menu_item_proxy'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ # Proxy for LibUI about menu item object
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class AboutMenuItemProxy < MenuItemProxy
30
+ private
31
+
32
+ def build_control
33
+ @libui = @parent_proxy.append_about_item(*@args)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -28,6 +28,18 @@ module Glimmer
28
28
  child.stretchy = 1 if child.stretchy.nil?
29
29
  ::LibUI.box_append(@libui, child.libui, child.stretchy)
30
30
  end
31
+
32
+ def libui_api_keyword
33
+ 'box'
34
+ end
35
+
36
+ private
37
+
38
+ def build_control
39
+ super.tap do
40
+ self.padded = 1
41
+ end
42
+ end
31
43
  end
32
44
  end
33
45
  end
@@ -0,0 +1,37 @@
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/menu_item_proxy'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ # Proxy for LibUI check menu item object
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class CheckMenuItemProxy < MenuItemProxy
30
+ private
31
+
32
+ def build_control
33
+ @libui = @parent_proxy.append_check_item(*@args)
34
+ end
35
+ end
36
+ end
37
+ 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/control_proxy'
23
+
24
+ module Glimmer
25
+ module LibUI
26
+ # Proxy for LibUI combobox objects
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class ComboboxProxy < ControlProxy
30
+ def items(*values)
31
+ values = values.first if values.first.is_a?(Array)
32
+ if values.empty?
33
+ @values
34
+ else
35
+ @values = values
36
+ @values.each { |value| append value }
37
+ end
38
+ end
39
+ alias set_items items
40
+ alias items= items
41
+ end
42
+ end
43
+ end