cura 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +25 -11
  3. data/Gemfile.lock +157 -62
  4. data/Rakefile +71 -18
  5. data/examples/todo_list/bin/todo_list +4 -1
  6. data/examples/todo_list/lib/todo_list/component/list_items.rb +27 -27
  7. data/examples/todo_list/lib/todo_list/component/lists.rb +27 -27
  8. data/lib/cura/application.rb +3 -0
  9. data/lib/cura/attributes/has_children.rb +25 -4
  10. data/lib/cura/attributes/has_colors.rb +7 -3
  11. data/lib/cura/attributes/has_dimensions.rb +1 -1
  12. data/lib/cura/attributes/has_events.rb +1 -1
  13. data/lib/cura/attributes/has_root.rb +8 -3
  14. data/lib/cura/attributes/has_visibility.rb +28 -0
  15. data/lib/cura/color.rb +2 -0
  16. data/lib/cura/component/base.rb +34 -9
  17. data/lib/cura/component/group.rb +19 -2
  18. data/lib/cura/component/listbox.rb +15 -4
  19. data/lib/cura/component/pack.rb +8 -4
  20. data/lib/cura/component.rb +23 -0
  21. data/lib/cura/error/invalid_component.rb +1 -1
  22. data/lib/cura/event/dispatcher.rb +1 -1
  23. data/lib/cura/event/middleware/aimer/target_option.rb +1 -3
  24. data/lib/cura/event/middleware/dispatch.rb +3 -2
  25. data/lib/cura/event/middleware/translator/mouse_click.rb +1 -1
  26. data/lib/cura/key.rb +12 -12
  27. data/lib/cura/version.rb +1 -1
  28. data/spec/spec_helper.rb +0 -1
  29. data/spec/{cura → unit/cura}/attributes/has_ancestry_spec.rb +0 -0
  30. data/spec/{cura → unit/cura}/attributes/has_application_spec.rb +0 -0
  31. data/spec/{cura → unit/cura}/attributes/has_attributes_spec.rb +0 -0
  32. data/spec/{cura → unit/cura}/attributes/has_children_spec.rb +0 -0
  33. data/spec/{cura → unit/cura}/attributes/has_colors_spec.rb +0 -0
  34. data/spec/{cura → unit/cura}/attributes/has_coordinates_spec.rb +0 -0
  35. data/spec/{cura → unit/cura}/attributes/has_dimensions_spec.rb +0 -0
  36. data/spec/{cura → unit/cura}/attributes/has_events_spec.rb +0 -0
  37. data/spec/{cura → unit/cura}/attributes/has_focusability_spec.rb +0 -0
  38. data/spec/{cura → unit/cura}/attributes/has_offsets_spec.rb +0 -0
  39. data/spec/{cura → unit/cura}/attributes/has_orientation_spec.rb +0 -0
  40. data/spec/{cura → unit/cura}/attributes/has_relative_coordinates_spec.rb +0 -0
  41. data/spec/{cura → unit/cura}/attributes/has_side_attributes_spec.rb +0 -0
  42. metadata +43 -51
  43. data/examples/box_model/debug.log +0 -0
  44. data/examples/todo_list/app.log +0 -9
  45. data/examples/todo_list/data.db +0 -0
  46. data/examples/todo_list/debug.log +0 -0
  47. data/examples/todo_list/profile.html +0 -11354
@@ -2,88 +2,88 @@ require "todo_list/component/list"
2
2
 
3
3
  module TodoList
4
4
  module Component
5
-
5
+
6
6
  class Lists < Cura::Component::Pack
7
-
7
+
8
8
  attr_reader :create_list_textbox
9
9
  attr_reader :listbox
10
-
11
-
10
+
11
+
12
12
  def initialize(attributes={})
13
13
  attributes = { fill: true, padding: { top: 1, bottom: 1 } }.merge(attributes)
14
-
14
+
15
15
  super(attributes)
16
-
16
+
17
17
  create_form_pack = Cura::Component::Pack.new(orientation: :horizontal)
18
18
  add_child(create_form_pack)
19
-
19
+
20
20
  @create_list_textbox = Cura::Component::Textbox.new(width: width - 16, margin: { right: 1 })
21
21
  @create_list_textbox.on_event(:key_down, self) { |event, model_list| model_list.create_list if event.name == :enter }
22
22
  create_form_pack.add_child(@create_list_textbox)
23
-
23
+
24
24
  @create_list_button = Cura::Component::Button.new(text: "Create List", padding: { left: 1, right: 1 })
25
25
  @create_list_button.on_event(:click, self) { |_, model_list| model_list.create_list }
26
26
  create_form_pack.add_child(@create_list_button)
27
-
27
+
28
28
  @listbox_header_label = Cura::Component::Label.new(text: "Lists" + " " * (width - 5), bold: true, underline: true, margin: { top: 1 })
29
29
  add_child(@listbox_header_label)
30
-
30
+
31
31
  @listbox = Cura::Component::Listbox.new(width: @width)
32
-
32
+
33
33
  @listbox.on_event(:selected) do
34
34
  application.list_items.list = selected_object unless selected_object.nil?
35
35
  end
36
-
36
+
37
37
  @listbox.on_event(:key_down, self) do |event, model_list|
38
38
  if event.target == self
39
39
  if event.control? && event.name == :D && !selected_object.nil?
40
40
  selected_object.list_items.each(&:destroy)
41
41
  selected_object.destroy
42
-
42
+
43
43
  application.list_items.list = nil
44
44
 
45
45
  previous_selected_index = @selected_index
46
46
  model_list.fill_listbox
47
47
  self.selected_index = [previous_selected_index, count - 1].min
48
48
  end
49
-
49
+
50
50
  if event.control? && event.name == :E
51
51
  selected_child.focus
52
52
  end
53
-
53
+
54
54
  if event.name == :enter
55
55
  application.list_items.listbox.focus
56
56
  end
57
57
  end
58
58
  end
59
-
59
+
60
60
  add_child(@listbox)
61
-
61
+
62
62
  fill_listbox
63
63
  end
64
-
64
+
65
65
  def create_list
66
66
  Model::List.create(text: @create_list_textbox.text)
67
-
67
+
68
68
  fill_listbox
69
-
69
+
70
70
  @create_list_textbox.clear
71
71
  @create_list_textbox.focus
72
-
72
+
73
73
  application.list_items.list = @listbox.selected_object unless @listbox.selected_object.nil?
74
74
  end
75
-
75
+
76
76
  def fill_listbox
77
77
  @listbox.delete_children
78
-
78
+
79
79
  Model::List.all.each do |list|
80
80
  list_component = Component::List.new(listbox: @listbox, model: list, width: @listbox.width)
81
-
82
- @listbox.add_child(list_component, list)
81
+
82
+ @listbox.add_child(list_component, object: list)
83
83
  end
84
84
  end
85
-
85
+
86
86
  end
87
-
87
+
88
88
  end
89
89
  end
@@ -207,6 +207,9 @@ module Cura
207
207
  end
208
208
 
209
209
  # TODO: If a class is given, run .new on it first
210
+ # TODO: Adapter.name(*arguments) which defaults to an underscore'd version of the class constant
211
+ # TODO: Adapter.find_by_name
212
+ # TODO: Use Adapter.find_by_name here to allow passing of a Symbol to #adapter=
210
213
 
211
214
  @adapter.setup
212
215
  end
@@ -1,6 +1,5 @@
1
1
  if Kernel.respond_to?(:require)
2
2
  require "cura/component/base"
3
-
4
3
  require "cura/error/invalid_component"
5
4
  end
6
5
 
@@ -38,10 +37,32 @@ module Cura
38
37
 
39
38
  # Add a child to this group.
40
39
  #
41
- # @param [Component] component
40
+ # If a Hash-like object is given, it must have the `:type` key which will be used to
41
+ # determine which class to initialize. The rest of the Hash will be used to set the
42
+ # attributes of the instance.
43
+ #
44
+ # @param [#to_sym, Component] component_or_type
45
+ # A Symbol representing the child component type or a {Component::Base} instance.
46
+ # When a Symbol is given, a new child component will be initialized of that type. See {Component::Base.type}.
47
+ # @param [#to_h] attributes
48
+ # When component_or_type is a Symbol, then these attributes will be used to initialize the child component.
49
+ # When component_or_type is a {Component::Base}, then these attributes will be used to update the child component.
42
50
  # @return [Component]
43
- def add_child(component)
44
- raise TypeError, "component must be a Cura::Component" unless component.is_a?(Component::Base)
51
+ def add_child(component_or_type, attributes={})
52
+ component = if component_or_type.respond_to?(:to_sym)
53
+ type = component_or_type.to_sym
54
+ component_class = Component.find_by_type(type)
55
+
56
+ raise Error::InvalidComponent if component_class.nil?
57
+
58
+ component_class.new
59
+ else
60
+ raise Error::InvalidComponent unless component_or_type.is_a?(Component::Base)
61
+
62
+ component_or_type
63
+ end
64
+
65
+ component.update_attributes(attributes)
45
66
 
46
67
  @children << component
47
68
 
@@ -28,7 +28,7 @@ module Cura
28
28
  # @method foreground=(value)
29
29
  # Set the foreground color of this object.
30
30
  #
31
- # @param [Color] value
31
+ # @param [Color, #to_sym] value
32
32
  # @return [Color]
33
33
 
34
34
  attribute(:foreground) { |value| validate_color_attribute(value) }
@@ -41,7 +41,7 @@ module Cura
41
41
  # @method background=(value)
42
42
  # Set the background color of this object.
43
43
  #
44
- # @param [Color] value
44
+ # @param [Color, #to_sym] value
45
45
  # @return [Color]
46
46
 
47
47
  attribute(:background) { |value| validate_color_attribute(value) }
@@ -52,7 +52,11 @@ module Cura
52
52
  unless value.is_a?(Cura::Color)
53
53
  value = value.to_sym
54
54
 
55
- raise Error::InvalidColor unless value == :inherit
55
+ if [:black, :white, :red, :green, :blue].include?(value)
56
+ value = Cura::Color.send(value)
57
+ else
58
+ raise Error::InvalidColor unless value == :inherit
59
+ end
56
60
  end
57
61
 
58
62
  value
@@ -16,12 +16,12 @@ module Cura
16
16
  # @method width
17
17
  # Get the width dimension of this object.
18
18
  #
19
- # @param [#to_i] value
20
19
  # @return [Integer]
21
20
 
22
21
  # @method width=(value)
23
22
  # Set the width dimension of this object.
24
23
  #
24
+ # @param [#to_i] value
25
25
  # @return [Integer]
26
26
 
27
27
  attribute(:width) { |value| validate_size_attribute(value) }
@@ -56,7 +56,7 @@ module Cura
56
56
  # Get the event handler for this object.
57
57
  #
58
58
  # @return [Event::Handler]
59
- attr_reader :event_handler
59
+ attr_reader :event_handler # TODO: Rename to #events ?
60
60
 
61
61
  # Register a callback for an event to this instance.
62
62
  #
@@ -40,10 +40,15 @@ module Cura
40
40
 
41
41
  # Add a child to this object's root component.
42
42
  #
43
- # @param [Component] component
43
+ # @param [#to_sym, Component] component_or_type
44
+ # A Symbol representing the child component type or a {Component::Base} instance.
45
+ # When a Symbol is given, a new child component will be initialized of that type. See {Component::Base.type}.
46
+ # @param [#to_h] attributes
47
+ # When component_or_type is a Symbol, then these attributes will be used to initialize the child component.
48
+ # When component_or_type is a {Component::Base}, then these attributes will be used to update the child component.
44
49
  # @return [Component]
45
- def add_child(component)
46
- @root.add_child(component)
50
+ def add_child(component_or_type, attributes={})
51
+ @root.add_child(component_or_type, attributes)
47
52
  end
48
53
 
49
54
  # Add multiple children to this object's root component.
@@ -0,0 +1,28 @@
1
+ require "cura/attributes/has_attributes" if Kernel.respond_to?(:require)
2
+
3
+ module Cura
4
+ module Attributes
5
+ # Adds the `#visible?`, `visible=` methods.
6
+ module HasVisibility
7
+ include HasAttributes
8
+
9
+ def initialize(attributes={})
10
+ @visible = true
11
+
12
+ super
13
+ end
14
+
15
+ # @method visible?
16
+ # Get the visibility.
17
+ #
18
+ # @return [Boolean]
19
+
20
+ # @method visible=
21
+ # Set the visibility.
22
+ #
23
+ # @return [Boolean]
24
+
25
+ attribute(:visible, query: true)
26
+ end
27
+ end
28
+ end
data/lib/cura/color.rb CHANGED
@@ -10,6 +10,8 @@ module Cura
10
10
  include Attributes::HasAttributes
11
11
 
12
12
  class << self
13
+ # TODO: All standard color names
14
+
13
15
  # The default color to be overidden by adapters.
14
16
  # Usually, for TUI's to use the terminal theme's colors.
15
17
  # TODO: Remove.
@@ -6,6 +6,8 @@ if Kernel.respond_to?(:require)
6
6
  require "cura/attributes/has_events"
7
7
  require "cura/attributes/has_offsets"
8
8
  require "cura/attributes/has_relative_coordinates"
9
+ require "cura/attributes/has_visibility"
10
+ require "cura/component"
9
11
  end
10
12
 
11
13
  module Cura
@@ -15,14 +17,35 @@ module Cura
15
17
  # All components use a box model similar to CSS.
16
18
  # Margins, borders, paddings, then content.
17
19
  class Base
20
+ class << self
21
+ # On subclass hook.
22
+ def inherited(subclass)
23
+ Component.all << subclass
24
+ end
25
+
26
+ # The type of this component class.
27
+ #
28
+ # @example
29
+ # Cura::Component::XMLTools::AttributeLabel.type # => :xml_tools_attribute_label
30
+ # @return [Symbol]
31
+ def type # TODO: Helper method for this sort of thing
32
+ @type ||= to_s.gsub(/^Cura::Component::/, "")
33
+ .gsub(/([A-Z][A-Za-z]*)([A-Z][A-Za-z0-9_]*)/, "\\1_\\2")
34
+ .gsub(/::/, "_").downcase.to_sym
35
+ end
36
+ end
37
+
18
38
  include Attributes::HasInitialize
19
39
  include Attributes::HasAttributes
40
+
41
+ include Attributes::HasAncestry
20
42
  include Attributes::HasDimensions
21
43
  include Attributes::HasEvents
22
44
  include Attributes::HasFocusability
23
45
  include Attributes::HasColors
24
46
  include Attributes::HasOffsets
25
47
  include Attributes::HasRelativeCoordinates
48
+ include Attributes::HasVisibility
26
49
 
27
50
  # Get the cursor for this application.
28
51
  # TODO: Delegate something like: def_delegate(:cursor) { application }
@@ -89,13 +112,6 @@ module Cura
89
112
  get_or_inherit_color(:background, Color.white)
90
113
  end
91
114
 
92
- # Instance inspection.
93
- #
94
- # @return [String]
95
- def inspect
96
- "#<#{self.class}:0x#{__id__.to_s(16)} x=#{x} y=#{y} absolute_x=#{absolute_x} absolute_y=#{absolute_y} w=#{width} h=#{height} parent=#{@parent.class}:0x#{@parent.__id__.to_s(16)}>"
97
- end
98
-
99
115
  # Update this component.
100
116
  #
101
117
  # @return [Component]
@@ -107,12 +123,21 @@ module Cura
107
123
  #
108
124
  # @return [Component]
109
125
  def draw
110
- draw_background
111
- draw_border
126
+ if @visible
127
+ draw_background
128
+ draw_border
129
+ end
112
130
 
113
131
  self
114
132
  end
115
133
 
134
+ # Instance inspection.
135
+ #
136
+ # @return [String]
137
+ def inspect
138
+ "#<#{self.class}:0x#{__id__.to_s(16)} x=#{x} y=#{y} absolute_x=#{absolute_x} absolute_y=#{absolute_y} w=#{width} h=#{height} parent=#{@parent.class}:0x#{@parent.__id__.to_s(16)}>"
139
+ end
140
+
116
141
  protected
117
142
 
118
143
  # Draw a point.
@@ -30,11 +30,28 @@ module Cura
30
30
  children.collect { |child| child.y + child.height + child.offsets.height }.max
31
31
  end
32
32
 
33
+ # # Set the parent of this object.
34
+ # # It's not recommended to set this directly as it may break the ancestory chain.
35
+ # #
36
+ # # @param [Object] value
37
+ # # @return [Object]
38
+ # def parent=(value)
39
+ # @parent = value
40
+ # @children.each
41
+ #
42
+ # @parent
43
+ # end
44
+
33
45
  # Add a child to this group and set it's parent to this Group.
34
46
  #
35
- # @param [Component] component
47
+ # @param [#to_sym, Component] component_or_type
48
+ # A Symbol representing the child component type or a {Component::Base} instance.
49
+ # When a Symbol is given, a new child component will be initialized of that type. See {Component::Base.type}.
50
+ # @param [#to_h] attributes
51
+ # When component_or_type is a Symbol, then these attributes will be used to initialize the child component.
52
+ # When component_or_type is a {Component::Base}, then these attributes will be used to update the child component.
36
53
  # @return [Component]
37
- def add_child(component)
54
+ def add_child(component_or_type, attributes={})
38
55
  component = super
39
56
 
40
57
  component.parent = self
@@ -83,11 +83,17 @@ module Cura
83
83
 
84
84
  # Add a child to this group.
85
85
  #
86
- # @param [Component] component
87
- # @param [Object] object An arbitrary object to associate with the added child in this listbox.
86
+ # @param [#to_sym, Component] component_or_type
87
+ # A Symbol representing the child component type or a {Component::Base} instance.
88
+ # When a Symbol is given, a new child component will be initialized of that type. See {Component::Base.type}.
89
+ # @param [#to_h] attributes
90
+ # When component_or_type is a Symbol, then these attributes will be used to initialize the child component.
91
+ # When component_or_type is a {Component::Base}, then these attributes will be used to update the child component.
92
+ # @option attributes [Object] :object An arbitrary object to associate with the added child in this listbox.
88
93
  # @return [Component]
89
- def add_child(component, object=nil)
90
- child = super(component)
94
+ def add_child(component_or_type, attributes={})
95
+ object = attributes.delete(:object)
96
+ child = super
91
97
 
92
98
  @objects << object
93
99
 
@@ -107,6 +113,11 @@ module Cura
107
113
  deleted_child
108
114
  end
109
115
 
116
+ # Get the objects stored.
117
+ #
118
+ # @return [Array]
119
+ attr_reader :objects
120
+
110
121
  # Get the associated object with the child at the given index.
111
122
  #
112
123
  # @param [#to_i] index
@@ -15,7 +15,6 @@ module Cura
15
15
  @fill = false
16
16
  @spacing = 0
17
17
 
18
- # @child_modifiers
19
18
  super
20
19
  end
21
20
 
@@ -39,15 +38,20 @@ module Cura
39
38
 
40
39
  # Add a child to this group.
41
40
  #
42
- # @param [Component] component
43
- # @param [#to_hash, #to_h] options
41
+ # @param [#to_sym, Component] component_or_type
42
+ # A Symbol representing the child component type or a {Component::Base} instance.
43
+ # When a Symbol is given, a new child component will be initialized of that type. See {Component::Base.type}.
44
+ # @param [#to_h] attributes
45
+ # When component_or_type is a Symbol, then these attributes will be used to initialize the child component.
46
+ # When component_or_type is a {Component::Base}, then these attributes will be used to update the child component.
44
47
  # @option options [#to_i] :expand
45
48
  # The new child is to be given extra space. The extra space will be divided evenly between all children that use this option.
46
49
  # @option options [#to_i] :fill
47
50
  # The space given to child by the expand option is actually allocated to child, rather than just padding it.
48
51
  # This parameter has no effect if expand is set to false.
49
52
  # @return [Component]
50
- def add_child(component)
53
+ def add_child(component_or_type, attributes={})
54
+ # TODO: :expand and :fill attributes?
51
55
  child = super
52
56
 
53
57
  pack_children
@@ -0,0 +1,23 @@
1
+ module Cura
2
+ # The container module for components.
3
+ module Component
4
+ class << self
5
+ # All {Component::Base} subclasses.
6
+ #
7
+ # @return [<Class>]
8
+ def all
9
+ @all ||= []
10
+ end
11
+
12
+ # Find a {Component::Base} subclass by it's type.
13
+ #
14
+ # @param [#to_sym] value
15
+ # @return [nil, Class]
16
+ def find_by_type(value)
17
+ value = value.to_sym
18
+
19
+ all.find { |component_class| component_class.type == value }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,7 +5,7 @@ module Cura
5
5
  # Raised when a component is invalid.
6
6
  class InvalidComponent < Base
7
7
  def to_s
8
- "must be a Cura::Component::Base"
8
+ "invalid component"
9
9
  end
10
10
  end
11
11
  end
@@ -96,7 +96,7 @@ module Cura
96
96
  @application.adapter.peek_event(milliseconds.to_i)
97
97
  end
98
98
 
99
- # Dispatch an event to the target or application, if the target is nil.
99
+ # Send the event through the middleware stack and dispatch all events on the queue.
100
100
  #
101
101
  # @param [#to_sym] event The name of the event class to create an instance of or an event instance.
102
102
  # @param [#to_hash, #to_h] options The options to pass through the middleware.
@@ -6,15 +6,13 @@ module Cura
6
6
  module Aimer
7
7
  # Sets the event's target to the component passed by an optional :target option.
8
8
  class TargetOption < Base
9
+ # @method call
9
10
  # Call this middleware.
10
11
  #
11
12
  # @param [#to_h] options
12
13
  # @option options [Event::Dispatcher] :dispatcher
13
14
  # @option options [Event::Base] :event
14
15
  # @option options [Attributes::HasEvents] :target The optional target of the event.
15
- def call(options={})
16
- super # Only here for documentation
17
- end
18
16
 
19
17
  protected
20
18
 
@@ -1,9 +1,10 @@
1
1
  module Cura
2
2
  module Event
3
3
  module Middleware
4
- # Dispatches the event.
4
+ # Adds the event to the dispatch queue.
5
+ # Should be the very last middleware in the chain.
5
6
  class Dispatch < Base
6
- # Dispatch the event.
7
+ # Add the event to the dispatch queue.
7
8
  #
8
9
  # @param [#to_h] options
9
10
  # @option options [Event::Base] :event
@@ -10,7 +10,7 @@ module Cura
10
10
  # Translates MouseDown and MouseUp events into a MouseClick event.
11
11
  class MouseClick < Base
12
12
  def initialize
13
- @last_mouse_down_at = Time.now
13
+ @last_mouse_down_at = Time.now # TODO: This is not a great solution. If/when events are threaded, this will be bad.
14
14
  end
15
15
 
16
16
  # Call this middleware.
data/lib/cura/key.rb CHANGED
@@ -197,18 +197,18 @@ module Cura
197
197
  mute: nil,
198
198
  non_us_backslash: nil,
199
199
  non_us_hash: nil,
200
- "0": "0",
201
- "00": "00",
202
- "000": "000",
203
- "1": "1",
204
- "2": "2",
205
- "3": "3",
206
- "4": "4",
207
- "5": "5",
208
- "6": "6",
209
- "7": "7",
210
- "8": "8",
211
- "9": "9",
200
+ "0".to_sym => "0",
201
+ "00".to_sym => "00",
202
+ "000".to_sym => "000",
203
+ "1".to_sym => "1",
204
+ "2".to_sym => "2",
205
+ "3".to_sym => "3",
206
+ "4".to_sym => "4",
207
+ "5".to_sym => "5",
208
+ "6".to_sym => "6",
209
+ "7".to_sym => "7",
210
+ "8".to_sym => "8",
211
+ "9".to_sym => "9",
212
212
  numlock_clear: nil,
213
213
  numpad_0: "0",
214
214
  numpad_1: "1",
data/lib/cura/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # An adaptable component library for creating graphical and text-based user interfaces.
2
2
  module Cura
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require "simplecov"
2
- SimpleCov.start
3
2
 
4
3
  RSpec.configure do |config|
5
4
  config.expect_with :rspec do |expectations|