Skip to content

Commit

Permalink
Merge pull request #394 from scarpe-team/shoes_events
Browse files Browse the repository at this point in the history
Add "animate" and "every" Shoes calls
  • Loading branch information
Schwad authored Oct 10, 2023
2 parents c87b7d9 + 8f830a9 commit d33bfdd
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 13 deletions.
20 changes: 20 additions & 0 deletions examples/animate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Shoes.app do
stack do
para "10 fps"
p = para "-"
animate do |frame|
p.replace(frame.to_s)
end
para "20 fps"
p2 = para "-"
animate(20) do |frame|
p2.replace(frame.to_s)
end
para "3spf"
p3 = para "-"
every(3) do |count|
p3.replace(count.to_s)
end
end
end

15 changes: 6 additions & 9 deletions lacci/lib/shoes/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,16 +211,13 @@ def border(...)
current_slot.border(...)
end

def motion(&block)
subscription_item(shoes_api_name: "motion", &block)
end

def hover(&block)
subscription_item(shoes_api_name: "hover", &block)
end
# Event handler objects

def click(&block)
subscription_item(shoes_api_name: "click", &block)
events = [:motion, :hover, :leave, :click, :release, :keypress, :animate, :every, :timer]
events.each do |event|
define_method(event) do |*args, &block|
subscription_item(args:, shoes_api_name: event.to_s, &block)
end
end

# Draw context methods
Expand Down
38 changes: 35 additions & 3 deletions lacci/lib/shoes/widgets/subscription_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,40 @@
#
# Inheriting from Widget gives these a parent slot and a
# linkable_id automatically.
#
# Events not yet implemented: start, finish events for slots -
# start is first draw, finish is widget destroyed
class Shoes::SubscriptionItem < Shoes::Widget
display_property :shoes_api_name
display_properties :shoes_api_name, :args

def initialize(shoes_api_name:, &block)
def initialize(args: [], shoes_api_name:, &block)
super

@callback = block

case shoes_api_name
when "animate"
@unsub_id = bind_self_event("animate") do |frame|
@callback.call(frame)
end
when "every"
@unsub_id = bind_self_event("every") do |count|
@callback.call(count)
end
when "timer"
@unsub_id = bind_self_event("timer") do
@callback.call
end
when "hover"
# Hover passes the Shoes widget as the block param
@unsub_id = bind_self_event("hover") do
@callback&.call(self)
end
when "leave"
# Leave passes the Shoes widget as the block param
@unsub_id = bind_self_event("leave") do
@callback&.call(self)
end
when "motion"
# Shoes sends back x, y, mods as the args.
# Shoes3 uses the strings "control" "shift" and
Expand All @@ -37,8 +57,20 @@ def initialize(shoes_api_name:, &block)
@unsub_id = bind_self_event("click") do |button, x, y, **_kwargs|
@callback&.call(button, x, y)
end
when "release"
# Click has block params button, left, top
# button is the button number, left and top are coords
@unsub_id = bind_self_event("click") do |button, x, y, **_kwargs|
@callback&.call(button, x, y)
end
when "keypress"
# Keypress passes the key string or symbol to the handler
# Do anything special for serialisation here?
@unsub_id = bind_self_event("click") do |key|
@callback&.call(key)
end
else
raise "Unknown Shoes API call #{shoes_api_name.inspect} passed to SubscriptionItem!"
raise "Unknown Shoes event #{shoes_api_name.inspect} passed to SubscriptionItem!"
end

@unsub_id = bind_self_event(shoes_api_name) do |*args|
Expand Down
36 changes: 35 additions & 1 deletion lib/scarpe/wv/subscription_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,32 @@ def initialize(properties)
bind(@shoes_api_name) do |*args|
send_self_event(*args, event_name: @shoes_api_name)
end

@wrangler = Scarpe::Webview::DisplayService.instance.wrangler

case @shoes_api_name
when "animate"
frame_rate = (@args[0] || 10)
@counter = 0
@wrangler.periodic_code("animate_#{@shoes_linkable_id}", 1.0 / frame_rate) do
@counter += 1
send_self_event(@counter, event_name: @shoes_api_name)
end
when "every"
delay = @args[0]
@counter = 0
@wrangler.periodic_code("every_#{@shoes_linkable_id}", delay) do
@counter += 1
send_self_event(@counter, event_name: @shoes_api_name)
end
when "timer"
# JS setTimeout?
raise "Implement me!"
when "motion", "hover", "leave", "click", "release", "keypress"
# Wait for set_parent
else
raise Scarpe::UnknownShoesEventAPIError, "Unknown Shoes event API: #{@shoes_api_name}!"
end
end

def element
Expand Down Expand Up @@ -37,15 +63,23 @@ def set_parent(new_parent)
)
when "hover"
new_parent.set_event_callback(self, "onmouseenter", handler_js_code(@shoes_api_name))
when "leave"
new_parent.set_event_callback(self, "onmouseleave", handler_js_code(@shoes_api_name))
when "click"
new_parent.set_event_callback(self, "onclick", handler_js_code(@shoes_api_name, "arguments[0].button", "arguments[0].x", "arguments[0].y"))
when "release"
new_parent.set_event_callback(self, "onmouseup", handler_js_code(@shoes_api_name, "arguments[0].button", "arguments[0].x", "arguments[0].y"))
when "keypress"
raise "Implement me!"
when "animate", "every", "timer"
# These were handled in initialize(), ignore them here
else
raise Scarpe::UnknownShoesEventAPIError, "Unknown Shoes event API: #{@shoes_api_name}!"
end
end

def destroy_self
@parent.remove_event_callbacks(self)
@parent&.remove_event_callbacks(self)
super
end
end
2 changes: 2 additions & 0 deletions lib/scarpe/wv/web_wrangler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ def init_code(name, &block)
# so it should be invoked when the WebWrangler is in setup mode,
# before the Webview is running.
#
# TODO: add a way to stop this loop and unsubscribe.
#
# @param name [String] the name of the Javascript init function, if needed
# @param interval [Float] the duration between invoking this block
# @yield the Ruby block to invoke periodically
Expand Down

0 comments on commit d33bfdd

Please sign in to comment.