lacci 0.2.2 → 0.3.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.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +8 -1
- data/lib/lacci/scarpe_cli.rb +2 -1
- data/lib/lacci/scarpe_core.rb +2 -1
- data/lib/lacci/version.rb +1 -1
- data/lib/scarpe/niente/app.rb +23 -0
- data/lib/scarpe/niente/display_service.rb +62 -0
- data/lib/scarpe/niente/drawable.rb +57 -0
- data/lib/scarpe/niente/logger.rb +29 -0
- data/lib/scarpe/niente/shoes_spec.rb +87 -0
- data/lib/scarpe/niente.rb +20 -0
- data/lib/shoes/app.rb +88 -43
- data/lib/shoes/background.rb +2 -2
- data/lib/shoes/border.rb +2 -2
- data/lib/shoes/builtins.rb +63 -0
- data/lib/shoes/changelog.rb +52 -0
- data/lib/shoes/colors.rb +3 -1
- data/lib/shoes/constants.rb +19 -1
- data/lib/shoes/display_service.rb +39 -16
- data/lib/shoes/download.rb +2 -2
- data/lib/shoes/drawable.rb +380 -0
- data/lib/shoes/drawables/arc.rb +49 -0
- data/lib/shoes/drawables/arrow.rb +41 -0
- data/lib/shoes/drawables/button.rb +73 -0
- data/lib/shoes/{widgets → drawables}/check.rb +5 -4
- data/lib/shoes/{widgets → drawables}/document_root.rb +3 -3
- data/lib/shoes/{widgets → drawables}/edit_box.rb +6 -6
- data/lib/shoes/{widgets → drawables}/edit_line.rb +6 -6
- data/lib/shoes/{widgets → drawables}/flow.rb +6 -6
- data/lib/shoes/{widgets → drawables}/image.rb +6 -6
- data/lib/shoes/{widgets → drawables}/line.rb +7 -5
- data/lib/shoes/drawables/link.rb +34 -0
- data/lib/shoes/drawables/list_box.rb +56 -0
- data/lib/shoes/drawables/para.rb +118 -0
- data/lib/shoes/drawables/progress.rb +14 -0
- data/lib/shoes/drawables/radio.rb +33 -0
- data/lib/shoes/drawables/rect.rb +17 -0
- data/lib/shoes/{widgets → drawables}/shape.rb +6 -7
- data/lib/shoes/{widgets → drawables}/slot.rb +32 -20
- data/lib/shoes/{widgets → drawables}/span.rb +8 -7
- data/lib/shoes/{widgets → drawables}/stack.rb +6 -4
- data/lib/shoes/drawables/star.rb +50 -0
- data/lib/shoes/drawables/subscription_item.rb +93 -0
- data/lib/shoes/drawables/text_drawable.rb +63 -0
- data/lib/shoes/drawables/video.rb +16 -0
- data/lib/shoes/drawables/widget.rb +69 -0
- data/lib/shoes/drawables.rb +31 -0
- data/lib/shoes/errors.rb +28 -0
- data/lib/shoes/log.rb +2 -2
- data/lib/shoes/ruby_extensions.rb +15 -0
- data/lib/shoes/spacing.rb +2 -2
- data/lib/shoes-spec.rb +93 -0
- data/lib/shoes.rb +27 -7
- metadata +55 -28
- data/lib/shoes/widget.rb +0 -218
- data/lib/shoes/widgets/alert.rb +0 -19
- data/lib/shoes/widgets/arc.rb +0 -51
- data/lib/shoes/widgets/button.rb +0 -35
- data/lib/shoes/widgets/font.rb +0 -14
- data/lib/shoes/widgets/link.rb +0 -25
- data/lib/shoes/widgets/list_box.rb +0 -25
- data/lib/shoes/widgets/para.rb +0 -68
- data/lib/shoes/widgets/radio.rb +0 -35
- data/lib/shoes/widgets/star.rb +0 -44
- data/lib/shoes/widgets/subscription_item.rb +0 -60
- data/lib/shoes/widgets/text_widget.rb +0 -51
- data/lib/shoes/widgets/video.rb +0 -15
- data/lib/shoes/widgets.rb +0 -29
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class Shoes::Slot < Shoes::
|
3
|
+
class Shoes::Slot < Shoes::Drawable
|
4
4
|
# @incompatibility Shoes uses #content, not #children, for this
|
5
5
|
attr_reader :children
|
6
6
|
|
7
|
+
shoes_events # No Slot-specific events yet
|
8
|
+
|
7
9
|
# Do not call directly, use set_parent
|
8
10
|
def remove_child(child)
|
9
11
|
@children ||= []
|
@@ -19,29 +21,39 @@ class Shoes::Slot < Shoes::Widget
|
|
19
21
|
@children << child
|
20
22
|
end
|
21
23
|
|
22
|
-
# Get a list of child
|
24
|
+
# Get a list of child drawables
|
23
25
|
def contents
|
24
26
|
@children ||= []
|
25
27
|
@children.dup
|
26
28
|
end
|
27
29
|
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
# We use method_missing for drawable-creating methods like "button".
|
31
|
+
# The parent's method_missing will auto-create Shoes style getters and setters.
|
32
|
+
def method_missing(name, *args, **kwargs, &block)
|
33
|
+
klass = ::Shoes::Drawable.drawable_class_by_name(name)
|
34
|
+
return super unless klass
|
35
|
+
|
36
|
+
::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)
|
39
|
+
|
40
|
+
unless klass.ancestors.include?(::Shoes::TextDrawable)
|
41
|
+
drawable_instance.set_parent self # Create drawable in THIS SLOT, not current app slot
|
42
|
+
end
|
43
|
+
|
44
|
+
drawable_instance
|
45
|
+
end
|
46
|
+
|
47
|
+
send(name, *args, **kwargs, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def respond_to_missing?(name, include_private = false)
|
51
|
+
return true if Drawable.drawable_class_by_name(name.to_s)
|
52
|
+
|
53
|
+
false
|
42
54
|
end
|
43
55
|
|
44
|
-
# Remove all children from this
|
56
|
+
# Remove all children from this drawable. If a block
|
45
57
|
# is given, call the block to replace the children with
|
46
58
|
# new contents from that block.
|
47
59
|
#
|
@@ -50,7 +62,7 @@ class Shoes::Slot < Shoes::Widget
|
|
50
62
|
#
|
51
63
|
# @incompatibility Shoes Classic calls the clear block with current self, while Scarpe uses the Shoes::App as self
|
52
64
|
#
|
53
|
-
# @yield The block to call to replace the contents of the
|
65
|
+
# @yield The block to call to replace the contents of the drawable (optional)
|
54
66
|
# @return [void]
|
55
67
|
def clear(&block)
|
56
68
|
@children.dup.each(&:destroy)
|
@@ -67,8 +79,8 @@ class Shoes::Slot < Shoes::Widget
|
|
67
79
|
# @yield the block to call to replace children; will be called on the Shoes::App, appending to the called Slot as the current slot
|
68
80
|
# @return [void]
|
69
81
|
def append(&block)
|
70
|
-
raise("append requires a block!") unless block_given?
|
71
|
-
raise("Don't append to something that isn't a slot!") unless self.is_a?(Shoes::Slot)
|
82
|
+
raise(Shoes::Errors::InvalidAttributeValueError, "append requires a block!") unless block_given?
|
83
|
+
raise(Shoes::Errors::InvalidAttributeValueError, "Don't append to something that isn't a slot!") unless self.is_a?(Shoes::Slot)
|
72
84
|
|
73
85
|
Shoes::App.instance.with_slot(self, &block)
|
74
86
|
end
|
@@ -1,25 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class Span < Shoes::
|
5
|
-
|
3
|
+
class Shoes
|
4
|
+
class Span < Shoes::Drawable
|
5
|
+
shoes_styles :text, :stroke, :size, :font, :html_attributes
|
6
|
+
shoes_events # No Span-specific events yet
|
6
7
|
|
7
8
|
def initialize(text, stroke: nil, size: :span, font: nil, **html_attributes)
|
9
|
+
super
|
10
|
+
|
8
11
|
@text = text
|
9
12
|
@stroke = stroke
|
10
13
|
@size = size
|
11
14
|
@font = font
|
12
15
|
@html_attributes = html_attributes
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
create_display_widget
|
17
|
+
create_display_drawable
|
17
18
|
end
|
18
19
|
|
19
20
|
def replace(text)
|
20
21
|
@text = text
|
21
22
|
|
22
|
-
# This should signal the display
|
23
|
+
# This should signal the display drawable to change
|
23
24
|
self.text = @text
|
24
25
|
end
|
25
26
|
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
class Shoes
|
4
4
|
class Stack < Shoes::Slot
|
5
5
|
include Shoes::Background
|
6
6
|
include Shoes::Border
|
7
7
|
include Shoes::Spacing
|
8
8
|
|
9
9
|
# TODO: sort out various margin and padding properties, including putting stuff into spacing
|
10
|
-
|
10
|
+
shoes_styles :width, :height, :scroll
|
11
|
+
|
12
|
+
shoes_events # No Stack-specific events yet
|
11
13
|
|
12
14
|
def initialize(width: nil, height: nil, margin: nil, padding: nil, scroll: false, margin_top: nil, margin_bottom: nil, margin_left: nil,
|
13
15
|
margin_right: nil, **options, &block)
|
@@ -16,8 +18,8 @@ module Shoes
|
|
16
18
|
|
17
19
|
super
|
18
20
|
|
19
|
-
|
20
|
-
# Create the display-side
|
21
|
+
create_display_drawable
|
22
|
+
# Create the display-side drawable *before* running the block, which will add child drawables with their display drawables
|
21
23
|
Shoes::App.instance.with_slot(self, &block) if block_given?
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shoes
|
4
|
+
class Star < Shoes::Drawable
|
5
|
+
shoes_styles :left, :top, :draw_context
|
6
|
+
|
7
|
+
shoes_style(:points) { |val| convert_to_integer(val, "points") }
|
8
|
+
shoes_style(:outer) { |val| convert_to_float(val, "outer") }
|
9
|
+
shoes_style(:inner) { |val| convert_to_float(val, "inner") }
|
10
|
+
|
11
|
+
shoes_events # No Star-specific events yet
|
12
|
+
|
13
|
+
def initialize(left, top, points = 10, outer = 100, inner = 50)
|
14
|
+
super
|
15
|
+
self.left = left
|
16
|
+
self.top = top
|
17
|
+
self.points = points
|
18
|
+
self.outer = outer
|
19
|
+
self.inner = inner
|
20
|
+
|
21
|
+
@draw_context = Shoes::App.instance.current_draw_context
|
22
|
+
|
23
|
+
create_display_drawable
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.convert_to_integer(value, attribute_name)
|
27
|
+
begin
|
28
|
+
value = Integer(value)
|
29
|
+
raise Shoes::Errors::InvalidAttributeValueError, "Negative num '#{value}' not allowed for attribute '#{attribute_name}'" if value < 0
|
30
|
+
|
31
|
+
value
|
32
|
+
rescue ArgumentError
|
33
|
+
error_message = "Invalid value '#{value}' provided for attribute '#{attribute_name}'. The value should be a number."
|
34
|
+
raise Shoes::Errors::InvalidAttributeValueError, error_message
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.convert_to_float(value, attribute_name)
|
39
|
+
begin
|
40
|
+
value = Float(value)
|
41
|
+
raise Shoes::Errors::InvalidAttributeValueError, "Negative num '#{value}' not allowed for attribute '#{attribute_name}'" if value < 0
|
42
|
+
|
43
|
+
value
|
44
|
+
rescue ArgumentError
|
45
|
+
error_message = "Invalid value '#{value}' provided for attribute '#{attribute_name}'. The value should be a number."
|
46
|
+
raise Shoes::Errors::InvalidAttributeValueError, error_message
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Certain Shoes calls like motion and keydown are basically an
|
4
|
+
# event subscription, with no other visible presence. However,
|
5
|
+
# they have a place in the drawable tree and can be deleted.
|
6
|
+
#
|
7
|
+
# Depending on the display library they may not have any
|
8
|
+
# direct visual (or similar) presence there either.
|
9
|
+
#
|
10
|
+
# Inheriting from Drawable gives these a parent slot and a
|
11
|
+
# linkable_id automatically.
|
12
|
+
#
|
13
|
+
# Events not yet implemented: start, finish events for slots -
|
14
|
+
# start is first draw, finish is drawable destroyed
|
15
|
+
class Shoes::SubscriptionItem < Shoes::Drawable
|
16
|
+
shoes_styles :shoes_api_name, :args
|
17
|
+
shoes_events :animate, :every, :timer, :hover, :leave, :motion, :click, :release, :keypress
|
18
|
+
|
19
|
+
def initialize(args: [], shoes_api_name:, &block)
|
20
|
+
super
|
21
|
+
|
22
|
+
@callback = block
|
23
|
+
|
24
|
+
case shoes_api_name
|
25
|
+
when "animate"
|
26
|
+
@unsub_id = bind_self_event("animate") do |frame|
|
27
|
+
@callback.call(frame)
|
28
|
+
end
|
29
|
+
when "every"
|
30
|
+
@unsub_id = bind_self_event("every") do |count|
|
31
|
+
@callback.call(count)
|
32
|
+
end
|
33
|
+
when "timer"
|
34
|
+
@unsub_id = bind_self_event("timer") do
|
35
|
+
@callback.call
|
36
|
+
end
|
37
|
+
when "hover"
|
38
|
+
# Hover passes the Shoes drawable as the block param
|
39
|
+
@unsub_id = bind_self_event("hover") do
|
40
|
+
@callback&.call(self)
|
41
|
+
end
|
42
|
+
when "leave"
|
43
|
+
# Leave passes the Shoes drawable as the block param
|
44
|
+
@unsub_id = bind_self_event("leave") do
|
45
|
+
@callback&.call(self)
|
46
|
+
end
|
47
|
+
when "motion"
|
48
|
+
# Shoes sends back x, y, mods as the args.
|
49
|
+
# Shoes3 uses the strings "control" "shift" and
|
50
|
+
# "control_shift" as the mods arg.
|
51
|
+
@unsub_id = bind_self_event("motion") do |x, y, ctrl_key, shift_key, **_kwargs|
|
52
|
+
mods = [ctrl_key ? "control" : nil, shift_key ? "shift" : nil].compact.join("_")
|
53
|
+
@callback&.call(x, y, mods)
|
54
|
+
end
|
55
|
+
when "click"
|
56
|
+
# Click has block params button, left, top
|
57
|
+
# button is the button number, left and top are coords
|
58
|
+
@unsub_id = bind_self_event("click") do |button, x, y, **_kwargs|
|
59
|
+
@callback&.call(button, x, y)
|
60
|
+
end
|
61
|
+
when "release"
|
62
|
+
# Click has block params button, left, top
|
63
|
+
# button is the button number, left and top are coords
|
64
|
+
@unsub_id = bind_self_event("release") do |button, x, y, **_kwargs|
|
65
|
+
@callback&.call(button, x, y)
|
66
|
+
end
|
67
|
+
when "keypress"
|
68
|
+
# Keypress passes the key string or symbol to the handler
|
69
|
+
# Do anything special for serialisation here?
|
70
|
+
@unsub_id = bind_self_event("keypress") do |key|
|
71
|
+
@callback&.call(key)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise "Unknown Shoes event #{shoes_api_name.inspect} passed to SubscriptionItem!"
|
75
|
+
end
|
76
|
+
|
77
|
+
@unsub_id = bind_self_event(shoes_api_name) do |*args|
|
78
|
+
@callback&.call(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
# This won't create a visible display drawable, but will turn into
|
82
|
+
# an invisible drawable and a stream of events.
|
83
|
+
create_display_drawable
|
84
|
+
end
|
85
|
+
|
86
|
+
def destroy
|
87
|
+
# TODO: we need a better way to do this automatically. See https://github.com/scarpe-team/scarpe/issues/291
|
88
|
+
unsub_shoes_event(@unsub_id) if @unsub_id
|
89
|
+
@unsub_id = nil
|
90
|
+
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shoes
|
4
|
+
# TextDrawable is the parent class of various classes of
|
5
|
+
# text that can go inside a para. This includes normal
|
6
|
+
# text, but also links, italic text, bold text, etc.
|
7
|
+
class TextDrawable < Shoes::Drawable
|
8
|
+
class << self
|
9
|
+
# rubocop:disable Lint/MissingSuper
|
10
|
+
def inherited(subclass)
|
11
|
+
Shoes::Drawable.drawable_classes ||= []
|
12
|
+
Shoes::Drawable.drawable_classes << subclass
|
13
|
+
|
14
|
+
Shoes::Drawable.drawable_default_styles ||= {}
|
15
|
+
Shoes::Drawable.drawable_default_styles[subclass] = {}
|
16
|
+
end
|
17
|
+
# rubocop:enable Lint/MissingSuper
|
18
|
+
end
|
19
|
+
|
20
|
+
shoes_events # No TextDrawable-specific events yet
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def default_text_drawable_with(element)
|
25
|
+
class_name = element.capitalize
|
26
|
+
|
27
|
+
drawable_class = Class.new(Shoes::TextDrawable) do
|
28
|
+
# Can we just change content to text to match the Shoes API?
|
29
|
+
shoes_style :content
|
30
|
+
|
31
|
+
def initialize(content)
|
32
|
+
super
|
33
|
+
|
34
|
+
@content = content
|
35
|
+
|
36
|
+
create_display_drawable
|
37
|
+
end
|
38
|
+
|
39
|
+
def text
|
40
|
+
self.content
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
self.content
|
45
|
+
end
|
46
|
+
|
47
|
+
def text=(new_text)
|
48
|
+
self.content = new_text
|
49
|
+
end
|
50
|
+
end
|
51
|
+
Shoes.const_set class_name, drawable_class
|
52
|
+
drawable_class.class_eval do
|
53
|
+
shoes_style :content
|
54
|
+
|
55
|
+
shoes_events # No specific events
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Shoes.default_text_drawable_with(:code)
|
62
|
+
Shoes.default_text_drawable_with(:em)
|
63
|
+
Shoes.default_text_drawable_with(:strong)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shoes
|
4
|
+
class Video < Shoes::Drawable
|
5
|
+
shoes_styles :url
|
6
|
+
shoes_events # No specific events yet
|
7
|
+
|
8
|
+
def initialize(url)
|
9
|
+
super
|
10
|
+
@url = url
|
11
|
+
create_display_drawable
|
12
|
+
end
|
13
|
+
|
14
|
+
# other methods
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A Shoes::Widget is mostly a Slot (related to the
|
4
|
+
# old Shoes concepts of Canvas) that creates drawables
|
5
|
+
# inside itself. When a subclass of Widget is created,
|
6
|
+
# it adds a method to create new objects of that type
|
7
|
+
# on Shoes::App and all Shoes slots.
|
8
|
+
#
|
9
|
+
# The hardest part with a Shoes::Widget is that it
|
10
|
+
# should work fine even if initialize() doesn't call
|
11
|
+
# super, which would make it hard to set up a Shoes
|
12
|
+
# linkable_id, create a display widget, etc.
|
13
|
+
#
|
14
|
+
# It would be possible to add an extra method to set
|
15
|
+
# these up and call it on every created drawable
|
16
|
+
# in case a Widget's initialize method doesn't call
|
17
|
+
# super, which happens quite often. But then we wouldn't
|
18
|
+
# support automatic setting of styles (e.g. padding)
|
19
|
+
# for the widget object itself, which is mostly a Flow.
|
20
|
+
# We also couldn't support default styles -- I can't tell
|
21
|
+
# whether Shoes supports these things either.
|
22
|
+
#
|
23
|
+
# But there's another way to do all of this. When a
|
24
|
+
# subclass of Widget defines an initialize method,
|
25
|
+
# we can catch the method_added hook, save a copy of
|
26
|
+
# that initialize method, and substitute our own
|
27
|
+
# initialize that calls super. We have to be a little
|
28
|
+
# careful -- if the widget's initialize *does* call
|
29
|
+
# super that shouldn't be an error. But that's
|
30
|
+
# workable by defining an extra method with the
|
31
|
+
# copied-method name that does nothing.
|
32
|
+
|
33
|
+
##### TODO: when this is subclassed, grab :initialize out
|
34
|
+
# of the subclass, put it into :initialize_widget, and
|
35
|
+
# replace with an initialize that creates the display
|
36
|
+
# widget propertly, sets the linkable_id, etc.
|
37
|
+
|
38
|
+
class Shoes::Widget < Shoes::Slot
|
39
|
+
include Shoes::Background
|
40
|
+
include Shoes::Border
|
41
|
+
include Shoes::Spacing
|
42
|
+
|
43
|
+
shoes_events
|
44
|
+
|
45
|
+
def self.method_added(name)
|
46
|
+
# We're only looking for the initialize() method, and only on subclasses
|
47
|
+
# of Shoes::Widget, not Shoes::Widget itself.
|
48
|
+
return if self == ::Shoes::Widget || name != :initialize
|
49
|
+
|
50
|
+
# Need to avoid infinite adding of initialize() if we're re-adding the default initialize
|
51
|
+
return if @midway_through_adding_initialize
|
52
|
+
|
53
|
+
# Take the user-provided initialize method and save a copy named __widget_initialize
|
54
|
+
alias_method :__widget_initialize, :initialize
|
55
|
+
|
56
|
+
# And add the default initialize back where it belongs
|
57
|
+
@midway_through_adding_initialize = true
|
58
|
+
define_method(:initialize) do |*args, **kwargs, &block|
|
59
|
+
super(*args, **kwargs, &block)
|
60
|
+
@options = kwargs
|
61
|
+
create_display_drawable
|
62
|
+
__widget_initialize(*args, **kwargs, &block)
|
63
|
+
|
64
|
+
# Do Widgets do this?
|
65
|
+
Shoes::App.instance.with_slot(self, &block) if block
|
66
|
+
end
|
67
|
+
@midway_through_adding_initialize = false
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shoes/drawables/slot"
|
4
|
+
require "shoes/drawables/stack"
|
5
|
+
require "shoes/drawables/flow"
|
6
|
+
require "shoes/drawables/widget"
|
7
|
+
require "shoes/drawables/document_root"
|
8
|
+
|
9
|
+
require "shoes/drawables/text_drawable"
|
10
|
+
|
11
|
+
require "shoes/drawables/subscription_item"
|
12
|
+
|
13
|
+
require "shoes/drawables/arc"
|
14
|
+
require "shoes/drawables/line"
|
15
|
+
require "shoes/drawables/rect"
|
16
|
+
require "shoes/drawables/shape"
|
17
|
+
require "shoes/drawables/star"
|
18
|
+
require "shoes/drawables/arrow"
|
19
|
+
|
20
|
+
require "shoes/drawables/button"
|
21
|
+
require "shoes/drawables/check"
|
22
|
+
require "shoes/drawables/edit_box"
|
23
|
+
require "shoes/drawables/edit_line"
|
24
|
+
require "shoes/drawables/image"
|
25
|
+
require "shoes/drawables/link"
|
26
|
+
require "shoes/drawables/list_box"
|
27
|
+
require "shoes/drawables/para"
|
28
|
+
require "shoes/drawables/radio"
|
29
|
+
require "shoes/drawables/span"
|
30
|
+
require "shoes/drawables/video"
|
31
|
+
require "shoes/drawables/progress"
|
data/lib/shoes/errors.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shoes; end
|
4
|
+
class Shoes::Errors
|
5
|
+
class InvalidAttributeValueError < Shoes::Error; end
|
6
|
+
|
7
|
+
class TooManyInstancesError < Shoes::Error; end
|
8
|
+
|
9
|
+
class NoSuchListItemError < Shoes::Error; end
|
10
|
+
|
11
|
+
class DuplicateCreateDrawableError < Shoes::Error; end
|
12
|
+
|
13
|
+
class MultipleDrawablesFoundError < Shoes::Error; end
|
14
|
+
|
15
|
+
class NoDrawablesFoundError < Shoes::Error; end
|
16
|
+
|
17
|
+
class NoSuchStyleError < Shoes::Error; end
|
18
|
+
|
19
|
+
class NoLinkableIdError < Shoes::Error; end
|
20
|
+
|
21
|
+
class BadLinkableIdError < Shoes::Error; end
|
22
|
+
|
23
|
+
class UnregisteredShoesEvent < Shoes::Error; end
|
24
|
+
|
25
|
+
class SingletonError < Shoes::Error; end
|
26
|
+
|
27
|
+
class MultipleShoesSpecRunsError < Shoes::Error; end
|
28
|
+
end
|
data/lib/shoes/log.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# If used alone, this will fail because the @instance is nil. It needs
|
9
9
|
# an implementation to be plugged in.
|
10
10
|
|
11
|
-
|
11
|
+
class Shoes
|
12
12
|
LOG_LEVELS = [:debug, :info, :warn, :error, :fatal].freeze
|
13
13
|
|
14
14
|
# Include this module to get a @log instance variable to log as your
|
@@ -28,7 +28,7 @@ module Shoes
|
|
28
28
|
attr_reader :current_log_config
|
29
29
|
|
30
30
|
def instance=(impl_object)
|
31
|
-
raise(Shoes::
|
31
|
+
raise(Shoes::Errors::TooManyInstancesError, "Already have an instance for Shoes::Log!") if @instance
|
32
32
|
|
33
33
|
@instance = impl_object
|
34
34
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
class Range
|
3
|
+
def rand
|
4
|
+
conv = (Integer === self.end && Integer === self.begin ? :to_i : :to_f)
|
5
|
+
((Kernel.rand * (self.end - self.begin)) + self.begin).send(conv)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
unless Time.respond_to? :today
|
10
|
+
def Time.today
|
11
|
+
t = Time.now
|
12
|
+
t - (t.to_i % 86_400)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
data/lib/shoes/spacing.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
class Shoes
|
4
4
|
module Spacing
|
5
5
|
def self.included(includer)
|
6
|
-
includer.
|
6
|
+
includer.shoes_styles :margin, :padding, :margin_top, :margin_left, :margin_right, :margin_bottom, :options
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
data/lib/shoes-spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Shoes
|
4
|
+
# A Scarpe-compatible display service can set Shoes::Spec.instance to
|
5
|
+
# a ShoesSpec testing class, and use it to run Shoes-Spec code.
|
6
|
+
# A Shoes application should never do this. It's intended to be used
|
7
|
+
# by display services.
|
8
|
+
module Spec
|
9
|
+
def self.instance
|
10
|
+
@instance
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.instance=(spec_inst)
|
14
|
+
if @instance && @instance != spec_inst
|
15
|
+
raise "Lacci can only use a single ShoesSpec implementation at one time!"
|
16
|
+
end
|
17
|
+
|
18
|
+
@instance = spec_inst
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# ShoesSpec testing objects can optionally inherit from this object,
|
23
|
+
# which shows the ShoesSpec testing API.
|
24
|
+
#
|
25
|
+
# @see {Shoes::Spec.instance=}
|
26
|
+
class SpecInstance
|
27
|
+
# Once a Shoes app has been created, this method can be called to
|
28
|
+
# execute Shoes-Spec testing code for that application. Shoes-Spec
|
29
|
+
# uses Minitest for most of its APIs, and Minitest generally reports
|
30
|
+
# results with a class name and test name. If those aren't passed
|
31
|
+
# explicitly, the SpecInstance can choose reasonable defaults.
|
32
|
+
#
|
33
|
+
# The test code should be set up to run automatically from the
|
34
|
+
# display service's existing hooks. For instance, the code might
|
35
|
+
# run in response to the first heartbeat, if the display service
|
36
|
+
# uses heartbeats.
|
37
|
+
#
|
38
|
+
# The test code will export assertion data in its native format.
|
39
|
+
# Multiple display services choose to use the Scarpe-Component
|
40
|
+
# for Minitest data export, which is straightforward to import
|
41
|
+
# into the Shoes-Spec test harness.
|
42
|
+
#
|
43
|
+
# @param code [String] the ShoesSpec code to execute
|
44
|
+
# @param class_name [String|NilClass] the Minitest class name for reporting or nil
|
45
|
+
# @param test_name [String|NilClass] the Minitest test name for reporting or nil
|
46
|
+
# @return [void]
|
47
|
+
def run_shoes_spec_test_code(code, class_name: nil, test_name: nil)
|
48
|
+
raise "Child class should override this!"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# ShoesSpec instances support finder methods like button() that return
|
53
|
+
# a proxy to the corresponding drawable. Those proxies should support
|
54
|
+
# standard Shoes::Drawable methods, including the ones appropriate to
|
55
|
+
# the same drawable object. They should also support certain other
|
56
|
+
# testing-specific methods like "trigger_click" that are used to
|
57
|
+
# simulate display-side events during testing.
|
58
|
+
#
|
59
|
+
# Keep in mind that a proxy will often be in a different process from
|
60
|
+
# the Shoes app. So the proxy can't portably return the object or
|
61
|
+
# display object, though it could possibly return another proxy for such
|
62
|
+
# a thing.
|
63
|
+
class SpecProxy
|
64
|
+
# The proxy will have finder methods for all drawables, such as
|
65
|
+
# button(), edit_line(), etc. How to document those?
|
66
|
+
|
67
|
+
# Trigger a click on a button or button-like drawable. Not every
|
68
|
+
# drawable will support this operation.
|
69
|
+
def trigger_click()
|
70
|
+
raise "Child class should override this!"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Trigger a hover over a hoverable drawable. Not every
|
74
|
+
# drawable will support this operation. A drawable that supports
|
75
|
+
# hover should support leave and vice-versa.
|
76
|
+
def trigger_hover()
|
77
|
+
raise "Child class should override this!"
|
78
|
+
end
|
79
|
+
|
80
|
+
# Trigger ending hover over a hoverable drawable. Not every
|
81
|
+
# drawable will support this operation. A drawable that supports
|
82
|
+
# hover should support leave and vice-versa.
|
83
|
+
def trigger_leave()
|
84
|
+
raise "Child class should override this!"
|
85
|
+
end
|
86
|
+
|
87
|
+
# Trigger a change in value for a drawable like a list_box
|
88
|
+
# with multiple values.
|
89
|
+
def trigger_change(value)
|
90
|
+
raise "Child class should override this!"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|