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