lacci 0.3.0 → 0.4.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/lacci/scarpe_cli.rb +0 -1
  3. data/lib/lacci/version.rb +1 -1
  4. data/lib/scarpe/niente/display_service.rb +5 -1
  5. data/lib/scarpe/niente/drawable.rb +2 -0
  6. data/lib/scarpe/niente/shoes_spec.rb +7 -1
  7. data/lib/scarpe/niente.rb +14 -2
  8. data/lib/shoes/app.rb +44 -50
  9. data/lib/shoes/constants.rb +23 -2
  10. data/lib/shoes/display_service.rb +43 -4
  11. data/lib/shoes/drawable.rb +309 -35
  12. data/lib/shoes/drawables/arc.rb +2 -24
  13. data/lib/shoes/drawables/arrow.rb +2 -22
  14. data/lib/shoes/drawables/border.rb +28 -0
  15. data/lib/shoes/drawables/button.rb +4 -20
  16. data/lib/shoes/drawables/check.rb +7 -3
  17. data/lib/shoes/drawables/document_root.rb +4 -4
  18. data/lib/shoes/drawables/edit_box.rb +6 -5
  19. data/lib/shoes/drawables/edit_line.rb +5 -4
  20. data/lib/shoes/drawables/flow.rb +3 -5
  21. data/lib/shoes/drawables/font_helper.rb +62 -0
  22. data/lib/shoes/drawables/image.rb +2 -2
  23. data/lib/shoes/drawables/line.rb +4 -7
  24. data/lib/shoes/drawables/link.rb +5 -8
  25. data/lib/shoes/drawables/list_box.rb +8 -5
  26. data/lib/shoes/drawables/oval.rb +48 -0
  27. data/lib/shoes/drawables/para.rb +106 -18
  28. data/lib/shoes/drawables/progress.rb +2 -1
  29. data/lib/shoes/drawables/radio.rb +5 -3
  30. data/lib/shoes/drawables/rect.rb +5 -4
  31. data/lib/shoes/drawables/shape.rb +2 -1
  32. data/lib/shoes/drawables/slot.rb +99 -8
  33. data/lib/shoes/drawables/stack.rb +6 -11
  34. data/lib/shoes/drawables/star.rb +8 -30
  35. data/lib/shoes/drawables/text_drawable.rb +93 -34
  36. data/lib/shoes/drawables/video.rb +3 -2
  37. data/lib/shoes/drawables/widget.rb +8 -3
  38. data/lib/shoes/drawables.rb +2 -1
  39. data/lib/shoes/errors.rb +13 -3
  40. data/lib/shoes/margin_helper.rb +79 -0
  41. data/lib/shoes.rb +4 -3
  42. metadata +11 -11
  43. data/lib/scarpe/niente/logger.rb +0 -29
  44. data/lib/shoes/drawables/span.rb +0 -27
  45. data/lib/shoes/spacing.rb +0 -9
@@ -2,13 +2,14 @@
2
2
 
3
3
  class Shoes
4
4
  class EditBox < Shoes::Drawable
5
- shoes_styles :text, :height, :width
5
+ shoes_styles :text, :height, :width ,:tooltip, :font
6
6
  shoes_events :change
7
7
 
8
- def initialize(text = "", height: nil, width: nil, &block)
9
- super
10
- @text = text
8
+ init_args
9
+ opt_init_args :text
10
+ def initialize(*args, **kwargs, &block)
11
11
  @callback = block
12
+ super
12
13
 
13
14
  bind_self_event("change") do |new_text|
14
15
  self.text = new_text
@@ -23,7 +24,7 @@ class Shoes
23
24
  end
24
25
 
25
26
  def append(new_text)
26
- self.text = self.text + new_text
27
+ self.text = (self.text || "") + new_text
27
28
  end
28
29
  end
29
30
  end
@@ -2,13 +2,14 @@
2
2
 
3
3
  class Shoes
4
4
  class EditLine < Shoes::Drawable
5
- shoes_styles :text, :width
5
+ shoes_styles :text, :width, :font, :tooltip, :stroke
6
6
  shoes_events :change
7
7
 
8
- def initialize(text = "", width: nil, &block)
9
- super
8
+ init_args
9
+ opt_init_args :text
10
+ def initialize(*args, **kwargs, &block)
10
11
  @block = block
11
- @text = text
12
+ super
12
13
 
13
14
  bind_self_event("change") do |new_text|
14
15
  self.text = new_text
@@ -3,15 +3,13 @@
3
3
  class Shoes
4
4
  class Flow < Shoes::Slot
5
5
  include Shoes::Background
6
- include Shoes::Border
7
- include Shoes::Spacing
8
6
 
9
- shoes_styles :width, :height, :margin, :padding
7
+ Shoes::Drawable.drawable_default_styles[Shoes::Flow][:width] = "100%"
8
+
10
9
  shoes_events
11
10
 
12
- def initialize(width: "100%", height: nil, margin: nil, padding: nil, **options, &block)
11
+ def initialize(*args, **kwargs, &block)
13
12
  super
14
- @options = options
15
13
 
16
14
  # Create the display-side drawable *before* instance_eval, which will add child drawables with their display drawables
17
15
  create_display_drawable
@@ -0,0 +1,62 @@
1
+ module FontHelper
2
+
3
+ def parse_font(font)
4
+
5
+ input = font
6
+ regex = /\s+(?=(?:[^']*'[^']*')*[^']*$)(?![^']*,[^']*')/
7
+ result = input.split(regex)
8
+
9
+ fs = nil
10
+ fv = nil
11
+ fw = nil
12
+ fss = nil
13
+ ff = ""
14
+
15
+ fos = ["italic", "oblique"]
16
+ fov = ["small-caps", "initial", "inherit"]
17
+ fow = ["bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"]
18
+ foss = ["xx-small", "x-small", "small","large", "x-large", "xx-large", "smaller", "larger"]
19
+
20
+ result.each do |i|
21
+ if fos.include?(i)
22
+ fs = i
23
+ next
24
+ elsif fov.include?(i)
25
+ fv = i
26
+ next
27
+ elsif fow.include?(i)
28
+ fw = i
29
+ next
30
+ elsif foss.include?(i)
31
+ fss = i
32
+ next
33
+ else
34
+ if contains_number?(i)
35
+
36
+ fss=i;
37
+
38
+ elsif i != "normal" && i != "medium" && i.strip != ""
39
+
40
+ if ff == "Arial"
41
+
42
+ ff = i
43
+
44
+ else
45
+
46
+ ff = ff+" "+i
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ [fs, fv , fw , fss , ff.strip]
55
+ end
56
+
57
+ def contains_number?(str)
58
+
59
+ !!(str =~ /\d/)
60
+
61
+ end
62
+ end
@@ -5,9 +5,9 @@ class Shoes
5
5
  shoes_styles :url, :width, :height, :top, :left, :click
6
6
  shoes_events # No Image-specific events yet
7
7
 
8
- def initialize(url, width: nil, height: nil, top: nil, left: nil, click: nil)
8
+ init_args :url
9
+ def initialize(*args, **kwargs)
9
10
  super
10
- @url = url
11
11
 
12
12
  # Get the image dimensions
13
13
  # @width, @height = size
@@ -5,15 +5,12 @@ class Shoes
5
5
  shoes_styles :left, :top, :x2, :y2, :draw_context
6
6
  shoes_events # No Line-specific events yet
7
7
 
8
- def initialize(left, top, x2, y2)
9
- super
10
-
11
- @left = left
12
- @top = top
13
- @x2 = x2
14
- @y2 = y2
8
+ init_args :left, :top, :x2, :y2
9
+ def initialize(*args, **kwargs)
15
10
  @draw_context = Shoes::App.instance.current_draw_context
16
11
 
12
+ super
13
+
17
14
  create_display_drawable
18
15
  end
19
16
  end
@@ -5,22 +5,19 @@ class Shoes
5
5
  shoes_styles :text, :click, :has_block
6
6
  shoes_events :click
7
7
 
8
- def initialize(text, click: nil, &block)
9
- super
8
+ #Shoes::Drawable.drawable_default_styles[Shoes::Link][:click] = "#"
10
9
 
11
- @text = text
10
+ init_args # Empty by the time it reaches Drawable#initialize
11
+ def initialize(*args, **kwargs, &block)
12
12
  @block = block
13
13
  # We can't send a block to the display drawable, but we can send a boolean
14
14
  @has_block = !block.nil?
15
15
 
16
- # The click property should be changed before it gets sent to the display drawable
17
- @click ||= "#"
16
+ super
18
17
 
19
18
  bind_self_event("click") do
20
19
  @block&.call
21
20
  end
22
-
23
- create_display_drawable
24
21
  end
25
22
  end
26
23
 
@@ -28,7 +25,7 @@ class Shoes
28
25
  # hovered over. The functionality isn't present in Lacci yet.
29
26
  class LinkHover < Link
30
27
  def initialize
31
- raise "This class should never be instantiated! Use link, not link_hover!"
28
+ raise "This class should never be instantiated directly! Use link, not link_hover!"
32
29
  end
33
30
  end
34
31
  end
@@ -11,11 +11,14 @@ class Shoes
11
11
 
12
12
  shoes_events :change
13
13
 
14
- def initialize(**args, &block)
15
- super
16
-
17
- @items = args[:items] || []
18
- @chosen = args[:choose] || args[:items]&.first
14
+ init_args # No positional args
15
+ def initialize(**kwargs, &block)
16
+ # These aren't being set as styles -- remove them from kwargs before calling super
17
+ # TODO: set [] as default value for items?
18
+ @items = kwargs.delete(:items) || []
19
+ @chosen = kwargs.delete(:choose) || @items&.first
20
+
21
+ super(**kwargs, &block)
19
22
 
20
23
  bind_self_event("change") do |new_item|
21
24
  self.chosen = new_item
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Shoes
4
+ # Docs: https://github.com/scarpe-team/scarpe/blob/main/docs/static/manual.md#ovalleft-top-radius--shoesshape
5
+ class Oval < Shoes::Drawable
6
+ shoes_styles :center, :draw_context, :stroke, :fill
7
+
8
+ shoes_style(:left) { |val| convert_to_integer(val, "left") }
9
+ shoes_style(:top) { |val| convert_to_integer(val, "top") }
10
+ shoes_style(:radius) { |val| convert_to_integer(val, "radius") }
11
+ shoes_style(:height) { |val| convert_to_integer(val, "height") }
12
+ shoes_style(:width) { |val| convert_to_integer(val, "width") }
13
+ shoes_style(:strokewidth) { |val| convert_to_integer(val, "strokewidth") }
14
+
15
+ Shoes::Drawable.drawable_default_styles[Shoes::Oval][:fill] = "black"
16
+ Shoes::Drawable.drawable_default_styles[Shoes::Oval][:stroke] = "black"
17
+
18
+ init_args :left, :top
19
+ opt_init_args :radius, :height
20
+ def initialize(*args, **options)
21
+ @draw_context = Shoes::App.instance.current_draw_context
22
+
23
+ super # Parse any positional or keyword args
24
+
25
+ unless @left && @top && (@width || @height || @radius)
26
+ raise Shoes::Errors::InvalidAttributeValueError, "Oval requires left, top and one of (width, height, radius) to be specified!"
27
+ end
28
+
29
+ # Calzini expects "radius" to mean the x-axis-aligned radius, not y-axis-aligned.
30
+ # For an axis-aligned oval the two may be different.
31
+
32
+ # If we have no width, but a radius, default the width to be the radius * 2
33
+ @width ||= @radius * 2 if @radius
34
+
35
+ # We now know we have width or height, but maybe not both.
36
+
37
+ # Default to a circle - set height from width or vice-versa
38
+ @width ||= @height
39
+ @height ||= @width
40
+
41
+ # If we don't have radius yet, set it from width
42
+ @radius ||= @width / 2
43
+
44
+ create_display_drawable
45
+ end
46
+
47
+ end
48
+ end
@@ -1,24 +1,34 @@
1
1
  # frozen_string_literal: true
2
-
2
+ require_relative 'font_helper.rb'
3
3
  class Shoes
4
- class Para < Shoes::Drawable
5
- shoes_styles :text_items, :size, :font, :html_attributes, :hidden
6
- shoes_style(:stroke) { |val| Shoes::Colors.to_rgb(val) }
4
+ class Para < Shoes::Drawable
5
+ include FontHelper
6
+ shoes_styles :text_items, :size, :family, :font_weight, :font, :font_variant, :emphasis, :kerning
7
+ shoes_style(:stroke) { |val, _name| Shoes::Colors.to_rgb(val) }
8
+ shoes_style(:fill) { |val, _name| Shoes::Colors.to_rgb(val) }
9
+
10
+ shoes_style(:align) do |val|
11
+ unless ["left", "center", "right"].include?(val)
12
+ raise(Shoes::Errors::InvalidAttributeValueError, "Align must be one of left, center or right!")
13
+ end
14
+ val
15
+ end
16
+
17
+ Shoes::Drawable.drawable_default_styles[Shoes::Para][:size] = :para
7
18
 
8
19
  shoes_events # No Para-specific events yet
9
20
 
10
- # Initializes a new instance of the `Para` widget.
21
+ # Initializes a new instance of the `Para` drawable. There are different
22
+ # methods to instantiate slightly different styles of Para, such as
23
+ # `tagline`, `caption` and `subtitle`. These will always be different
24
+ # sizes, but may be generally styled differently for some display services.
11
25
  #
12
26
  # @param args The text content of the paragraph.
13
- # @param stroke [String, nil] The color of the text stroke.
14
- # @param size [Symbol] The size of the paragraph text.
15
- # @param font [String, nil] The font of the paragraph text.
16
- # @param hidden [Boolean] Determines if the paragraph is initially hidden.
17
- # @param html_attributes [Hash] Additional HTML attributes for the paragraph.
27
+ # @param kwargs [Hash] the various Shoes styles for this paragraph.
18
28
  #
19
29
  # @example
20
30
  # Shoes.app do
21
- # p = para "Hello, This is at the top!", stroke: "red", size: :title, font: "Arial"
31
+ # p = para "Hello, This is at the top!", stroke: red, size: :title, font: "Arial"
22
32
  #
23
33
  # banner("Welcome to Shoes!")
24
34
  # title("Shoes Examples")
@@ -29,22 +39,60 @@ class Shoes
29
39
  #
30
40
  # p.replace "On top we'll switch to ", strong("bold"), "!"
31
41
  # end
32
- def initialize(*args, stroke: nil, size: :para, font: nil, **html_attributes)
33
- super
42
+
43
+ def initialize(*args, **kwargs)
44
+
45
+ if kwargs[:font]
46
+ arr= parse_font(kwargs[:font])
47
+
48
+ if arr[0] != nil
49
+
50
+ kwargs[:emphasis] = arr[0]
51
+
52
+ end
53
+
54
+ if arr[1] != nil
55
+
56
+ kwargs[:font_variant] = arr[1]
57
+
58
+ end
59
+
60
+ if arr[2] != nil
61
+
62
+ kwargs[:font_weight] = arr[2]
63
+
64
+ end
65
+
66
+ if arr[3] != nil
67
+
68
+ kwargs[:size] = arr[3]
69
+
70
+ end
34
71
 
72
+ if arr[4] != ""
73
+
74
+ kwargs[:family] = arr[4]
75
+
76
+ end
77
+
78
+ end
79
+
80
+ # Don't pass text_children args to Drawable#initialize
81
+ super(*[], **kwargs)
82
+
35
83
  # Text_children alternates strings and TextDrawables, so we can't just pass
36
84
  # it as a Shoes style. It won't serialize.
37
85
  update_text_children(args)
38
86
 
39
- @html_attributes = html_attributes || {}
40
-
41
87
  create_display_drawable
42
88
  end
43
89
 
90
+
91
+
44
92
  private
45
93
 
46
94
  def text_children_to_items(text_children)
47
- text_children.map { |arg| arg.is_a?(String) ? arg : arg.linkable_id }
95
+ text_children.map { |arg| arg.is_a?(TextDrawable) ? arg.linkable_id : arg.to_s }
48
96
  end
49
97
 
50
98
  public
@@ -67,10 +115,20 @@ class Shoes
67
115
  update_text_children(children)
68
116
  end
69
117
 
118
+ # Return the text, but not the styling, of the para's
119
+ # contents. For example, if the contents had strong
120
+ # and emphasized text, the bold and emphasized would
121
+ # be removed but the text would be returned.
122
+ #
123
+ # @return [String] the text from this para
70
124
  def text
71
125
  @text_children.map(&:to_s).join
72
126
  end
73
127
 
128
+ # Return the text but not styling from the para. This
129
+ # is the same as #text.
130
+ #
131
+ # @return [String] the text from this para
74
132
  def to_s
75
133
  self.text
76
134
  end
@@ -84,35 +142,65 @@ class Shoes
84
142
  # This should signal the display drawable to change
85
143
  self.text_items = text_children_to_items(@text_children)
86
144
  end
145
+
146
+
87
147
  end
88
148
  end
89
149
 
90
150
  class Shoes
91
151
  class Drawable
152
+ # Return a banner-sized para. This can use all the normal
153
+ # Para styles and arguments. See {Para#initialize} for
154
+ # details.
155
+ #
156
+ # @return [Shoes::Para] the new para drawable
92
157
  def banner(*args, **kwargs)
93
158
  para(*args, **{ size: :banner }.merge(kwargs))
94
159
  end
95
160
 
161
+ # Return a title-sized para. This can use all the normal
162
+ # Para styles and arguments. See {Para#initialize} for
163
+ # details.
164
+ #
165
+ # @return [Shoes::Para] the new para drawable
96
166
  def title(*args, **kwargs)
97
167
  para(*args, **{ size: :title }.merge(kwargs))
98
168
  end
99
169
 
170
+ # Return a subtitle-sized para. This can use all the normal
171
+ # Para styles and arguments. See {Para#initialize} for
172
+ # details.
173
+ #
174
+ # @return [Shoes::Para] the new para drawable
100
175
  def subtitle(*args, **kwargs)
101
176
  para(*args, **{ size: :subtitle }.merge(kwargs))
102
177
  end
103
178
 
179
+ # Return a tagline-sized para. This can use all the normal
180
+ # Para styles and arguments. See {Para#initialize} for
181
+ # details.
182
+ #
183
+ # @return [Shoes::Para] the new para drawable
104
184
  def tagline(*args, **kwargs)
105
185
  para(*args, **{ size: :tagline }.merge(kwargs))
106
186
  end
107
187
 
188
+ # Return a caption-sized para. This can use all the normal
189
+ # Para styles and arguments. See {Para#initialize} for
190
+ # details.
191
+ #
192
+ # @return [Shoes::Para] the new para drawable
108
193
  def caption(*args, **kwargs)
109
194
  para(*args, **{ size: :caption }.merge(kwargs))
110
195
  end
111
196
 
197
+ # Return an inscription-sized para. This can use all the normal
198
+ # Para styles and arguments. See {Para#initialize} for
199
+ # details.
200
+ #
201
+ # @return [Shoes::Para] the new para drawable
112
202
  def inscription(*args, **kwargs)
113
203
  para(*args, **{ size: :inscription }.merge(kwargs))
114
204
  end
115
-
116
- alias_method :ins, :inscription
117
205
  end
118
206
  end
@@ -5,7 +5,8 @@ class Shoes
5
5
  shoes_styles :fraction
6
6
  shoes_events # No Progress-specific events yet
7
7
 
8
- def initialize(fraction: nil)
8
+ init_args # No positional args
9
+ def initialize(**kwargs)
9
10
  super
10
11
 
11
12
  create_display_drawable
@@ -8,11 +8,13 @@ class Shoes
8
8
  shoes_styles :group, :checked
9
9
  shoes_events :click
10
10
 
11
- def initialize(group = nil, checked: nil, &block)
12
- super
13
- @group = group
11
+ init_args
12
+ opt_init_args :group
13
+ def initialize(*args, **kwargs, &block)
14
14
  @block = block
15
15
 
16
+ super
17
+
16
18
  bind_self_event("click") { click }
17
19
  create_display_drawable
18
20
  end
@@ -2,14 +2,15 @@
2
2
 
3
3
  class Shoes
4
4
  class Rect < Shoes::Drawable
5
- shoes_styles :left, :top, :width, :height, :draw_context, :curve
6
- shoes_events # No Rect-specific events yet
5
+ shoes_styles :draw_context, :curve, :stroke, :fill
6
+ shoes_events # No Rect-specific events
7
7
 
8
- def initialize(*args)
8
+ init_args :left, :top, :width, :height
9
+ opt_init_args :curve
10
+ def initialize(*args, **kwargs)
9
11
  @draw_context = Shoes::App.instance.current_draw_context
10
12
 
11
13
  super
12
- self.left, self.top, self.width, self.height, self.curve = args
13
14
 
14
15
  create_display_drawable
15
16
  end
@@ -13,7 +13,8 @@ class Shoes
13
13
  shoes_styles :left, :top, :shape_commands, :draw_context
14
14
  shoes_events # No Shape-specific events yet
15
15
 
16
- def initialize(left: nil, top: nil, &block)
16
+ init_args # No positional args
17
+ def initialize(**kwargs, &block)
17
18
  @shape_commands = []
18
19
  @draw_context = Shoes::App.instance.current_draw_context
19
20
 
@@ -1,10 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Shoes::Slot < Shoes::Drawable
4
- # @incompatibility Shoes uses #content, not #children, for this
4
+ # @incompatibility Shoes uses #content, not #children, for this. Scarpe does both.
5
5
  attr_reader :children
6
6
 
7
- shoes_events # No Slot-specific events yet
7
+ shoes_events # No Slot-specific events
8
+
9
+ # This only shows this specific slot's settings, not its parent's.
10
+ # Use current_draw_context to allow inheritance.
11
+ attr_reader :draw_context
12
+
13
+
14
+ def initialize(...)
15
+ # The draw context tracks current settings like fill and stroke,
16
+ # plus potentially other current state that changes from drawable
17
+ # to drawable and slot to slot.
18
+ @draw_context = {
19
+ "fill" => nil,
20
+ "stroke" => nil,
21
+ "strokewidth" => nil,
22
+ "rotate" => nil,
23
+ # "transform" => nil, # "corner",
24
+ # "translate" => nil, # [0, 0],
25
+ }
26
+
27
+ super
28
+ end
8
29
 
9
30
  # Do not call directly, use set_parent
10
31
  def remove_child(child)
@@ -29,30 +50,99 @@ class Shoes::Slot < Shoes::Drawable
29
50
 
30
51
  # We use method_missing for drawable-creating methods like "button".
31
52
  # The parent's method_missing will auto-create Shoes style getters and setters.
53
+ # This is similar to the method_missing in Shoes::App, but differs in where
54
+ # the new drawable will appear.
32
55
  def method_missing(name, *args, **kwargs, &block)
33
56
  klass = ::Shoes::Drawable.drawable_class_by_name(name)
34
57
  return super unless klass
35
58
 
36
59
  ::Shoes::Slot.define_method(name) do |*args, **kwargs, &block|
37
- # Look up the Shoes drawable and create it...
38
- drawable_instance = klass.new(*args, **kwargs, &block)
60
+ instance = nil
39
61
 
40
- unless klass.ancestors.include?(::Shoes::TextDrawable)
41
- drawable_instance.set_parent self # Create drawable in THIS SLOT, not current app slot
62
+ # Look up the Shoes drawable and create it. But first set
63
+ # this slot as the current one so that draw context
64
+ # is handled properly.
65
+ Shoes::App.instance.with_slot(self) do
66
+ instance = klass.new(*args, **kwargs, &block)
42
67
  end
43
68
 
44
- drawable_instance
69
+ instance
45
70
  end
46
71
 
47
72
  send(name, *args, **kwargs, &block)
48
73
  end
49
74
 
50
75
  def respond_to_missing?(name, include_private = false)
51
- return true if Drawable.drawable_class_by_name(name.to_s)
76
+ return true if ::Shoes::Drawable.drawable_class_by_name(name.to_s)
52
77
 
53
78
  false
54
79
  end
55
80
 
81
+ # Draw context methods
82
+
83
+ # Set the default fill color in this slot and child slots.
84
+ # Pass nil for "no setting", so that it can inherit defaults.
85
+ #
86
+ # @param color [Nil,Color] a Shoes color for the fill color or nil to use parent setting
87
+ # @return [void]
88
+ def fill(color)
89
+ @draw_context["fill"] = color
90
+ end
91
+
92
+ # Set the default fill in this slot and child slots to transparent.
93
+ #
94
+ # @return [void]
95
+ def nofill
96
+ @draw_context["fill"] = rgb(0, 0, 0, 0)
97
+ end
98
+
99
+ # Set the default stroke color in this slot and child slots.
100
+ # Pass nil for "no setting" so it can inherit defaults.
101
+ #
102
+ # @param color [Nil,Color] a Shoes color for the stroke color or nil to use parent setting
103
+ # @return [void]
104
+ def stroke(color)
105
+ @draw_context["stroke"] = color
106
+ end
107
+
108
+ # Set the default strokewidth in this slot and child slots.
109
+ # Pass nil for "no setting".
110
+ #
111
+ # @param width [Numeric,Nil] the new width, or nil to use parent setting
112
+ # @return [void]
113
+ def strokewidth(width)
114
+ @draw_context["strokewidth"] = width
115
+ end
116
+
117
+ # Set the default stroke in this slot and child slots
118
+ # to transparent.
119
+ #
120
+ # @return [void]
121
+ def nostroke
122
+ @draw_context["stroke"] = rgb(0, 0, 0, 0)
123
+ end
124
+
125
+ # Set the current rotation in this slot and any child slots.
126
+ # Pass nil to reset the angle to default.
127
+ #
128
+ # @param angle [Numeric,Nil] the new default rotation for shapes or nil to use parent setting
129
+ # @return [void]
130
+ def rotate(angle)
131
+ @draw_context["rotate"] = angle
132
+ end
133
+
134
+ # Get the current draw context styles, based on this slot and its parent slots.
135
+ #
136
+ # @return [Hash] a hash of Shoes styles for the context
137
+ def current_draw_context
138
+ s = @parent ? @parent.current_draw_context : {}
139
+ @draw_context.each { |k, v| s[k] = v unless v.nil? }
140
+
141
+ s
142
+ end
143
+
144
+ # Methods to add or remove children
145
+
56
146
  # Remove all children from this drawable. If a block
57
147
  # is given, call the block to replace the children with
58
148
  # new contents from that block.
@@ -65,6 +155,7 @@ class Shoes::Slot < Shoes::Drawable
65
155
  # @yield The block to call to replace the contents of the drawable (optional)
66
156
  # @return [void]
67
157
  def clear(&block)
158
+ @children ||= []
68
159
  @children.dup.each(&:destroy)
69
160
  append(&block) if block_given?
70
161
  nil