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,13 @@
1
+ if Kernel.respond_to?(:require)
2
+ require "cura/version"
3
+ require "cura/adapter"
4
+ require "cura/application"
5
+ require "cura/window"
6
+ require "cura/component/group"
7
+ require "cura/component/pack"
8
+ require "cura/component/label"
9
+ require "cura/component/button"
10
+ require "cura/component/listbox"
11
+ # require 'cura/component/scrollbar'
12
+ require "cura/component/textbox"
13
+ end
@@ -0,0 +1,67 @@
1
+ if Kernel.respond_to?(:require)
2
+ require "cura/attributes/has_initialize"
3
+ require "cura/attributes/has_attributes"
4
+ end
5
+
6
+ module Cura
7
+
8
+ # The base class for adapters.
9
+ class Adapter
10
+
11
+ class << self
12
+
13
+ # The list of all Adapter subclasses.
14
+ #
15
+ # @return [Array]
16
+ def all
17
+ @all ||= []
18
+ end
19
+
20
+ def inherited(subclass)
21
+ all << subclass
22
+ end
23
+
24
+ def mixins
25
+ @mixins ||= {}
26
+ end
27
+
28
+ def mixin(value)
29
+ mixins.merge!(value.to_h)
30
+ end
31
+
32
+ end
33
+
34
+ include Attributes::HasInitialize
35
+ include Attributes::HasAttributes
36
+
37
+ def initialize(attributes={})
38
+ @setup = false
39
+
40
+ super
41
+ end
42
+
43
+ def setup
44
+ @setup = true
45
+
46
+ self.class.mixins.each { |type, mod| type.send(:include, mod) }
47
+
48
+ self
49
+ end
50
+
51
+ def setup?
52
+ @setup
53
+ end
54
+
55
+ def clear
56
+
57
+ end
58
+
59
+ def cleanup
60
+ @setup = false
61
+
62
+ self
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,245 @@
1
+ if Kernel.respond_to?(:require)
2
+ require "cura/attributes/has_attributes"
3
+ require "cura/attributes/has_windows"
4
+ require "cura/attributes/has_events"
5
+ require "cura/attributes/has_initialize"
6
+
7
+ require "cura/component/base"
8
+
9
+ require "cura/event/dispatcher"
10
+
11
+ require "cura/event/click"
12
+ require "cura/event/focus"
13
+ require "cura/event/unfocus"
14
+ require "cura/event/handler"
15
+ require "cura/event/key_down"
16
+ require "cura/event/mouse_button"
17
+ require "cura/event/mouse_wheel_down"
18
+ require "cura/event/mouse_wheel_up"
19
+ require "cura/event/resize"
20
+ require "cura/event/selected"
21
+
22
+ require "cura/event/middleware/dispatch"
23
+ require "cura/event/middleware/aimer/mouse_focus"
24
+ require "cura/event/middleware/aimer/target_option"
25
+ require "cura/event/middleware/aimer/dispatcher_target"
26
+ require "cura/event/middleware/translator/mouse_click"
27
+
28
+ require "cura/error/invalid_adapter"
29
+
30
+ require "cura/cursor"
31
+ require "cura/pencil"
32
+ end
33
+
34
+ module Cura
35
+
36
+ # An application.
37
+ class Application
38
+
39
+ class << self
40
+
41
+ def run(attributes={})
42
+ new(attributes).run
43
+ end
44
+
45
+ end
46
+
47
+ include Attributes::HasInitialize
48
+ include Attributes::HasAttributes
49
+ include Attributes::HasWindows
50
+ include Attributes::HasEvents
51
+
52
+ def initialize(attributes={})
53
+ super
54
+
55
+ @running = false
56
+ @cursor = Cursor.new(application: self)
57
+ @pencil = Pencil.new
58
+
59
+ setup_adapter
60
+ setup_dispatcher
61
+ end
62
+
63
+ # @method adapter
64
+ # Get the adapter used for running this application.
65
+ #
66
+ # @return [Adapter]
67
+
68
+ # @method adapter=(adapter)
69
+ # Set the adapter used for running this application.
70
+ # This cannot be set after #run is used.
71
+ #
72
+ # @param [Adapter] value The new adapter.
73
+ # @return [Adapter]
74
+
75
+ attribute(:adapter) { |adapter| validate_adapter(adapter) }
76
+
77
+ # Get the text cursor.
78
+ #
79
+ # @return [Cursor]
80
+ attr_reader :cursor
81
+
82
+ # Get the pencil used for drawing.
83
+ #
84
+ # @return [Pencil]
85
+ attr_reader :pencil
86
+
87
+ # Get the event dispatcher.
88
+ #
89
+ # @return [Event::Dispatcher]
90
+ attr_reader :dispatcher
91
+
92
+ # Run this application.
93
+ #
94
+ # @return [Application] This application.
95
+ def run
96
+ run_event_loop
97
+
98
+ self
99
+ ensure
100
+ @adapter.cleanup
101
+ end
102
+
103
+ # Stop the application after the current run cycle.
104
+ #
105
+ # @return [Application] This application.
106
+ def stop
107
+ @running = false
108
+
109
+ self
110
+ end
111
+
112
+ # Stop the application immediently.
113
+ #
114
+ # @return [Application] This application.
115
+ def stop!
116
+ stop
117
+ @adapter.cleanup
118
+
119
+ self
120
+ end
121
+
122
+ # Check if this application is running.
123
+ #
124
+ # @return [Boolean]
125
+ def running?
126
+ @running
127
+ end
128
+
129
+ # Get the currently focused component.
130
+ #
131
+ # @return [Component::Base]
132
+ def focused
133
+ @dispatcher.target
134
+ end
135
+
136
+ # Set focus to a component.
137
+ #
138
+ # There can only be one component focused at a time within an application, if any.
139
+ # All dispatched events are sent to the currently focused component, or the application if no component is focused.
140
+ #
141
+ # @param [nil, Component::Base] component
142
+ # @return [Component::Base]
143
+ def focus(component)
144
+ raise TypeError, "component must be nil or be a Cura::Component::Base" unless component.nil? || component.is_a?(Cura::Component::Base)
145
+
146
+ dispatch_event(:unfocus)
147
+ @dispatcher.target = component
148
+ dispatch_event(:focus)
149
+
150
+ component
151
+ end
152
+
153
+ # Dispatch an event.
154
+ #
155
+ # @param [#to_sym] event The name of the event class to create an instance of or an event instance.
156
+ # @param [#to_hash, #to_h] options
157
+ # @option options [#to_i] :target The optional target of the event.
158
+ # @return [Event::Base] The dispatched event.
159
+ def dispatch_event(event, options={})
160
+ @dispatcher.dispatch_event(event, options)
161
+ end
162
+
163
+ # Add a window to this application.
164
+ #
165
+ # @param [Window] window
166
+ # @return [Window]
167
+ def add_window(window)
168
+ super
169
+
170
+ window.application = self
171
+
172
+ window
173
+ end
174
+
175
+ # Update all windows.
176
+ #
177
+ # @return [Application]
178
+ def update
179
+ update_windows
180
+ cursor.update
181
+
182
+ self
183
+ end
184
+
185
+ # Draw all windows.
186
+ #
187
+ # @return [Application]
188
+ def draw
189
+ draw_windows
190
+
191
+ self
192
+ end
193
+
194
+ # Instance inspection.
195
+ #
196
+ # @return [String]
197
+ def inspect
198
+ "#<#{self.class}>"
199
+ end
200
+
201
+ protected
202
+
203
+ def setup_adapter
204
+ if @adapter.nil?
205
+ adapter_class ||= Adapter.all.first
206
+ raise Error::InvalidAdapter if adapter_class.nil?
207
+
208
+ @adapter = adapter_class.new
209
+ end
210
+
211
+ # TODO: If a class is given, run .new on it first
212
+
213
+ @adapter.setup
214
+ end
215
+
216
+ def setup_dispatcher
217
+ @dispatcher = Event::Dispatcher.new(application: self)
218
+
219
+ @dispatcher.middleware << Event::Middleware::Aimer::MouseFocus.new
220
+ @dispatcher.middleware << Event::Middleware::Aimer::TargetOption.new
221
+ @dispatcher.middleware << Event::Middleware::Aimer::DispatcherTarget.new
222
+ @dispatcher.middleware << Event::Middleware::Dispatch.new
223
+ @dispatcher.middleware << Event::Middleware::Translator::MouseClick.new
224
+ end
225
+
226
+ def validate_adapter(adapter)
227
+ # TODO: Raise error if ever set more than once
228
+ raise Error::InvalidAdapter unless adapter.is_a?(Cura::Adapter)
229
+
230
+ adapter
231
+ end
232
+
233
+ def run_event_loop
234
+ @running = true
235
+
236
+ while @running
237
+ update
238
+ draw
239
+ dispatcher.run
240
+ end
241
+ end
242
+
243
+ end
244
+
245
+ end
@@ -0,0 +1,40 @@
1
+ module Cura
2
+ module Attributes
3
+
4
+ # Allows an object to have a `parent` and `ancestors`.
5
+ module HasAncestry
6
+
7
+ def initialize(attributes={})
8
+ @ancestors = []
9
+
10
+ super
11
+ end
12
+
13
+ # Get/set the parent of this object.
14
+ # It's not recommended to set this directly as it may break the ancestory chain.
15
+ #
16
+ # @return [Object]
17
+ attr_accessor :parent
18
+
19
+ # Determine if this object has a parent.
20
+ #
21
+ # @return [Boolean]
22
+ def parent?
23
+ !@parent.nil?
24
+ end
25
+
26
+ # Get the ancestors of this object.
27
+ #
28
+ # @return [Array<Object>]
29
+ def ancestors
30
+ if @parent.nil?
31
+ []
32
+ else
33
+ @parent.respond_to?(:ancestors) ? [@parent] + @parent.ancestors : [@parent]
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ if Kernel.respond_to?(:require)
2
+ require "cura/application"
3
+
4
+ require "cura/error/invalid_application"
5
+ end
6
+
7
+ module Cura
8
+ module Attributes
9
+
10
+ # Allows an object to belong to a Cura::Application.
11
+ module HasApplication
12
+
13
+ # Get the application of this object.
14
+ #
15
+ # @return [Application]
16
+ attr_reader :application
17
+
18
+ # Set the application of this object.
19
+ #
20
+ # @param [Application] value
21
+ # @return [Application]
22
+ def application=(value)
23
+ raise Error::InvalidApplication unless value.nil? || value.is_a?(Cura::Application)
24
+
25
+ @application = value
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,89 @@
1
+ module Cura
2
+ module Attributes
3
+
4
+ # Adds the `update_attributes` method.
5
+ module HasAttributes # TODO: Aspect::HasAttributes
6
+
7
+ # The class methods to be mixed in when included.
8
+ module ClassMethods
9
+
10
+ def attribute(name, options={}, &block)
11
+ options = options.to_h
12
+
13
+ if options[:query]
14
+ define_method("#{name}?") { instance_variable_get("@#{name}") }
15
+ else
16
+ attr_reader(name)
17
+ end
18
+
19
+ if options[:query]
20
+ define_method("#{name}=") do |value|
21
+ value = instance_exec(value, options, &block) unless block.nil?
22
+
23
+ instance_variable_set("@#{name}", !!value)
24
+ end
25
+ else
26
+ define_method("#{name}=") do |value|
27
+ value = instance_exec(value, options, &block) unless block.nil?
28
+
29
+ instance_variable_set("@#{name}", value)
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ class << self
37
+
38
+ def included(base)
39
+ base.extend(ClassMethods)
40
+ end
41
+
42
+ end
43
+
44
+ # Initialize this object by optionally updating attributes with a Hash.
45
+ #
46
+ # @param [#to_h] attributes Attributes to set after initializing.
47
+ def initialize(attributes={})
48
+ update_attributes(attributes)
49
+
50
+ super
51
+ end
52
+
53
+ # Update any attributes on this object.
54
+ #
55
+ # @param [#to_h] attributes
56
+ # @return [Hash] The attributes.
57
+ def update_attributes(attributes={})
58
+ attributes = convert_attributes(attributes)
59
+
60
+ attributes.each { |name, value| send("#{name}=", value) }
61
+ end
62
+
63
+ protected
64
+
65
+ VALID_SIZE_SYMBOLS = [:auto, :inherit]
66
+
67
+ def validate_size_attribute(value)
68
+ if value.is_a?(Symbol)
69
+ raise ArgumentError, "must be one of #{VALID_SIZE_SYMBOLS.join(', ')}" unless VALID_SIZE_SYMBOLS.include?(value)
70
+ else
71
+ value = value.to_i
72
+ value = 0 if value < 0
73
+ end
74
+
75
+ value
76
+ end
77
+
78
+ # Convert the attributes to a Hash and any other conversions that may need to happen.
79
+ #
80
+ # @param [#to_h] attributes
81
+ # @return [Hash] The attributes.
82
+ def convert_attributes(attributes={})
83
+ attributes.to_h
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end