cura 0.0.1 → 0.0.2

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -21
  3. data/cura.gemspec +1 -1
  4. data/examples/hello_world/lib/hello_world.rb +10 -10
  5. data/examples/mruby-examples/mrbgem.rake +5 -6
  6. data/examples/todo_list/data.db +0 -0
  7. data/examples/todo_list/lib/todo_list/application.rb +24 -18
  8. data/lib/cura/adapter.rb +13 -20
  9. data/lib/cura/application.rb +47 -51
  10. data/lib/cura/attributes/has_ancestry.rb +4 -8
  11. data/lib/cura/attributes/has_application.rb +3 -7
  12. data/lib/cura/attributes/has_attributes.rb +1 -9
  13. data/lib/cura/attributes/has_children.rb +14 -20
  14. data/lib/cura/attributes/has_colors.rb +14 -18
  15. data/lib/cura/attributes/has_coordinates.rb +9 -15
  16. data/lib/cura/attributes/has_dimensions.rb +12 -18
  17. data/lib/cura/attributes/has_events.rb +10 -18
  18. data/lib/cura/attributes/has_focusability.rb +5 -11
  19. data/lib/cura/attributes/has_initialize.rb +1 -5
  20. data/lib/cura/attributes/has_offsets.rb +16 -20
  21. data/lib/cura/attributes/has_orientation.rb +12 -18
  22. data/lib/cura/attributes/has_relative_coordinates.rb +4 -8
  23. data/lib/cura/attributes/has_root.rb +18 -22
  24. data/lib/cura/attributes/has_side_attributes.rb +18 -24
  25. data/lib/cura/attributes/has_windows.rb +13 -19
  26. data/lib/cura/borders.rb +0 -4
  27. data/lib/cura/color.rb +84 -91
  28. data/lib/cura/component/base.rb +29 -33
  29. data/lib/cura/component/button.rb +10 -16
  30. data/lib/cura/component/group.rb +14 -18
  31. data/lib/cura/component/label.rb +44 -48
  32. data/lib/cura/component/listbox.rb +24 -28
  33. data/lib/cura/component/pack.rb +14 -18
  34. data/lib/cura/component/scrollbar.rb +41 -45
  35. data/lib/cura/component/textbox.rb +21 -25
  36. data/lib/cura/cursor.rb +15 -23
  37. data/lib/cura/error/base.rb +0 -3
  38. data/lib/cura/error/invalid_adapter.rb +1 -7
  39. data/lib/cura/error/invalid_application.rb +1 -7
  40. data/lib/cura/error/invalid_color.rb +1 -7
  41. data/lib/cura/error/invalid_component.rb +1 -7
  42. data/lib/cura/error/invalid_middleware.rb +1 -7
  43. data/lib/cura/event.rb +4 -8
  44. data/lib/cura/event/base.rb +17 -24
  45. data/lib/cura/event/click.rb +1 -6
  46. data/lib/cura/event/dispatcher.rb +20 -26
  47. data/lib/cura/event/focus.rb +1 -6
  48. data/lib/cura/event/handler.rb +16 -24
  49. data/lib/cura/event/key_down.rb +11 -17
  50. data/lib/cura/event/middleware/aimer/base.rb +4 -10
  51. data/lib/cura/event/middleware/aimer/dispatcher_target.rb +2 -8
  52. data/lib/cura/event/middleware/aimer/mouse_focus.rb +6 -11
  53. data/lib/cura/event/middleware/aimer/target_option.rb +4 -10
  54. data/lib/cura/event/middleware/base.rb +0 -4
  55. data/lib/cura/event/middleware/dispatch.rb +0 -4
  56. data/lib/cura/event/middleware/translator/base.rb +4 -10
  57. data/lib/cura/event/middleware/translator/mouse_click.rb +4 -8
  58. data/lib/cura/event/mouse.rb +5 -11
  59. data/lib/cura/event/mouse_button.rb +21 -27
  60. data/lib/cura/event/mouse_wheel_down.rb +1 -6
  61. data/lib/cura/event/mouse_wheel_up.rb +1 -6
  62. data/lib/cura/event/resize.rb +0 -4
  63. data/lib/cura/event/selected.rb +1 -6
  64. data/lib/cura/event/unfocus.rb +1 -6
  65. data/lib/cura/focus_controller.rb +19 -23
  66. data/lib/cura/key.rb +277 -283
  67. data/lib/cura/margins.rb +0 -4
  68. data/lib/cura/offsets.rb +14 -18
  69. data/lib/cura/padding.rb +0 -4
  70. data/lib/cura/pencil.rb +3 -7
  71. data/lib/cura/version.rb +1 -3
  72. data/lib/cura/window.rb +11 -16
  73. data/spec/cura/attributes/has_ancestry_spec.rb +39 -39
  74. data/spec/cura/attributes/has_application_spec.rb +20 -20
  75. data/spec/cura/attributes/has_attributes_spec.rb +26 -26
  76. data/spec/cura/attributes/has_children_spec.rb +54 -54
  77. data/spec/cura/attributes/has_colors_spec.rb +4 -4
  78. data/spec/cura/attributes/has_coordinates_spec.rb +4 -4
  79. data/spec/cura/attributes/has_dimensions_spec.rb +4 -4
  80. data/spec/cura/attributes/has_events_spec.rb +4 -4
  81. data/spec/cura/attributes/has_focusability_spec.rb +18 -18
  82. data/spec/cura/attributes/has_offsets_spec.rb +4 -4
  83. data/spec/cura/attributes/has_orientation_spec.rb +38 -38
  84. data/spec/cura/attributes/has_relative_coordinates_spec.rb +4 -4
  85. data/spec/cura/attributes/has_side_attributes_spec.rb +4 -4
  86. data/spec/spec_helper.rb +1 -1
  87. data/spec/support/shared_examples_for_attributes.rb +41 -41
  88. metadata +1 -1
@@ -10,13 +10,11 @@ end
10
10
 
11
11
  module Cura
12
12
  module Component
13
-
14
13
  # The base class for all components.
15
14
  #
16
15
  # All components use a box model similar to CSS.
17
16
  # Margins, borders, paddings, then content.
18
17
  class Base
19
-
20
18
  include Attributes::HasInitialize
21
19
  include Attributes::HasAttributes
22
20
  include Attributes::HasDimensions
@@ -25,7 +23,7 @@ module Cura
25
23
  include Attributes::HasColors
26
24
  include Attributes::HasOffsets
27
25
  include Attributes::HasRelativeCoordinates
28
-
26
+
29
27
  # Get the cursor for this application.
30
28
  # TODO: Delegate something like: def_delegate(:cursor) { application }
31
29
  #
@@ -33,7 +31,7 @@ module Cura
33
31
  def cursor
34
32
  application.cursor
35
33
  end
36
-
34
+
37
35
  # Get the pencil for this application.
38
36
  # TODO: Delegate
39
37
  #
@@ -41,30 +39,30 @@ module Cura
41
39
  def pencil
42
40
  application.pencil
43
41
  end
44
-
42
+
45
43
  # Get the application of this object.
46
44
  #
47
45
  # @return [Application]
48
46
  def application
49
47
  return nil if parent.nil?
50
-
48
+
51
49
  parent.application
52
50
  end
53
-
51
+
54
52
  # Focus on this component.
55
53
  #
56
54
  # @return [Component]
57
55
  def focus
58
56
  application.dispatcher.target = self
59
57
  end
60
-
58
+
61
59
  # Check whether this component is focused.
62
60
  #
63
61
  # @return [Boolean]
64
62
  def focused?
65
63
  application.dispatcher.target == self
66
64
  end
67
-
65
+
68
66
  # Determine if the given absolute coordinates are within the bounds of this component.
69
67
  #
70
68
  # @param [#to_h] options
@@ -73,83 +71,83 @@ module Cura
73
71
  # @return [Boolean]
74
72
  def contains_coordinates?(options={})
75
73
  options = options.to_h
76
-
74
+
77
75
  (absolute_x..absolute_x + width).include?(options[:x].to_i) && (absolute_y..absolute_y + width).include?(options[:y].to_i)
78
76
  end
79
-
77
+
80
78
  # Get the foreground color of this object.
81
79
  #
82
80
  # @return [Color]
83
81
  def foreground
84
82
  get_or_inherit_color(:foreground, Color.black)
85
83
  end
86
-
84
+
87
85
  # Get the background color of this object.
88
86
  #
89
87
  # @return [Color]
90
88
  def background
91
89
  get_or_inherit_color(:background, Color.white)
92
90
  end
93
-
91
+
94
92
  # Instance inspection.
95
93
  #
96
94
  # @return [String]
97
95
  def inspect
98
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)}>"
99
97
  end
100
-
98
+
101
99
  # Update this component.
102
100
  #
103
101
  # @return [Component]
104
102
  def update
105
103
  self
106
104
  end
107
-
105
+
108
106
  # Draw this component.
109
107
  #
110
108
  # @return [Component]
111
109
  def draw
112
110
  draw_background
113
111
  draw_border
114
-
112
+
115
113
  self
116
114
  end
117
-
115
+
118
116
  protected
119
-
117
+
120
118
  # Draw a point.
121
119
  def draw_point(x, y, color=Cura::Color.black)
122
120
  x = absolute_x + @offsets.left + x
123
121
  y = absolute_y + @offsets.top + y
124
-
122
+
125
123
  pencil.draw_point(x, y, color)
126
124
  end
127
-
125
+
128
126
  # Draw a rectangle.
129
127
  # TODO: filled argument
130
128
  def draw_rectangle(x, y, width, height, color=Cura::Color.black)
131
129
  x = absolute_x + @offsets.left + x
132
130
  y = absolute_y + @offsets.top + y
133
-
131
+
134
132
  pencil.draw_rectangle(x, y, width, height, color)
135
133
  end
136
-
134
+
137
135
  # Draw a single character.
138
136
  def draw_character(x, y, character, foreground=Cura::Color.black, background=Cura::Color.white, bold=false, underline=false)
139
137
  x = absolute_x + @offsets.left + x
140
138
  y = absolute_y + @offsets.top + y
141
-
139
+
142
140
  pencil.draw_character(x, y, character, foreground, background, bold, underline)
143
141
  end
144
-
142
+
145
143
  # Draw text.
146
144
  def draw_text(x, y, text, foreground=Cura::Color.black, background=Cura::Color.white, bold=false, underline=false)
147
145
  x = absolute_x + @offsets.left + x
148
146
  y = absolute_y + @offsets.top + y
149
-
147
+
150
148
  pencil.draw_text(x, y, text, foreground, background, bold, underline)
151
149
  end
152
-
150
+
153
151
  # Draw the background of this component.
154
152
  def draw_background
155
153
  x = absolute_x + @margin.left + @border.left
@@ -157,24 +155,22 @@ module Cura
157
155
  width = self.width + @padding.width
158
156
  height = self.height + @padding.height
159
157
  color = background
160
-
158
+
161
159
  pencil.draw_rectangle(x, y, width, height, color)
162
160
  end
163
-
161
+
164
162
  # Draw the border of this component.
165
163
  def draw_border # TODO
166
164
  end
167
-
165
+
168
166
  def get_or_inherit_color(name, default)
169
167
  value = instance_variable_get("@#{name}")
170
-
168
+
171
169
  return value unless value == :inherit
172
170
  return default unless respond_to?(:parent) && parent.respond_to?(name)
173
-
171
+
174
172
  parent.send(name)
175
173
  end
176
-
177
174
  end
178
-
179
175
  end
180
176
  end
@@ -1,57 +1,51 @@
1
- if Kernel.respond_to?(:require)
2
- require "cura/component/label"
3
- end
1
+ require "cura/component/label" if Kernel.respond_to?(:require)
4
2
 
5
3
  module Cura
6
4
  module Component
7
-
8
5
  # A button component.
9
6
  class Button < Label
10
-
11
7
  on_event(:key_down) do |event|
12
8
  click if event.target == self && event.name == :enter
13
9
  end
14
-
10
+
15
11
  on_event(:mouse_button) do |event|
16
12
  click if event.target == self && event.up? && contains_coordinates?(x: event.x, y: event.y)
17
13
  end
18
-
14
+
19
15
  # @method focused_background
20
16
  # Get the focused background color of this object.
21
17
  #
22
18
  # @return [Color]
23
-
19
+
24
20
  # @method focused_background=(value)
25
21
  # Set the focused background color of this object.
26
22
  #
27
23
  # @param [Color] value
28
24
  # @return [Color]
29
-
25
+
30
26
  attribute(:focused_background) { |value| validate_color_attribute(value) }
31
-
27
+
32
28
  def initialize(attributes={})
33
29
  @focusable = true
34
30
  @foreground = Cura::Color.black
35
31
  @background = Cura::Color.white
36
32
  @focused_background = Color.new(78, 78, 78)
37
-
33
+
38
34
  super
39
35
  end
40
-
36
+
41
37
  def background
42
38
  focused? ? @focused_background : get_or_inherit_color(:background, Color.black)
43
39
  end
44
-
40
+
45
41
  # Click this button.
46
42
  #
47
43
  # @return [Button]
48
44
  def click
49
45
  application.dispatch_event(:click, target: self)
50
-
46
+
51
47
  self
52
48
  end
53
-
54
49
  end
55
-
56
50
  end
57
51
  end
@@ -5,73 +5,69 @@ end
5
5
 
6
6
  module Cura
7
7
  module Component
8
-
9
8
  # A component with children.
10
9
  # When children are added, their parent will be set to this group.
11
10
  class Group < Base
12
-
13
11
  include Attributes::HasChildren
14
-
12
+
15
13
  # Get the width of this group.
16
14
  #
17
15
  # @return [Integer]
18
16
  def width
19
17
  return @width unless @width == :auto
20
18
  return 0 if children.empty?
21
-
19
+
22
20
  children.collect { |child| child.x + child.width + child.offsets.width }.max
23
21
  end
24
-
22
+
25
23
  # Get the height of this group.
26
24
  #
27
25
  # @return [Integer]
28
26
  def height
29
27
  return @height unless @height == :auto
30
28
  return 0 if children.empty?
31
-
29
+
32
30
  children.collect { |child| child.y + child.height + child.offsets.height }.max
33
31
  end
34
-
32
+
35
33
  # Add a child to this group and set it's parent to this Group.
36
34
  #
37
35
  # @param [Component] component
38
36
  # @return [Component]
39
37
  def add_child(component)
40
38
  component = super
41
-
39
+
42
40
  component.parent = self
43
-
41
+
44
42
  component
45
43
  end
46
-
44
+
47
45
  # Remove a child from this object's children at the given index and set it's parent to nil.
48
46
  #
49
47
  # @param [Integer] index
50
48
  # @return [Component]
51
49
  def delete_child_at(index)
52
50
  component = super
53
-
51
+
54
52
  component.parent = nil
55
-
53
+
56
54
  component
57
55
  end
58
-
56
+
59
57
  # Update all children.
60
58
  def update
61
59
  super
62
-
60
+
63
61
  update_children
64
62
  end
65
-
63
+
66
64
  # Draw all children relative to this location.
67
65
  # TODO: If the dimensions of this group of this group are less than the computed dimensions, the drawing will be clipped.
68
66
  def draw
69
67
  super
70
-
68
+
71
69
  draw_children
72
70
  end
73
-
74
71
  end
75
-
76
72
  end
77
73
  end
@@ -5,12 +5,10 @@ end
5
5
 
6
6
  module Cura
7
7
  module Component
8
-
9
8
  # A component displaying text.
10
9
  class Label < Base
11
-
12
10
  include Attributes::HasAttributes
13
-
11
+
14
12
  # Note that you can pass the following:
15
13
  # alignment: { horizontal: true, vertical: true }
16
14
  # instead of:
@@ -21,94 +19,94 @@ module Cura
21
19
  @bold = false
22
20
  @underline = false
23
21
  @text = ""
24
-
22
+
25
23
  super
26
24
  end
27
-
25
+
28
26
  # TODO: #text_foreground, #text_background (? Maybe a separate Text component, like in )
29
-
27
+
30
28
  # Get the width of this label.
31
29
  #
32
30
  # @return [Integer]
33
31
  def width
34
32
  return text_width if @width == :auto
35
-
33
+
36
34
  @width
37
35
  end
38
-
36
+
39
37
  # Get the height of this label.
40
38
  #
41
39
  # @return [Integer]
42
40
  def height
43
41
  return text_height if @height == :auto
44
-
42
+
45
43
  @height
46
44
  end
47
-
45
+
48
46
  # @method text
49
47
  # Get the text of this label.
50
48
  #
51
49
  # @return [String]
52
-
50
+
53
51
  # @method text=(value)
54
52
  # Set the text of this label.
55
53
  #
56
54
  # @param [#to_s] value
57
55
  # @return [String]
58
56
  attribute(:text) { |value| value.to_s }
59
-
57
+
60
58
  # Get the lines of this label.
61
59
  #
62
60
  # @return [<String>]
63
61
  def lines
64
62
  @text.split("\n") # NOTE: Would use String#lines but it's output doesn't think a trailing newline character constitutes a line unless it is followed by another character. #split also removes the newline characters.
65
63
  end
66
-
64
+
67
65
  # Get the width of the text of this label.
68
66
  #
69
67
  # @return [Integer]
70
68
  def text_width
71
69
  return 0 if @text.empty?
72
-
70
+
73
71
  lines.collect(&:length).sort.last
74
72
  end
75
-
73
+
76
74
  # Get the height of the text of this label.
77
75
  #
78
76
  # @return [Integer]
79
77
  def text_height
80
78
  value = lines.length
81
-
79
+
82
80
  value == 0 ? 1 : value
83
81
  end
84
-
82
+
85
83
  # @method bold?
86
84
  # Get whether the text is bold.
87
85
  #
88
86
  # @return [Boolean]
89
-
87
+
90
88
  # @method bold=(value)
91
89
  # Set whether the text is bold.
92
90
  #
93
91
  # @return [Boolean]
94
92
  attribute(:bold, query: true)
95
-
93
+
96
94
  # @method underline?
97
95
  # Get whether the text is underlined.
98
96
  #
99
97
  # @return [Boolean]
100
-
98
+
101
99
  # @method underlined=(value)
102
100
  # Set whether the text is underlined.
103
101
  #
104
102
  # @return [Boolean]
105
103
  attribute(:underline, query: true)
106
-
104
+
107
105
  # @method horizontal_alignment
108
106
  # Get the horizontal alignment of this label.
109
107
  #
110
108
  # @return [Symbol]
111
-
109
+
112
110
  # @method horizontal_alignment=(value)
113
111
  # Set the horizontal alignment of this label.
114
112
  # Must be :left, :center, or :right.
@@ -116,13 +114,13 @@ module Cura
116
114
  # @param [#to_sym] value
117
115
  # @return [Symbol]
118
116
  attribute(:horizontal_alignment) { |value| convert_horizontal_alignment_attribute(value) }
119
-
117
+
120
118
  # @method vertical_alignment
121
119
  # Get the vertical alignment of this label.
122
120
  # Will be :left, :center, or :right.
123
121
  #
124
122
  # @return [Symbol]
125
-
123
+
126
124
  # @method vertical_alignment=(value)
127
125
  # Set the vertical alignment of this label.
128
126
  # Must be :left, :center, or :right.
@@ -130,48 +128,48 @@ module Cura
130
128
  # @param [#to_sym] value
131
129
  # @return [Symbol]
132
130
  attribute(:vertical_alignment) { |value| convert_vertical_alignment_attribute(value) }
133
-
131
+
134
132
  def draw
135
133
  super
136
-
134
+
137
135
  draw_text unless text.empty?
138
136
  end
139
-
137
+
140
138
  protected
141
-
139
+
142
140
  # Helper method for subclasses
143
141
  def text_to_draw
144
142
  @text
145
143
  end
146
-
144
+
147
145
  # Helper method for subclasses
148
146
  def character_to_draw(character)
149
147
  character
150
148
  end
151
-
149
+
152
150
  # TODO: Should use instance vars
153
151
  def draw_text
154
- x_offset = x_offset_start = x_offset_from_alignment# + @offsets.left
155
- y_offset = y_offset_from_alignment# + @offsets.top
152
+ x_offset = x_offset_start = x_offset_from_alignment # + @offsets.left
153
+ y_offset = y_offset_from_alignment # + @offsets.top
156
154
  absolute_x = self.absolute_x
157
155
  absolute_y = self.absolute_y
158
-
156
+
159
157
  text_to_draw.each_char do |character|
160
158
  if character == "\n" # TODO: If multiline? Also check if outside the bounds of the drawing area
161
159
  x_offset = x_offset_start
162
-
160
+
163
161
  y_offset += 1
164
162
  else
165
163
  unless x_offset > width || y_offset > height
166
164
  character = character_to_draw(character)
167
165
  draw_character(x_offset, y_offset, character, foreground, background, @bold, @underline)
168
166
  end
169
-
167
+
170
168
  x_offset += 1
171
169
  end
172
170
  end
173
171
  end
174
-
172
+
175
173
  def x_offset_from_alignment
176
174
  case horizontal_alignment
177
175
  when :left then 0
@@ -179,7 +177,7 @@ module Cura
179
177
  when :right then (text_width - width).abs
180
178
  end
181
179
  end
182
-
180
+
183
181
  def y_offset_from_alignment
184
182
  case vertical_alignment
185
183
  when :top then 0
@@ -187,38 +185,36 @@ module Cura
187
185
  when :bottom then (text_height - height).abs
188
186
  end
189
187
  end
190
-
188
+
191
189
  protected
192
-
190
+
193
191
  # TODO: Just use a #alignment attribute and have a Cura::Alignment object?
194
192
  def convert_attributes(attributes={})
195
193
  attributes = super
196
-
194
+
197
195
  if attributes.key?(:alignment)
198
196
  alignment_attributes = attributes.delete(:alignment).to_h
199
-
197
+
200
198
  attributes[:horizontal_alignment] = alignment_attributes[:horizontal] if alignment_attributes.key?(:horizontal)
201
199
  attributes[:vertical_alignment] = alignment_attributes[:vertical] if alignment_attributes.key?(:vertical)
202
200
  end
203
-
201
+
204
202
  attributes
205
203
  end
206
-
204
+
207
205
  def convert_horizontal_alignment_attribute(value)
208
206
  value = value.to_sym
209
207
  raise ArgumentError, "must be :left, :center, or :right" unless [:left, :center, :right].include?(value)
210
-
208
+
211
209
  value
212
210
  end
213
-
211
+
214
212
  def convert_vertical_alignment_attribute(value)
215
213
  value = value.to_sym
216
214
  raise ArgumentError, "must be :top, :center, or :bottom" unless [:top, :center, :bottom].include?(value)
217
-
215
+
218
216
  value
219
217
  end
220
-
221
218
  end
222
-
223
219
  end
224
220
  end