cura 0.0.1

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 (115) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +122 -0
  4. data/LICENSE +20 -0
  5. data/README.md +159 -0
  6. data/Rakefile +42 -0
  7. data/cura.gemspec +23 -0
  8. data/examples/box_model/bin/box_model +11 -0
  9. data/examples/box_model/debug.log +0 -0
  10. data/examples/box_model/lib/box_model.rb +21 -0
  11. data/examples/box_model/lib/box_model/application.rb +24 -0
  12. data/examples/hello_world/bin/hello_world +10 -0
  13. data/examples/hello_world/lib/hello_world.rb +201 -0
  14. data/examples/mruby-examples/README.md +10 -0
  15. data/examples/mruby-examples/include/cura_examples.h +6 -0
  16. data/examples/mruby-examples/mrbgem.rake +14 -0
  17. data/examples/mruby-examples/src/gem_init.c +34 -0
  18. data/examples/mruby-examples/tools/hello_world/hello_world.c +6 -0
  19. data/examples/todo_list/app.log +9 -0
  20. data/examples/todo_list/bin/todo_list +26 -0
  21. data/examples/todo_list/data.db +0 -0
  22. data/examples/todo_list/debug.log +0 -0
  23. data/examples/todo_list/lib/todo_list.rb +28 -0
  24. data/examples/todo_list/lib/todo_list/application.rb +54 -0
  25. data/examples/todo_list/lib/todo_list/component/header.rb +27 -0
  26. data/examples/todo_list/lib/todo_list/component/list.rb +50 -0
  27. data/examples/todo_list/lib/todo_list/component/list_item.rb +28 -0
  28. data/examples/todo_list/lib/todo_list/component/list_items.rb +97 -0
  29. data/examples/todo_list/lib/todo_list/component/lists.rb +89 -0
  30. data/examples/todo_list/lib/todo_list/database.rb +50 -0
  31. data/examples/todo_list/lib/todo_list/model/list.rb +9 -0
  32. data/examples/todo_list/lib/todo_list/model/list_item.rb +9 -0
  33. data/examples/todo_list/profile.html +11354 -0
  34. data/lib/cura.rb +13 -0
  35. data/lib/cura/adapter.rb +67 -0
  36. data/lib/cura/application.rb +245 -0
  37. data/lib/cura/attributes/has_ancestry.rb +40 -0
  38. data/lib/cura/attributes/has_application.rb +31 -0
  39. data/lib/cura/attributes/has_attributes.rb +89 -0
  40. data/lib/cura/attributes/has_children.rb +113 -0
  41. data/lib/cura/attributes/has_colors.rb +66 -0
  42. data/lib/cura/attributes/has_coordinates.rb +49 -0
  43. data/lib/cura/attributes/has_dimensions.rb +63 -0
  44. data/lib/cura/attributes/has_events.rb +89 -0
  45. data/lib/cura/attributes/has_focusability.rb +37 -0
  46. data/lib/cura/attributes/has_initialize.rb +15 -0
  47. data/lib/cura/attributes/has_offsets.rb +82 -0
  48. data/lib/cura/attributes/has_orientation.rb +53 -0
  49. data/lib/cura/attributes/has_relative_coordinates.rb +39 -0
  50. data/lib/cura/attributes/has_root.rb +104 -0
  51. data/lib/cura/attributes/has_side_attributes.rb +95 -0
  52. data/lib/cura/attributes/has_windows.rb +70 -0
  53. data/lib/cura/borders.rb +16 -0
  54. data/lib/cura/color.rb +330 -0
  55. data/lib/cura/component/base.rb +180 -0
  56. data/lib/cura/component/button.rb +57 -0
  57. data/lib/cura/component/group.rb +77 -0
  58. data/lib/cura/component/label.rb +224 -0
  59. data/lib/cura/component/listbox.rb +152 -0
  60. data/lib/cura/component/pack.rb +144 -0
  61. data/lib/cura/component/scrollbar.rb +184 -0
  62. data/lib/cura/component/textbox.rb +118 -0
  63. data/lib/cura/cursor.rb +77 -0
  64. data/lib/cura/error/base.rb +10 -0
  65. data/lib/cura/error/invalid_adapter.rb +18 -0
  66. data/lib/cura/error/invalid_application.rb +18 -0
  67. data/lib/cura/error/invalid_color.rb +18 -0
  68. data/lib/cura/error/invalid_component.rb +18 -0
  69. data/lib/cura/error/invalid_middleware.rb +18 -0
  70. data/lib/cura/event.rb +38 -0
  71. data/lib/cura/event/base.rb +108 -0
  72. data/lib/cura/event/click.rb +14 -0
  73. data/lib/cura/event/dispatcher.rb +122 -0
  74. data/lib/cura/event/focus.rb +14 -0
  75. data/lib/cura/event/handler.rb +74 -0
  76. data/lib/cura/event/key_down.rb +68 -0
  77. data/lib/cura/event/middleware/aimer/base.rb +38 -0
  78. data/lib/cura/event/middleware/aimer/dispatcher_target.rb +24 -0
  79. data/lib/cura/event/middleware/aimer/mouse_focus.rb +48 -0
  80. data/lib/cura/event/middleware/aimer/target_option.rb +38 -0
  81. data/lib/cura/event/middleware/base.rb +21 -0
  82. data/lib/cura/event/middleware/dispatch.rb +20 -0
  83. data/lib/cura/event/middleware/translator/base.rb +37 -0
  84. data/lib/cura/event/middleware/translator/mouse_click.rb +44 -0
  85. data/lib/cura/event/mouse.rb +34 -0
  86. data/lib/cura/event/mouse_button.rb +103 -0
  87. data/lib/cura/event/mouse_wheel_down.rb +14 -0
  88. data/lib/cura/event/mouse_wheel_up.rb +14 -0
  89. data/lib/cura/event/resize.rb +17 -0
  90. data/lib/cura/event/selected.rb +14 -0
  91. data/lib/cura/event/unfocus.rb +14 -0
  92. data/lib/cura/focus_controller.rb +89 -0
  93. data/lib/cura/key.rb +313 -0
  94. data/lib/cura/margins.rb +16 -0
  95. data/lib/cura/offsets.rb +91 -0
  96. data/lib/cura/padding.rb +16 -0
  97. data/lib/cura/pencil.rb +29 -0
  98. data/lib/cura/version.rb +6 -0
  99. data/lib/cura/window.rb +85 -0
  100. data/spec/cura/attributes/has_ancestry_spec.rb +108 -0
  101. data/spec/cura/attributes/has_application_spec.rb +59 -0
  102. data/spec/cura/attributes/has_attributes_spec.rb +75 -0
  103. data/spec/cura/attributes/has_children_spec.rb +169 -0
  104. data/spec/cura/attributes/has_colors_spec.rb +20 -0
  105. data/spec/cura/attributes/has_coordinates_spec.rb +19 -0
  106. data/spec/cura/attributes/has_dimensions_spec.rb +19 -0
  107. data/spec/cura/attributes/has_events_spec.rb +18 -0
  108. data/spec/cura/attributes/has_focusability_spec.rb +58 -0
  109. data/spec/cura/attributes/has_offsets_spec.rb +18 -0
  110. data/spec/cura/attributes/has_orientation_spec.rb +102 -0
  111. data/spec/cura/attributes/has_relative_coordinates_spec.rb +18 -0
  112. data/spec/cura/attributes/has_side_attributes_spec.rb +19 -0
  113. data/spec/spec_helper.rb +12 -0
  114. data/spec/support/shared_examples_for_attributes.rb +122 -0
  115. metadata +211 -0
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "pathname"
4
+ $LOAD_PATH.unshift(Pathname.new(__FILE__).join("..", "..", "..", "..", "lib").expand_path.to_s)
5
+ $LOAD_PATH.unshift(Pathname.new(__FILE__).join("..", "..", "..", "..", "..", "cura-termbox", "lib").expand_path.to_s)
6
+ $LOAD_PATH.unshift(Pathname.new(__FILE__).join("..", "..", "lib").expand_path.to_s)
7
+
8
+ require "hello_world"
9
+
10
+ HelloWorld.run
@@ -0,0 +1,201 @@
1
+ if Kernel.respond_to?(:require)
2
+ require "cura"
3
+ # require 'cura-adapter-termbox'
4
+ require "cura/termbox/adapter"
5
+ # require 'cura-adapter-curses'
6
+ # require 'cura-adapter-sdl'
7
+ # require 'cura-adapter-sdl-ffi'
8
+ # require 'cura-adapter-opengl'
9
+ # require 'cura-adapter-opengl-ffi'
10
+ # require 'cura-adapter-gosu'
11
+ end
12
+
13
+ class HelloWorld < Cura::Application
14
+ #
15
+ # class << self
16
+ #
17
+ # def run
18
+ # adapter = choose_adapter
19
+ #
20
+ # super(adapter: adapter.new)
21
+ # end
22
+ #
23
+ # protected
24
+ #
25
+ # def choose_adapter
26
+ # adapters = Cura::Adapter.all
27
+ # adapter = nil
28
+ # index = -1
29
+ #
30
+ # loop do
31
+ # adapters.each_with_index do |adapter, index|
32
+ # puts "#{index}. #{adapter}"
33
+ # end
34
+ #
35
+ # puts "\nChoose adapter or type 'exit'"
36
+ # print "> "
37
+ #
38
+ # answer = gets.downcase.strip
39
+ #
40
+ # exit if answer == "exit"
41
+ #
42
+ # index = answer.to_i
43
+ #
44
+ # break if index < adapters.length && index >= 0
45
+ # end
46
+ #
47
+ # adapters[index]
48
+ # end
49
+ #
50
+ # end
51
+
52
+ on_event(:key_down) do |event|
53
+ stop if event.control? && event.name == :C # CTRL+C
54
+ end
55
+
56
+ attr_accessor :timer_start
57
+ attr_reader :input_result_label
58
+ attr_reader :form_first_name_textbox
59
+ attr_reader :form_last_name_textbox
60
+ attr_reader :form_age_textbox
61
+ attr_reader :form_zip_textbox
62
+ attr_reader :form_submit_button
63
+ attr_reader :people_listbox
64
+
65
+ def initialize(attributes={})
66
+ super
67
+
68
+ @dispatcher.wait_time = 100 # Update every 100 milliseconds instead of waiting forever for events
69
+
70
+ window = Cura::Window.new
71
+ add_window(window)
72
+
73
+ pack = Cura::Component::Pack.new(width: window.width, height: window.height, fill: true)
74
+ window.add_child(pack)
75
+
76
+ label_header = Cura::Component::Label.new(text: "Cura", bold: true, underline: true, alignment: { horizontal: :center }, margin: { top: 1 })
77
+ pack.add_child(label_header)
78
+
79
+ label_help = Cura::Component::Label.new(text: "Press CTRL-C to exit", alignment: { horizontal: :center }, margin: { bottom: 1 })
80
+ pack.add_child(label_help)
81
+
82
+ label_hello = Cura::Component::Label.new(text: "Hello, world!", alignment: { horizontal: :center })
83
+ pack.add_child(label_hello)
84
+
85
+ label_hello_kanji = Cura::Component::Label.new(text: "今日は", alignment: { horizontal: :center }, margin: { bottom: 1 })
86
+ pack.add_child(label_hello_kanji)
87
+
88
+ input_pack = Cura::Component::Pack.new(fill: true)
89
+ input_header_label = Cura::Component::Label.new(text: "Type and press Enter to echo for 5 seconds:")
90
+ input_pack.add_child(input_header_label)
91
+
92
+ input_textbox = Cura::Component::Textbox.new
93
+ input_pack.add_child(input_textbox)
94
+
95
+ #-----
96
+
97
+ @timer_start = nil
98
+ @input_result_label = Cura::Component::Label.new
99
+ input_pack.add_child(@input_result_label)
100
+
101
+ input_textbox.on_event(:key_down) do |event|
102
+ if event.name == :enter
103
+ application.timer_start = Time.now
104
+ application.input_result_label.text = input_textbox.text
105
+ clear
106
+ end
107
+ end
108
+
109
+ #-----
110
+
111
+ pack.add_child(input_pack)
112
+
113
+ form_pack = Cura::Component::Pack.new(orientation: :horizontal)
114
+
115
+ form_first_name_label = Cura::Component::Label.new(text: "First Name:", margin: { right: 1 })
116
+ form_pack.add_child(form_first_name_label)
117
+
118
+ @form_first_name_textbox = Cura::Component::Textbox.new(width: 20, margin: { right: 1 })
119
+ form_pack.add_child(@form_first_name_textbox)
120
+ @form_first_name_textbox.on_event(:key_down) { |event| application.form_submit_button.click if event.name == :enter }
121
+
122
+ form_last_name_label = Cura::Component::Label.new(text: "Last Name:", margin: { right: 1 })
123
+ form_pack.add_child(form_last_name_label)
124
+
125
+ @form_last_name_textbox = Cura::Component::Textbox.new(width: 20, margin: { right: 1 })
126
+ form_pack.add_child(@form_last_name_textbox)
127
+ @form_last_name_textbox.on_event(:key_down) { |event| application.form_submit_button.click if event.name == :enter }
128
+
129
+ form_age_label = Cura::Component::Label.new(text: "Age:", margin: { right: 1 })
130
+ form_pack.add_child(form_age_label)
131
+
132
+ @form_age_textbox = Cura::Component::Textbox.new(width: 20, margin: { right: 1 })
133
+ form_pack.add_child(@form_age_textbox)
134
+ @form_age_textbox.on_event(:key_down) { |event| application.form_submit_button.click if event.name == :enter }
135
+
136
+ form_zip_label = Cura::Component::Label.new(text: "ZIP:", margin: { right: 1 })
137
+ form_pack.add_child(form_zip_label)
138
+
139
+ @form_zip_textbox = Cura::Component::Textbox.new(width: 20)
140
+ form_pack.add_child(@form_zip_textbox)
141
+ @form_zip_textbox.on_event(:key_down) { |event| application.form_submit_button.click if event.name == :enter }
142
+
143
+ form_clear_button = Cura::Component::Button.new(text: "Clear", padding: { left: 1, right: 1 }, margin: { left: 1 })
144
+ form_pack.add_child(form_clear_button)
145
+
146
+ form_clear_button.on_event(:click) { application.clear_form }
147
+
148
+ @form_submit_button = Cura::Component::Button.new(text: "Submit", padding: { left: 1, right: 1 }, margin: { left: 1 })
149
+ form_pack.add_child(@form_submit_button)
150
+
151
+ @form_submit_button.on_event(:click) do |_event|
152
+ first = application.form_first_name_textbox.text
153
+ last = application.form_last_name_textbox.text
154
+ age = application.form_age_textbox.text
155
+ zip = application.form_zip_textbox.text
156
+
157
+ application.clear_form
158
+
159
+ label_text_segments = []
160
+ label_text_segments << "First: #{first}" unless first.empty?
161
+ label_text_segments << "Last: #{last}" unless last.empty?
162
+ label_text_segments << "Age: #{age}" unless age.empty?
163
+ label_text_segments << "ZIP: #{zip}" unless zip.empty?
164
+
165
+ label = Cura::Component::Label.new(text: label_text_segments.join(" - "))
166
+ application.people_listbox.add_child(label)
167
+ end
168
+ pack.add_child(form_pack)
169
+
170
+ people_label = Cura::Component::Label.new(text: "People:")
171
+ pack.add_child(people_label)
172
+
173
+ @people_listbox = Cura::Component::Listbox.new
174
+ @people_listbox.on_event(:key_down) { |event| delete_child(selected_child) if event.control? && event.name == :D }
175
+
176
+ pack.add_child(@people_listbox)
177
+
178
+
179
+
180
+ input_textbox.focus
181
+ end
182
+
183
+ def update
184
+ super
185
+
186
+ if !@timer_start.nil? && Time.now - @timer_start > 5
187
+ @timer_start = nil
188
+ @input_result_label.text = nil
189
+ end
190
+ end
191
+
192
+ def clear_form
193
+ @form_first_name_textbox.clear
194
+ @form_last_name_textbox.clear
195
+ @form_age_textbox.clear
196
+ @form_zip_textbox.clear
197
+
198
+ @form_first_name_textbox.focus
199
+ end
200
+
201
+ end
@@ -0,0 +1,10 @@
1
+ To run the examples, clone MRuby and add the following to the `mrbgems/default.gembox` file:
2
+
3
+ ```rb
4
+ conf.gem github: 'RyanScottLewis/cura'
5
+
6
+ conf.gem github: 'RyanScottLewis/mruby-termbox' # Dependency of mruby-cura-termbox
7
+ conf.gem github: 'RyanScottLewis/mruby-cura-termbox'
8
+
9
+ conf.gem 'path_to/cura/examples/mruby-examples'
10
+ ```
@@ -0,0 +1,6 @@
1
+ #ifndef CURA_EXAMPLES_H
2
+ #define CURA_EXAMPLES_H
3
+
4
+ int run_example_app( const char *app_const );
5
+
6
+ #endif // CURA_EXAMPLES_H
@@ -0,0 +1,14 @@
1
+ MRuby::Gem::Specification.new('cura-examples') do |spec|
2
+
3
+ spec.license = 'MIT'
4
+ spec.author = 'Ryan Scott Lewis'
5
+ spec.summary = ''
6
+
7
+ spec.rbfiles = []
8
+
9
+ # HelloWorld
10
+ spec.rbfiles << "#{dir}/../hello_world/lib/hello_world.rb"
11
+
12
+ spec.bins << "hello_world"
13
+
14
+ end
@@ -0,0 +1,34 @@
1
+ #include "mruby.h"
2
+ #include "mruby/variable.h"
3
+
4
+ int run_example_app( const char *app_const ) {
5
+ int error_code = -1;
6
+ mrb_state *mrb = mrb_open();
7
+
8
+ if ( mrb == NULL )
9
+ return error_code;
10
+
11
+ mrb_value app = mrb_const_get(
12
+ mrb,
13
+ mrb_obj_value( mrb->object_class ),
14
+ mrb_intern_cstr( mrb, app_const )
15
+ );
16
+
17
+ mrb_funcall( mrb, app, "run", 0 );
18
+
19
+ if ( mrb->exc ) {
20
+ mrb_print_error( mrb );
21
+ } else {
22
+ error_code = 0;
23
+ }
24
+
25
+ mrb_close( mrb );
26
+
27
+ return error_code;
28
+ }
29
+
30
+ void mrb_cura_examples_gem_init( mrb_state *mrb ) {
31
+ }
32
+
33
+ void mrb_cura_examples_gem_final( mrb_state *mrb ) {
34
+ }
@@ -0,0 +1,6 @@
1
+ #include "mruby.h"
2
+ #include "cura_examples.h"
3
+
4
+ int main() {
5
+ return run_example_app( "HelloWorld" );
6
+ }
@@ -0,0 +1,9 @@
1
+ #<Cura::Event::Unfocus:0x007fdeeb339e70 @target=#<TodoList::Application>>
2
+ #<Cura::Event::Focus:0x007fdeeb338f70 @target=#<Cura::Component::Textbox:0x3fef759c4588 x=0 y=0 absolute_x=1 absolute_y=2 w=14 h=1 parent=Cura::Component::Pack:0x3fef759c49e8>>
3
+ #<Cura::Event::KeyDown:0x007fdeec85f750 @control=false, @name=:tab, @target=#<Cura::Component::Textbox:0x3fef759c4588 x=0 y=0 absolute_x=1 absolute_y=2 w=14 h=1 parent=Cura::Component::Pack:0x3fef759c49e8>>
4
+ #<Cura::Event::Unfocus:0x007fdeec8569c0 @target=#<Cura::Component::Textbox:0x3fef759c4588 x=0 y=0 absolute_x=1 absolute_y=2 w=14 h=1 parent=Cura::Component::Pack:0x3fef759c49e8>>
5
+ #<Cura::Event::Focus:0x007fdeec854698 @target=#<Cura::Component::Button:0x3fef759bd8f0 x=15 y=0 absolute_x=16 absolute_y=2 w=11 h=1 parent=Cura::Component::Pack:0x3fef759c49e8>>
6
+ #<Cura::Event::KeyDown:0x007fdeea8781d0 @control=false, @name=:tab, @target=#<Cura::Component::Button:0x3fef759bd8f0 x=15 y=0 absolute_x=16 absolute_y=2 w=11 h=1 parent=Cura::Component::Pack:0x3fef759c49e8>>
7
+ #<Cura::Event::Unfocus:0x007fdeea85ae50 @target=#<Cura::Component::Button:0x3fef759bd8f0 x=15 y=0 absolute_x=16 absolute_y=2 w=11 h=1 parent=Cura::Component::Pack:0x3fef759c49e8>>
8
+ #<Cura::Event::Focus:0x007fdeea8413d8 @target=#<Cura::Component::Listbox:0x3fef759b99d0 x=0 y=3 absolute_x=1 absolute_y=5 w=30 h=2 parent=TodoList::Component::Lists:0x3fef759c53d4>>
9
+ #<Cura::Event::KeyDown:0x007fdeea98c828 @control=true, @name=:C, @target=#<Cura::Component::Listbox:0x3fef759b99d0 x=0 y=3 absolute_x=1 absolute_y=5 w=30 h=2 parent=TodoList::Component::Lists:0x3fef759c53d4>>
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "pathname"
4
+ $LOAD_PATH.unshift(Pathname.new(__FILE__).join("..", "..", "..", "..", "lib").expand_path.to_s)
5
+ $LOAD_PATH.unshift(Pathname.new(__FILE__).join("..", "..", "..", "..", "..", "cura-termbox", "lib").expand_path.to_s)
6
+ $LOAD_PATH.unshift(Pathname.new(__FILE__).join("..", "..", "lib").expand_path.to_s)
7
+
8
+ require "todo_list"
9
+ require "cura/termbox/adapter"
10
+
11
+ profile = false
12
+
13
+ if profile
14
+ require "ruby-prof"
15
+
16
+ RubyProf.start
17
+
18
+ TodoList.run
19
+
20
+ result = RubyProf.stop
21
+ printer = RubyProf::CallStackPrinter.new(result)
22
+
23
+ Pathname.new(__FILE__).join("..", "..", "profile.html").expand_path.open("w+") { |file| printer.print(file) }
24
+ else
25
+ TodoList.run
26
+ end
File without changes
@@ -0,0 +1,28 @@
1
+ require "pathname"
2
+
3
+ LOG_PATH = Pathname.new(__FILE__).join("..", "..", "debug.log")
4
+ LOG_PATH.truncate(0) if LOG_PATH.exist?
5
+
6
+ require "logger"
7
+ LOGGER = Logger.new(LOG_PATH)
8
+
9
+ require "todo_list/database"
10
+ require "todo_list/application"
11
+
12
+ module TodoList
13
+
14
+ class << self
15
+
16
+ def root
17
+ @root ||= Pathname.new(__FILE__).join("..", "..").expand_path
18
+ end
19
+
20
+ def run
21
+ Database.setup
22
+
23
+ Application.run
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,54 @@
1
+ require "cura"
2
+
3
+ require "todo_list/component/header"
4
+ require "todo_list/component/lists"
5
+ require "todo_list/component/list_items"
6
+
7
+ module TodoList
8
+
9
+ class Application < Cura::Application
10
+
11
+ on_event(:key_down) do |event|
12
+ stop if event.control? && event.name == :C # CTRL+C
13
+ end
14
+
15
+ attr_reader :list_items
16
+
17
+ def initialize(attributes={})
18
+ super
19
+
20
+ window = Cura::Window.new
21
+
22
+ add_window(window)
23
+
24
+ window.on_event(:key_down) do |event|
25
+ @focus_controller.index += 1 if event.control? && event.name == :F
26
+ @focus_controller.index -= 1 if event.control? && event.name == :B
27
+ end
28
+
29
+ #-
30
+
31
+ window.root = Cura::Component::Pack.new(width: window.width, height: window.height, fill: true)
32
+
33
+ header = Component::Header.new
34
+ window.add_child(header)
35
+
36
+ middle_pack = Cura::Component::Pack.new(height: window.height - 1, orientation: :horizontal, fill: true)
37
+ window.add_child(middle_pack)
38
+
39
+ sidebar = Component::Lists.new(width: 30, padding: 1)
40
+ middle_pack.add_child(sidebar)
41
+
42
+ @list_items = Component::ListItems.new(width: window.width - 30 - 4, padding: 1)
43
+ middle_pack.add_child(@list_items) # , expand: true, fill: true) # TODO
44
+
45
+ #-
46
+
47
+ @list_items.list = sidebar.listbox.selected_object if sidebar.listbox.children?
48
+
49
+ sidebar.create_list_textbox.focus
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,27 @@
1
+ module TodoList
2
+ module Component
3
+
4
+ class Header < Cura::Component::Pack
5
+
6
+ attr_reader :create_list_textbox
7
+
8
+ def initialize(attributes={})
9
+ attributes = { orientation: :horizontal }.merge(attributes)
10
+
11
+ super(attributes)
12
+
13
+ add_children(
14
+ Cura::Component::Label.new(text: "Todo", bold: true, margin: { right: 3 }),
15
+ Cura::Component::Label.new(text: "^-C to exit", margin: { right: 3 }),
16
+ Cura::Component::Label.new(text: "^-E to edit item", margin: { right: 3 }),
17
+ Cura::Component::Label.new(text: "^-D to delete item", margin: { right: 3 }),
18
+ Cura::Component::Label.new(text: "^-F to move focus forwards", margin: { right: 3 }),
19
+ Cura::Component::Label.new(text: "^-B to move focus backwards", margin: { right: 3 }),
20
+ Cura::Component::Label.new(text: "Enter to select list/toggle list item completed", margin: { right: 3 })
21
+ )
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ module TodoList
2
+ module Component
3
+
4
+ class List < Cura::Component::Pack
5
+
6
+ on_event(:focus) do |event|
7
+ @textbox.focus if event.target == self
8
+ end
9
+
10
+ def initialize(attributes={})
11
+ attributes = { orientation: :horizontal }.merge(attributes)
12
+
13
+ super(attributes)
14
+
15
+ raise ArgumentError, "model cannot be nil" if @model.nil?
16
+ raise ArgumentError, "listbox cannot be nil" if @listbox.nil?
17
+
18
+ setup_components
19
+ end
20
+
21
+ attr_accessor :model
22
+
23
+ attr_accessor :listbox
24
+
25
+ attr_reader :textbox
26
+
27
+ protected
28
+
29
+ def setup_components
30
+ setup_textbox
31
+ end
32
+
33
+ def setup_textbox
34
+ @textbox = Cura::Component::Textbox.new(text: @model.text, width: width - 2, background: :inherit, foreground: :inherit, focusable: false)
35
+ @textbox.on_event(:key_down, @listbox, @model) do |event, listbox, model|
36
+ if event.name == :enter
37
+ model.text = text
38
+ model.save
39
+
40
+ listbox.focus
41
+ end
42
+ end
43
+
44
+ add_child(@textbox)
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end