mirror of
https://github.com/britzl/monarch.git
synced 2025-11-26 19:00:53 +01:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffc148b4bf | ||
|
|
724713f9e4 | ||
|
|
39628b75af | ||
|
|
dbf1bdea9d | ||
|
|
d45005cd90 | ||
|
|
a701f6cd92 | ||
|
|
f811c1f306 |
17
README.md
17
README.md
@@ -123,6 +123,7 @@ When a transition is completed it is up to the developer to send a ```transition
|
|||||||
Monarch comes with a system for setting up transitions easily in a gui_script using the ```monarch.transitions.gui``` module. Example:
|
Monarch comes with a system for setting up transitions easily in a gui_script using the ```monarch.transitions.gui``` module. Example:
|
||||||
|
|
||||||
local transitions = require "monarch.transitions.gui"
|
local transitions = require "monarch.transitions.gui"
|
||||||
|
local monarch = require "monarch.monarch"
|
||||||
|
|
||||||
function init(self)
|
function init(self)
|
||||||
-- create transitions for the node 'root'
|
-- create transitions for the node 'root'
|
||||||
@@ -137,6 +138,10 @@ Monarch comes with a system for setting up transitions easily in a gui_script us
|
|||||||
|
|
||||||
function on_message(self, message_id, message, sender)
|
function on_message(self, message_id, message, sender)
|
||||||
self.transition.handle(message_id, message, sender)
|
self.transition.handle(message_id, message, sender)
|
||||||
|
-- you can also check when a transition has completed:
|
||||||
|
if message_id == monarch.TRANSITION.DONE and message.transition == monarch.TRANSITION.SHOW_IN then
|
||||||
|
print("Show in done!")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
### Predefined transitions
|
### Predefined transitions
|
||||||
@@ -222,6 +227,14 @@ Go back to a previous Monarch screen
|
|||||||
* ```callback``` (function) - Optional function to call when the previous screen is visible.
|
* ```callback``` (function) - Optional function to call when the previous screen is visible.
|
||||||
|
|
||||||
|
|
||||||
|
### monarch.preload(screen_id, [callback])
|
||||||
|
Preload a Monarch screen. This will load but not enable the screen. This is useful for content heavy screens that you wish to be able to show without having to wait for it load.
|
||||||
|
|
||||||
|
**PARAMETERS**
|
||||||
|
* ```screen_id``` (hash) - Id of the screen to preload.
|
||||||
|
* ```callback``` (function) - Optional function to call when the new screen is preloaded.
|
||||||
|
|
||||||
|
|
||||||
### monarch.data(screen_id)
|
### monarch.data(screen_id)
|
||||||
Get the data associated with a screen (from a call to ```monarch.show()``` or ```monarch.back()```).
|
Get the data associated with a screen (from a call to ```monarch.show()``` or ```monarch.back()```).
|
||||||
|
|
||||||
@@ -240,3 +253,7 @@ Check if a Monarch screen exists.
|
|||||||
|
|
||||||
**RETURN**
|
**RETURN**
|
||||||
* ```exists``` (boolean) - True if the screen exists.
|
* ```exists``` (boolean) - True if the screen exists.
|
||||||
|
|
||||||
|
|
||||||
|
### monarch.debug()
|
||||||
|
Enable verbose logging of the internals of Monarch.
|
||||||
|
|||||||
@@ -32,6 +32,15 @@ function M.debug()
|
|||||||
log = print
|
log = print
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- use a lookup table for so we don't have to do "return (type(s) == "string" and hash(s) or s)"
|
||||||
|
-- every time
|
||||||
|
local hash_lookup = {}
|
||||||
|
local function tohash(s)
|
||||||
|
hash_lookup[s] = hash_lookup[s] or (type(s) == "string" and hash(s) or s)
|
||||||
|
return hash_lookup[s]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function screen_from_proxy(proxy)
|
local function screen_from_proxy(proxy)
|
||||||
for _, screen in pairs(screens) do
|
for _, screen in pairs(screens) do
|
||||||
if screen.proxy == proxy then
|
if screen.proxy == proxy then
|
||||||
@@ -51,9 +60,11 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Check if a screen exists in the current screen stack
|
--- Check if a screen exists in the current screen stack
|
||||||
-- @param id
|
-- @param id (string|hash)
|
||||||
-- @return true of the screen is in the stack
|
-- @return true of the screen is in the stack
|
||||||
function M.in_stack(id)
|
function M.in_stack(id)
|
||||||
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
for i = 1, #stack do
|
for i = 1, #stack do
|
||||||
if stack[i].id == id then
|
if stack[i].id == id then
|
||||||
return true
|
return true
|
||||||
@@ -65,9 +76,11 @@ end
|
|||||||
|
|
||||||
--- Check if a screen is at the top of the stack
|
--- Check if a screen is at the top of the stack
|
||||||
-- (primarily used for unit tests, but could have a usecase outside tests)
|
-- (primarily used for unit tests, but could have a usecase outside tests)
|
||||||
-- @param id
|
-- @param id (string|hash)
|
||||||
-- @return true if the screen is at the top of the stack
|
-- @return true if the screen is at the top of the stack
|
||||||
function M.is_top(id)
|
function M.is_top(id)
|
||||||
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
local top = stack[#stack]
|
local top = stack[#stack]
|
||||||
return top and top.id == id or false
|
return top and top.id == id or false
|
||||||
end
|
end
|
||||||
@@ -89,6 +102,8 @@ end
|
|||||||
-- * focus_url - URL to a script that is to be notified of focus
|
-- * focus_url - URL to a script that is to be notified of focus
|
||||||
-- lost/gained events
|
-- lost/gained events
|
||||||
function M.register(id, proxy, settings)
|
function M.register(id, proxy, settings)
|
||||||
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
assert(not screens[id], ("There is already a screen registered with id %s"):format(tostring(id)))
|
assert(not screens[id], ("There is already a screen registered with id %s"):format(tostring(id)))
|
||||||
assert(proxy, "You must provide a collection proxy URL")
|
assert(proxy, "You must provide a collection proxy URL")
|
||||||
local url = msg.url(proxy)
|
local url = msg.url(proxy)
|
||||||
@@ -107,6 +122,8 @@ end
|
|||||||
-- This is done automatically by the screen.script
|
-- This is done automatically by the screen.script
|
||||||
-- @param id Id of the screen to unregister
|
-- @param id Id of the screen to unregister
|
||||||
function M.unregister(id)
|
function M.unregister(id)
|
||||||
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||||
screens[id] = nil
|
screens[id] = nil
|
||||||
end
|
end
|
||||||
@@ -236,10 +253,17 @@ local function show_in(screen, previous_screen, reload, cb)
|
|||||||
log("show_in() reloading", screen.id)
|
log("show_in() reloading", screen.id)
|
||||||
unload(screen)
|
unload(screen)
|
||||||
end
|
end
|
||||||
|
-- if the screen has been preloaded we need to enable it
|
||||||
|
if screen.preloaded then
|
||||||
|
log("show_in() screen was preloaded", screen.id)
|
||||||
|
msg.post(screen.proxy, ENABLE)
|
||||||
|
screen.loaded = true
|
||||||
|
screen.preloaded = false
|
||||||
-- the screen could be loaded if the previous screen was a popup
|
-- the screen could be loaded if the previous screen was a popup
|
||||||
-- and the popup asked to show this screen again
|
-- and the popup asked to show this screen again
|
||||||
-- in that case we shouldn't attempt to load it again
|
-- in that case we shouldn't attempt to load it again
|
||||||
if not screen.loaded then
|
elseif not screen.loaded then
|
||||||
|
log("show_in() loading screen", screen.id)
|
||||||
async_load(screen)
|
async_load(screen)
|
||||||
end
|
end
|
||||||
stack[#stack + 1] = screen
|
stack[#stack + 1] = screen
|
||||||
@@ -258,7 +282,13 @@ local function back_in(screen, previous_screen, cb)
|
|||||||
co = coroutine.create(function()
|
co = coroutine.create(function()
|
||||||
screen.co = co
|
screen.co = co
|
||||||
change_context(screen)
|
change_context(screen)
|
||||||
if not screen.loaded then
|
if screen.preloaded then
|
||||||
|
log("back_in() screen was preloaded", screen.id)
|
||||||
|
msg.post(screen.proxy, ENABLE)
|
||||||
|
screen.preloaded = false
|
||||||
|
screen.loaded = true
|
||||||
|
elseif not screen.loaded then
|
||||||
|
log("back_in() loading screen", screen.id)
|
||||||
async_load(screen)
|
async_load(screen)
|
||||||
end
|
end
|
||||||
if previous_screen and not previous_screen.popup then
|
if previous_screen and not previous_screen.popup then
|
||||||
@@ -290,31 +320,35 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Get data associated with a screen
|
--- Get data associated with a screen
|
||||||
-- @param id Id of the screen to get data for
|
-- @param id (string|hash) Id of the screen to get data for
|
||||||
-- @return Data associated with the screen
|
-- @return Data associated with the screen
|
||||||
function M.data(id)
|
function M.data(id)
|
||||||
assert(id, "You must provide a screen id")
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||||
return screens[id].data
|
return screens[id].data
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Checks to see if a screen id is registered
|
--- Checks to see if a screen id is registered
|
||||||
-- @param id Id of the screen to check if is registered
|
-- @param id (string|hash) Id of the screen to check if is registered
|
||||||
-- @return True or False if the screen id is registered or not
|
-- @return True or False if the screen id is registered or not
|
||||||
function M.screen_exists(id)
|
function M.screen_exists(id)
|
||||||
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
return screens[id] ~= nil
|
return screens[id] ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Show a new screen
|
--- Show a new screen
|
||||||
-- @param id Id of the screen to show
|
-- @param id (string|hash) - Id of the screen to show
|
||||||
-- @param options Table with options when showing the screen (can be nil). Valid values:
|
-- @param options (table) - Table with options when showing the screen (can be nil). Valid values:
|
||||||
-- * clear - Set to true if the stack should be cleared down to an existing instance of the screen
|
-- * clear - Set to true if the stack should be cleared down to an existing instance of the screen
|
||||||
-- * reload - Set to true if screen should be reloaded if it already exists in the stack and is loaded.
|
-- * reload - Set to true if screen should be reloaded if it already exists in the stack and is loaded.
|
||||||
-- This would be the case if doing a show() from a popup on the screen just below the popup.
|
-- This would be the case if doing a show() from a popup on the screen just below the popup.
|
||||||
-- @param data Optional data to set on the screen. Can be retrieved by the data() function
|
-- @param data (*) - Optional data to set on the screen. Can be retrieved by the data() function
|
||||||
-- @param cb Optional callback to invoke when screen is shown
|
-- @param cb (function) - Optional callback to invoke when screen is shown
|
||||||
function M.show(id, options, data, cb)
|
function M.show(id, options, data, cb)
|
||||||
assert(id, "You must provide a screen id")
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||||
|
|
||||||
local screen = screens[id]
|
local screen = screens[id]
|
||||||
@@ -362,8 +396,8 @@ end
|
|||||||
|
|
||||||
|
|
||||||
-- Go back to the previous screen in the stack
|
-- Go back to the previous screen in the stack
|
||||||
-- @param data Optional data to set for the previous screen
|
-- @param data (*) - Optional data to set for the previous screen
|
||||||
-- @param cb Optional callback to invoke when the previous screen is visible again
|
-- @param cb (function) - Optional callback to invoke when the previous screen is visible again
|
||||||
function M.back(data, cb)
|
function M.back(data, cb)
|
||||||
local screen = table.remove(stack)
|
local screen = table.remove(stack)
|
||||||
if screen then
|
if screen then
|
||||||
@@ -392,6 +426,30 @@ function M.back(data, cb)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Preload a screen. This will load but not enable and show a screen. Useful for "heavier" screens
|
||||||
|
-- that you wish to show without any delay.
|
||||||
|
-- @param id (string|hash) - Id of the screen to preload
|
||||||
|
-- @param cb (function) - Optional callback to invoke when screen is loaded
|
||||||
|
function M.preload(id, cb)
|
||||||
|
assert(id, "You must provide a screen id")
|
||||||
|
id = tohash(id)
|
||||||
|
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||||
|
|
||||||
|
local screen = screens[id]
|
||||||
|
local co
|
||||||
|
co = coroutine.create(function()
|
||||||
|
screen.co = co
|
||||||
|
change_context(screen)
|
||||||
|
screen.wait_for = PROXY_LOADED
|
||||||
|
msg.post(screen.proxy, ASYNC_LOAD)
|
||||||
|
coroutine.yield()
|
||||||
|
screen.preloaded = true
|
||||||
|
screen.wait_for = nil
|
||||||
|
if cb then cb() end
|
||||||
|
end)
|
||||||
|
coroutine.resume(co)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function M.on_message(message_id, message, sender)
|
function M.on_message(message_id, message, sender)
|
||||||
if message_id == PROXY_LOADED then
|
if message_id == PROXY_LOADED then
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ function M.create(node)
|
|||||||
|
|
||||||
local transitions = {}
|
local transitions = {}
|
||||||
|
|
||||||
|
local current_transition = nil
|
||||||
|
|
||||||
local initial_data = {}
|
local initial_data = {}
|
||||||
initial_data.pos = gui.get_position(node)
|
initial_data.pos = gui.get_position(node)
|
||||||
initial_data.scale = gui.get_scale(node)
|
initial_data.scale = gui.get_scale(node)
|
||||||
@@ -111,15 +113,18 @@ function M.create(node)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function start_transition(transition, url)
|
local function start_transition(transition, transition_id, url)
|
||||||
table.insert(transition.urls, url)
|
table.insert(transition.urls, url)
|
||||||
if not transition.in_progress then
|
if not transition.in_progress then
|
||||||
|
table.insert(transition.urls, msg.url())
|
||||||
|
current_transition = transition
|
||||||
transition.in_progress = true
|
transition.in_progress = true
|
||||||
transition.fn(node, initial_data, transition.easing, transition.duration, transition.delay or 0, function()
|
transition.fn(node, initial_data, transition.easing, transition.duration, transition.delay or 0, function()
|
||||||
transition.in_progress = false
|
transition.in_progress = false
|
||||||
|
local message = { transition = transition_id }
|
||||||
while #transition.urls > 0 do
|
while #transition.urls > 0 do
|
||||||
local url = table.remove(transition.urls)
|
local url = table.remove(transition.urls)
|
||||||
msg.post(url, monarch.TRANSITION.DONE)
|
msg.post(url, monarch.TRANSITION.DONE, message)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -129,10 +134,16 @@ function M.create(node)
|
|||||||
function instance.handle(message_id, message, sender)
|
function instance.handle(message_id, message, sender)
|
||||||
if message_id == LAYOUT_CHANGED then
|
if message_id == LAYOUT_CHANGED then
|
||||||
initial_data.pos = gui.get_position(node)
|
initial_data.pos = gui.get_position(node)
|
||||||
|
-- replay the current transition if the layout changes
|
||||||
|
-- this will ensure that things are still hidden if they
|
||||||
|
-- were transitioned out
|
||||||
|
if current_transition then
|
||||||
|
current_transition.fn(node, initial_data, current_transition.easing, 0, 0)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
local transition = transitions[message_id]
|
local transition = transitions[message_id]
|
||||||
if transition then
|
if transition then
|
||||||
start_transition(transition, sender)
|
start_transition(transition, message_id, sender)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
local cowait = require "test.cowait"
|
local cowait = require "test.cowait"
|
||||||
local monarch = require "monarch.monarch"
|
local monarch = require "monarch.monarch"
|
||||||
|
|
||||||
local SCREEN1 = hash("screen1")
|
local SCREEN1_STR = hash("screen1")
|
||||||
|
local SCREEN1 = hash(SCREEN1_STR)
|
||||||
local SCREEN2 = hash("screen2")
|
local SCREEN2 = hash("screen2")
|
||||||
local POPUP1 = hash("popup1")
|
local POPUP1 = hash("popup1")
|
||||||
local POPUP2 = hash("popup2")
|
local POPUP2 = hash("popup2")
|
||||||
@@ -65,12 +66,13 @@ return function()
|
|||||||
|
|
||||||
it("should be able to tell if a screen exists", function()
|
it("should be able to tell if a screen exists", function()
|
||||||
assert(monarch.screen_exists(SCREEN1))
|
assert(monarch.screen_exists(SCREEN1))
|
||||||
|
assert(monarch.screen_exists(SCREEN1_STR))
|
||||||
assert(not monarch.screen_exists(hash("foobar")))
|
assert(not monarch.screen_exists(hash("foobar")))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
it("should be able to show screens and go back to previous screens", function()
|
it("should be able to show screens and go back to previous screens", function()
|
||||||
monarch.show(SCREEN1)
|
monarch.show(SCREEN1_STR)
|
||||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||||
assert_stack({ SCREEN1 })
|
assert_stack({ SCREEN1 })
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user