mirror of
https://github.com/britzl/monarch.git
synced 2025-09-27 18:12:22 +02:00
Initial commit
This commit is contained in:
198
monarch/monarch.lua
Normal file
198
monarch/monarch.lua
Normal file
@@ -0,0 +1,198 @@
|
||||
local M = {}
|
||||
|
||||
local screens = {}
|
||||
|
||||
local stack = {}
|
||||
|
||||
|
||||
local function screen_from_proxy(proxy)
|
||||
for id,screen in pairs(screens) do
|
||||
if screen.proxy == proxy then
|
||||
return screen
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function screen_from_script()
|
||||
local url = msg.url()
|
||||
for id,screen in pairs(screens) do
|
||||
if screen.script == url then
|
||||
return screen
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function in_stack(id)
|
||||
for i=1,#stack do
|
||||
if stack[i].id == id then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function M.register(id, proxy, popup, transitions)
|
||||
assert(not screens[id], ("There is already a screen registered with id %s"):format(tostring(id)))
|
||||
screens[id] = { id = id, proxy = proxy, script = msg.url(), popup = popup, transitions = transitions }
|
||||
end
|
||||
|
||||
function M.unregister(id)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
screens[id] = nil
|
||||
end
|
||||
|
||||
local function show_out(screen, next_screen)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
screen.co = co
|
||||
msg.post(screen.script, "release_input_focus")
|
||||
msg.post(screen.script, "monarch_context")
|
||||
coroutine.yield()
|
||||
if not next_screen.popup then
|
||||
msg.post(screen.transitions.show_out, "transition_show_out")
|
||||
coroutine.yield()
|
||||
msg.post(screen.proxy, "unload")
|
||||
coroutine.yield()
|
||||
end
|
||||
screen.co = nil
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function show_in(screen)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
screen.co = co
|
||||
msg.post(screen.script, "monarch_context")
|
||||
coroutine.yield()
|
||||
msg.post(screen.proxy, "async_load")
|
||||
coroutine.yield()
|
||||
msg.post(screen.proxy, "enable")
|
||||
stack[#stack + 1] = screen
|
||||
msg.post(screen.transitions.show_in, "transition_show_in")
|
||||
coroutine.yield()
|
||||
msg.post(screen.script, "acquire_input_focus")
|
||||
screen.co = nil
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function back_in(screen, previous_screen)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
screen.co = co
|
||||
msg.post(screen.script, "monarch_context")
|
||||
coroutine.yield()
|
||||
if not previous_screen.popup then
|
||||
msg.post(screen.proxy, "async_load")
|
||||
coroutine.yield()
|
||||
msg.post(screen.proxy, "enable")
|
||||
msg.post(screen.transitions.back_in, "transition_back_in")
|
||||
coroutine.yield()
|
||||
end
|
||||
msg.post(screen.script, "acquire_input_focus")
|
||||
screen.co = nil
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function back_out(screen)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
screen.co = co
|
||||
msg.post(screen.script, "monarch_context")
|
||||
coroutine.yield()
|
||||
msg.post(screen.transitions.back_out, "transition_back_out")
|
||||
coroutine.yield()
|
||||
msg.post(screen.proxy, "unload")
|
||||
screen.co = nil
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
|
||||
--- Show a new screen
|
||||
-- @param id Id of the screen to show
|
||||
-- @param clear Set to true if the stack should be cleared down to an existing instance of the screen. Optional
|
||||
function M.show(id, clear)
|
||||
assert(id, "You must provide a screen id")
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
|
||||
local screen = screens[id]
|
||||
|
||||
-- manipulate the current top
|
||||
-- close popup if needed
|
||||
-- transition out
|
||||
local top = stack[#stack]
|
||||
if top then
|
||||
-- if top is popup then close it
|
||||
if top.popup then
|
||||
stack[#stack] = nil
|
||||
show_out(top, screen)
|
||||
top = stack[#stack]
|
||||
end
|
||||
-- unload and transition out from top
|
||||
if top then
|
||||
show_out(top, screen)
|
||||
end
|
||||
end
|
||||
|
||||
-- if the screen we want to show is in the stack
|
||||
-- already and the clear flag is set then we need
|
||||
-- to remove every screen on the stack up until and
|
||||
-- including the screen itself
|
||||
if clear and in_stack(id) then
|
||||
while true do
|
||||
if table.remove(stack).id == id then
|
||||
break
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- show screen
|
||||
show_in(screen)
|
||||
end
|
||||
|
||||
|
||||
-- Go back to the previous screen in the stack
|
||||
function M.back()
|
||||
local screen = table.remove(stack)
|
||||
if screen then
|
||||
back_out(screen)
|
||||
local top = stack[#stack]
|
||||
if top then
|
||||
back_in(top, screen)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.on_message(message_id, message, sender)
|
||||
if message_id == hash("proxy_loaded") then
|
||||
local screen = screen_from_proxy(sender)
|
||||
assert(screen, "Unable to find screen for loaded proxy")
|
||||
coroutine.resume(screen.co)
|
||||
elseif message_id == hash("proxy_unloaded") then
|
||||
local screen = screen_from_proxy(sender)
|
||||
assert(screen, "Unable to find screen for unloaded proxy")
|
||||
elseif message_id == hash("monarch_context") then
|
||||
local screen = screen_from_script()
|
||||
assert(screen, "Unable to find screen for current script url")
|
||||
coroutine.resume(screen.co)
|
||||
elseif message_id == hash("transition_done") then
|
||||
local screen = screen_from_script()
|
||||
assert(screen, "Unable to find screen for current script url")
|
||||
coroutine.resume(screen.co)
|
||||
end
|
||||
end
|
||||
|
||||
function M.dump_stack()
|
||||
local s = ""
|
||||
for i,screen in ipairs(stack) do
|
||||
s = s .. ("%d = %s\n"):format(i, tostring(screen.id))
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
return M
|
32
monarch/monarch.script
Normal file
32
monarch/monarch.script
Normal file
@@ -0,0 +1,32 @@
|
||||
local monarch = require "monarch.monarch"
|
||||
|
||||
|
||||
function init(self)
|
||||
-- Add initialization code here
|
||||
-- Remove this function if not needed
|
||||
end
|
||||
|
||||
function final(self)
|
||||
-- Add finalization code here
|
||||
-- Remove this function if not needed
|
||||
end
|
||||
|
||||
function update(self, dt)
|
||||
-- Add update code here
|
||||
-- Remove this function if not needed
|
||||
end
|
||||
|
||||
function on_message(self, message_id, message, sender)
|
||||
-- Add message-handling code here
|
||||
-- Remove this function if not needed
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
-- Add input-handling code here
|
||||
-- Remove this function if not needed
|
||||
end
|
||||
|
||||
function on_reload(self)
|
||||
-- Add reload-handling code here
|
||||
-- Remove this function if not needed
|
||||
end
|
46
monarch/screen.script
Normal file
46
monarch/screen.script
Normal file
@@ -0,0 +1,46 @@
|
||||
local monarch = require "monarch.monarch"
|
||||
|
||||
go.property("screen_proxy", msg.url("#collectionproxy"))
|
||||
go.property("screen_id", hash(""))
|
||||
go.property("popup", false)
|
||||
go.property("transition_show_in", msg.url())
|
||||
go.property("transition_show_out", msg.url())
|
||||
go.property("transition_back_in", msg.url())
|
||||
go.property("transition_back_out", msg.url())
|
||||
|
||||
|
||||
function init(self)
|
||||
print("screen init", self.proxy)
|
||||
monarch.register(self.screen_id, self.screen_proxy, self.popup, {
|
||||
show_in = self.transition_show_in,
|
||||
show_out = self.transition_show_out,
|
||||
back_in = self.transition_back_in,
|
||||
back_out = self.transition_back_out,
|
||||
})
|
||||
end
|
||||
|
||||
function final(self)
|
||||
print("screen final", self.proxy)
|
||||
monarch.unregister(self.screen_id)
|
||||
end
|
||||
|
||||
function on_message(self, message_id, message, sender)
|
||||
print("screen on_message", message_id, sender)
|
||||
if message_id == hash("show") then
|
||||
monarch.show(self.screen_id, message.clear)
|
||||
elseif message_id == hash("hide") then
|
||||
monarch.hide(self.screen_id)
|
||||
elseif message_id == hash("back") then
|
||||
monarch.hide(self.screen_id)
|
||||
elseif message_id == hash("transition_show_in") then
|
||||
msg.post(sender, "transition_done")
|
||||
elseif message_id == hash("transition_show_out") then
|
||||
msg.post(sender, "transition_done")
|
||||
elseif message_id == hash("transition_back_in") then
|
||||
msg.post(sender, "transition_done")
|
||||
elseif message_id == hash("transition_back_out") then
|
||||
msg.post(sender, "transition_done")
|
||||
else
|
||||
monarch.on_message(message_id, message, sender)
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user