2015-12-26 20:52:07 +00:00
|
|
|
describe("UIManager spec", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
local time, UIManager
|
2017-08-08 20:35:40 +00:00
|
|
|
local now, wait_until
|
2015-12-26 20:52:07 +00:00
|
|
|
local noop = function() end
|
|
|
|
|
2016-03-29 07:56:29 +00:00
|
|
|
setup(function()
|
|
|
|
require("commonrequire")
|
2022-05-05 19:00:22 +00:00
|
|
|
time = require("ui/time")
|
2016-03-29 07:56:29 +00:00
|
|
|
UIManager = require("ui/uimanager")
|
|
|
|
end)
|
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
it("should consume due tasks", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
|
|
|
local future = now + time.s(60000)
|
|
|
|
local future2 = future + time.s(5)
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = future2, action = noop, args = {} },
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = future, action = noop, args = {} },
|
|
|
|
{ time = now, action = noop, args = {} },
|
|
|
|
{ time = now - time.us(5), action = noop, args = {} },
|
|
|
|
{ time = now - time.s(10), action = noop, args = {} },
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:_checkTasks()
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same(2, #UIManager._task_queue)
|
|
|
|
assert.are.same(future, UIManager._task_queue[2].time)
|
|
|
|
assert.are.same(future2, UIManager._task_queue[1].time)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
|
|
|
|
|
|
|
it("should calcualte wait_until properly in checkTasks routine", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
|
|
|
local future_time = now + time.s(60000)
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = future_time, action = noop, args = {} },
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now, action = noop, args = {} },
|
|
|
|
{ time = now - time.us(5), action = noop, args = {} },
|
|
|
|
{ time = now - time.s(10), action = noop, args = {} },
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
wait_until, now = UIManager:_checkTasks()
|
2022-05-05 19:00:22 +00:00
|
|
|
assert.are.same(future_time, wait_until)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
|
|
|
|
|
|
|
it("should return nil wait_until properly in checkTasks routine", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = now, action = noop, args = {} },
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now - time.us(5), action = noop, args = {} },
|
|
|
|
{ time = now - time.s(10), action = noop, args = {} },
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
wait_until, now = UIManager:_checkTasks()
|
2019-09-12 12:15:08 +00:00
|
|
|
assert.are.same(nil, wait_until)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
|
|
|
|
|
|
|
it("should insert new task properly in empty task queue", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:quit()
|
|
|
|
assert.are.same(0, #UIManager._task_queue)
|
|
|
|
UIManager:scheduleIn(50, 'foo')
|
|
|
|
assert.are.same(1, #UIManager._task_queue)
|
2019-09-12 12:15:08 +00:00
|
|
|
assert.are.same('foo', UIManager._task_queue[1].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
|
|
|
|
|
|
|
it("should insert new task properly in single task queue", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
|
|
|
local future_time = now + time.s(10000)
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = future_time, action = '1', args = {} },
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
assert.are.same(1, #UIManager._task_queue)
|
|
|
|
UIManager:scheduleIn(150, 'quz')
|
|
|
|
assert.are.same(2, #UIManager._task_queue)
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('quz', UIManager._task_queue[2].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
|
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = now, action = '1', args = {} },
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
assert.are.same(1, #UIManager._task_queue)
|
|
|
|
UIManager:scheduleIn(150, 'foo')
|
|
|
|
assert.are.same(2, #UIManager._task_queue)
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('foo', UIManager._task_queue[1].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:scheduleIn(155, 'bar')
|
|
|
|
assert.are.same(3, #UIManager._task_queue)
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('bar', UIManager._task_queue[1].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
it("should insert new task in descendant order", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = now, action = '3', args = {} },
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now - time.us(5), action = '2', args = {} },
|
|
|
|
{ time = now - time.s(10), action = '1', args = {} },
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
-- insert into the tail slot
|
|
|
|
UIManager:scheduleIn(10, 'foo')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('foo', UIManager._task_queue[1].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
-- insert into the second slot
|
2022-05-05 19:00:22 +00:00
|
|
|
UIManager:schedule(now - time.s(5), 'bar')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('bar', UIManager._task_queue[4].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
-- insert into the head slot
|
2022-05-05 19:00:22 +00:00
|
|
|
UIManager:schedule(now - time.s(15), 'baz')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('baz', UIManager._task_queue[6].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
-- insert into the last second slot
|
|
|
|
UIManager:scheduleIn(5, 'qux')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('qux', UIManager._task_queue[2].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
-- insert into the middle slot
|
2022-05-05 19:00:22 +00:00
|
|
|
UIManager:schedule(now - time.us(1), 'quux')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('quux', UIManager._task_queue[4].action)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
it("should insert new tasks with same times before existing tasks", function()
|
|
|
|
local ffiutil = require("ffi/util")
|
|
|
|
|
2022-10-10 20:17:50 +00:00
|
|
|
now = time.now()
|
|
|
|
UIManager:quit()
|
|
|
|
|
|
|
|
-- insert task "5s" between "now" and "10s"
|
|
|
|
UIManager:schedule(now, "now");
|
|
|
|
assert.are.same("now", UIManager._task_queue[1].action)
|
|
|
|
UIManager:schedule(now + time.s(10), "10s");
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same("10s", UIManager._task_queue[1].action)
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:schedule(now + time.s(5), "5s");
|
|
|
|
assert.are.same("5s", UIManager._task_queue[2].action)
|
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- insert task in place of "10s", as it'll expire shortly afer "10s"
|
|
|
|
-- NOTE: Can't use this here right now, as time.now, which is used internally,
|
|
|
|
-- may or may not have moved, depending on host's performance and clock granularity
|
|
|
|
-- (especially if host is fast and/or COARSE is available).
|
|
|
|
-- But a short wait fixes this here.
|
|
|
|
ffiutil.usleep(1000)
|
|
|
|
UIManager:scheduleIn(10, 'foo') -- is a bit later than "10s", as time.now() is used internally
|
|
|
|
assert.are.same('foo', UIManager._task_queue[1].action)
|
2022-10-10 20:17:50 +00:00
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- insert task in place of "10s", which was just shifted by foo
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:schedule(now + time.s(10), 'bar')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('bar', UIManager._task_queue[2].action)
|
2022-10-10 20:17:50 +00:00
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- insert task in place of "bar"
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:schedule(now + time.s(10), 'baz')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('baz', UIManager._task_queue[2].action)
|
2022-10-10 20:17:50 +00:00
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- insert task in place of "5s"
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:schedule(now + time.s(5), 'nix')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('nix', UIManager._task_queue[5].action)
|
|
|
|
-- "barba" replaces "nix"
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:scheduleIn(5, 'barba') -- is a bit later than "5s", as time.now() is used internally
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('barba', UIManager._task_queue[5].action)
|
2022-10-10 20:17:50 +00:00
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- "mama is sheduled now and as such inserted in "now"'s place
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:schedule(now, 'mama')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('mama', UIManager._task_queue[8].action)
|
2022-10-10 20:17:50 +00:00
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- "papa" is shortly after "now", so inserted in its place
|
2022-10-24 23:54:18 +00:00
|
|
|
-- NOTE: For the same reason as above, test this last, as time.now may not have moved...
|
|
|
|
UIManager:nextTick('papa') -- is a bit later than "now"
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same('papa', UIManager._task_queue[8].action)
|
2022-10-24 23:54:18 +00:00
|
|
|
|
2022-11-02 19:08:15 +00:00
|
|
|
-- "letta" is shortly after "papa", so inserted in its place
|
2022-10-10 20:17:50 +00:00
|
|
|
UIManager:tickAfterNext('letta')
|
2022-11-02 19:08:15 +00:00
|
|
|
assert.are.same("function", type(UIManager._task_queue[8].action))
|
2022-10-10 20:17:50 +00:00
|
|
|
end)
|
|
|
|
|
2016-03-08 06:52:52 +00:00
|
|
|
it("should unschedule all the tasks with the same action", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
2016-03-08 06:52:52 +00:00
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = now, action = '3', args = {} },
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now - time.us(5), action = '2', args = {} },
|
|
|
|
{ time = now - time.us(6), action = '3', args = {} },
|
|
|
|
{ time = now - time.s(10), action = '1', args = {} },
|
|
|
|
{ time = now - time.s(15), action = '3', args = {} },
|
2016-03-08 06:52:52 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2016-03-08 06:52:52 +00:00
|
|
|
-- insert into the tail slot
|
|
|
|
UIManager:unschedule('3')
|
|
|
|
assert.are.same({
|
2022-10-25 19:55:22 +00:00
|
|
|
{ time = now - time.us(5), action = '2', args = {} },
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now - time.s(10), action = '1', args = {} },
|
2016-03-08 06:52:52 +00:00
|
|
|
}, UIManager._task_queue)
|
|
|
|
end)
|
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
it("should not have race between unschedule and _checkTasks", function()
|
2022-05-05 19:00:22 +00:00
|
|
|
now = time.now()
|
2015-12-26 20:52:07 +00:00
|
|
|
local run_count = 0
|
|
|
|
local task_to_remove = function()
|
|
|
|
run_count = run_count + 1
|
|
|
|
end
|
|
|
|
UIManager:quit()
|
|
|
|
UIManager._task_queue = {
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now, action = task_to_remove, args = {} }, -- this will be removed
|
|
|
|
{ time = now - time.us(5), action = task_to_remove, args = {} }, -- this will be removed
|
2015-12-26 20:52:07 +00:00
|
|
|
{
|
2022-05-05 19:00:22 +00:00
|
|
|
time = now - time.s(10),
|
2022-10-27 19:14:25 +00:00
|
|
|
action = function() -- this will be called, too
|
2015-12-26 20:52:07 +00:00
|
|
|
run_count = run_count + 1
|
|
|
|
UIManager:unschedule(task_to_remove)
|
2021-02-22 01:09:44 +00:00
|
|
|
end,
|
|
|
|
args = {},
|
2015-12-26 20:52:07 +00:00
|
|
|
},
|
2022-11-02 19:08:15 +00:00
|
|
|
{ time = now - time.s(15), action = task_to_remove, args = {} }, -- this will be called
|
2015-12-26 20:52:07 +00:00
|
|
|
}
|
2022-11-02 19:08:15 +00:00
|
|
|
|
2015-12-26 20:52:07 +00:00
|
|
|
UIManager:_checkTasks()
|
2019-09-12 12:15:08 +00:00
|
|
|
assert.are.same(2, run_count)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|
2016-03-18 23:33:14 +00:00
|
|
|
|
|
|
|
it("should clear _task_queue_dirty bit before looping", function()
|
|
|
|
UIManager:quit()
|
|
|
|
assert.is.not_true(UIManager._task_queue_dirty)
|
|
|
|
UIManager:nextTick(function() UIManager:nextTick(noop) end)
|
|
|
|
UIManager:_checkTasks()
|
|
|
|
assert.is_true(UIManager._task_queue_dirty)
|
|
|
|
end)
|
2016-03-29 07:56:29 +00:00
|
|
|
|
2017-09-05 07:01:46 +00:00
|
|
|
describe("modal widgets", function()
|
|
|
|
it("should insert modal widget on top", function()
|
|
|
|
-- first modal widget
|
|
|
|
UIManager:show({
|
|
|
|
x_prefix_test_number = 1,
|
|
|
|
modal = true,
|
|
|
|
handleEvent = function()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
})
|
|
|
|
-- regular widget, should go under modal widget
|
|
|
|
UIManager:show({
|
|
|
|
x_prefix_test_number = 2,
|
|
|
|
modal = nil,
|
|
|
|
handleEvent = function()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2019-09-12 12:15:08 +00:00
|
|
|
assert.equals(2, UIManager._window_stack[1].widget.x_prefix_test_number)
|
|
|
|
assert.equals(1, UIManager._window_stack[2].widget.x_prefix_test_number)
|
2017-09-05 07:01:46 +00:00
|
|
|
end)
|
|
|
|
it("should insert second modal widget on top of first modal widget", function()
|
|
|
|
UIManager:show({
|
|
|
|
x_prefix_test_number = 3,
|
|
|
|
modal = true,
|
|
|
|
handleEvent = function()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2019-09-12 12:15:08 +00:00
|
|
|
assert.equals(2, UIManager._window_stack[1].widget.x_prefix_test_number)
|
|
|
|
assert.equals(1, UIManager._window_stack[2].widget.x_prefix_test_number)
|
|
|
|
assert.equals(3, UIManager._window_stack[3].widget.x_prefix_test_number)
|
2017-09-05 07:01:46 +00:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
2016-05-30 04:57:27 +00:00
|
|
|
it("should check active widgets in order", function()
|
|
|
|
local call_signals = {false, false, false}
|
|
|
|
UIManager._window_stack = {
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[1] = true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[2] = true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[3] = true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{widget = {handleEvent = function()end}},
|
|
|
|
}
|
|
|
|
|
|
|
|
UIManager:sendEvent("foo")
|
|
|
|
assert.falsy(call_signals[1])
|
|
|
|
assert.falsy(call_signals[2])
|
|
|
|
assert.truthy(call_signals[3])
|
|
|
|
end)
|
|
|
|
|
|
|
|
it("should handle stack change when checking for active widgets", function()
|
2016-06-11 19:17:18 +00:00
|
|
|
-- senario 1: 2nd widget removes the 3rd widget in the stack
|
2016-05-30 04:57:27 +00:00
|
|
|
local call_signals = {0, 0, 0}
|
|
|
|
UIManager._window_stack = {
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[1] = call_signals[1] + 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[2] = call_signals[2] + 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[3] = call_signals[3] + 1
|
|
|
|
table.remove(UIManager._window_stack, 2)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{widget = {handleEvent = function()end}},
|
|
|
|
}
|
|
|
|
|
|
|
|
UIManager:sendEvent("foo")
|
|
|
|
assert.is.same(call_signals[1], 1)
|
|
|
|
assert.is.same(call_signals[2], 0)
|
|
|
|
assert.is.same(call_signals[3], 1)
|
2016-06-11 19:17:18 +00:00
|
|
|
|
|
|
|
-- senario 2: top widget removes itself
|
|
|
|
call_signals = {0, 0, 0}
|
|
|
|
UIManager._window_stack = {
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[1] = call_signals[1] + 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[2] = call_signals[2] + 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
is_always_active = true,
|
|
|
|
handleEvent = function()
|
|
|
|
call_signals[3] = call_signals[3] + 1
|
|
|
|
table.remove(UIManager._window_stack, 3)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
UIManager:sendEvent("foo")
|
2019-09-12 12:15:08 +00:00
|
|
|
assert.is.same(1, call_signals[1])
|
|
|
|
assert.is.same(1, call_signals[2])
|
|
|
|
assert.is.same(1, call_signals[3])
|
2016-05-30 04:57:27 +00:00
|
|
|
end)
|
2016-06-19 00:24:38 +00:00
|
|
|
|
|
|
|
it("should handle stack change when broadcasting events", function()
|
|
|
|
UIManager._window_stack = {
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
|
|
|
UIManager._window_stack[1] = nil
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
UIManager:broadcastEvent("foo")
|
|
|
|
assert.is.same(#UIManager._window_stack, 0)
|
|
|
|
|
ReaderUI: Saner FM/RD lifecycle
* Ensure that going from one to the other tears down the former and
its plugins before instantiating the latter and its plugins.
UIManager: Unify Event sending & broadcasting
* Make the two behave the same way (walk the widget stack from top to
bottom), and properly handle the window stack shrinking shrinking
*and* growing.
Previously, broadcasting happened bottom-to-top and didn't really
handle the list shrinking/growing, while sending only handled the list
shrinking by a single element, and hopefully that element being the one
the event was just sent to.
These two items combined allowed us to optimize suboptimal
refresh behavior with Menu and other Menu classes when
opening/closing a document.
e.g., the "opening document" Notification is now properly regional,
and the "open last doc" option no longer flashes like a crazy person
anymore.
Plugins: Allow optimizing Menu refresh with custom menus, too.
Requires moving Menu's close_callback *after* onMenuSelect, which, eh,
probably makes sense, and is probably harmless in the grand scheme of
things.
2021-05-01 16:53:04 +00:00
|
|
|
-- Remember that the stack is processed top to bottom!
|
|
|
|
-- Test making a hole in the middle of the stack.
|
2016-06-19 00:24:38 +00:00
|
|
|
UIManager._window_stack = {
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
ReaderUI: Saner FM/RD lifecycle
* Ensure that going from one to the other tears down the former and
its plugins before instantiating the latter and its plugins.
UIManager: Unify Event sending & broadcasting
* Make the two behave the same way (walk the widget stack from top to
bottom), and properly handle the window stack shrinking shrinking
*and* growing.
Previously, broadcasting happened bottom-to-top and didn't really
handle the list shrinking/growing, while sending only handled the list
shrinking by a single element, and hopefully that element being the one
the event was just sent to.
These two items combined allowed us to optimize suboptimal
refresh behavior with Menu and other Menu classes when
opening/closing a document.
e.g., the "opening document" Notification is now properly regional,
and the "open last doc" option no longer flashes like a crazy person
anymore.
Plugins: Allow optimizing Menu refresh with custom menus, too.
Requires moving Menu's close_callback *after* onMenuSelect, which, eh,
probably makes sense, and is probably harmless in the grand scheme of
things.
2021-05-01 16:53:04 +00:00
|
|
|
assert.truthy(true)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
|
|
|
assert.falsy(true)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
|
|
|
assert.falsy(true)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
|
|
|
table.remove(UIManager._window_stack, #UIManager._window_stack - 2)
|
|
|
|
table.remove(UIManager._window_stack, #UIManager._window_stack - 2)
|
|
|
|
table.remove(UIManager._window_stack, #UIManager._window_stack - 1)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
|
|
|
assert.truthy(true)
|
2016-06-19 00:24:38 +00:00
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
ReaderUI: Saner FM/RD lifecycle
* Ensure that going from one to the other tears down the former and
its plugins before instantiating the latter and its plugins.
UIManager: Unify Event sending & broadcasting
* Make the two behave the same way (walk the widget stack from top to
bottom), and properly handle the window stack shrinking shrinking
*and* growing.
Previously, broadcasting happened bottom-to-top and didn't really
handle the list shrinking/growing, while sending only handled the list
shrinking by a single element, and hopefully that element being the one
the event was just sent to.
These two items combined allowed us to optimize suboptimal
refresh behavior with Menu and other Menu classes when
opening/closing a document.
e.g., the "opening document" Notification is now properly regional,
and the "open last doc" option no longer flashes like a crazy person
anymore.
Plugins: Allow optimizing Menu refresh with custom menus, too.
Requires moving Menu's close_callback *after* onMenuSelect, which, eh,
probably makes sense, and is probably harmless in the grand scheme of
things.
2021-05-01 16:53:04 +00:00
|
|
|
}
|
|
|
|
UIManager:broadcastEvent("foo")
|
|
|
|
assert.is.same(2, #UIManager._window_stack)
|
|
|
|
|
|
|
|
-- Test inserting a new widget in the stack
|
|
|
|
local new_widget = {
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
|
|
|
assert.truthy(true)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UIManager._window_stack = {
|
2016-06-19 00:24:38 +00:00
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
ReaderUI: Saner FM/RD lifecycle
* Ensure that going from one to the other tears down the former and
its plugins before instantiating the latter and its plugins.
UIManager: Unify Event sending & broadcasting
* Make the two behave the same way (walk the widget stack from top to
bottom), and properly handle the window stack shrinking shrinking
*and* growing.
Previously, broadcasting happened bottom-to-top and didn't really
handle the list shrinking/growing, while sending only handled the list
shrinking by a single element, and hopefully that element being the one
the event was just sent to.
These two items combined allowed us to optimize suboptimal
refresh behavior with Menu and other Menu classes when
opening/closing a document.
e.g., the "opening document" Notification is now properly regional,
and the "open last doc" option no longer flashes like a crazy person
anymore.
Plugins: Allow optimizing Menu refresh with custom menus, too.
Requires moving Menu's close_callback *after* onMenuSelect, which, eh,
probably makes sense, and is probably harmless in the grand scheme of
things.
2021-05-01 16:53:04 +00:00
|
|
|
table.insert(UIManager._window_stack, new_widget)
|
2016-06-19 00:24:38 +00:00
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
widget = {
|
|
|
|
handleEvent = function()
|
ReaderUI: Saner FM/RD lifecycle
* Ensure that going from one to the other tears down the former and
its plugins before instantiating the latter and its plugins.
UIManager: Unify Event sending & broadcasting
* Make the two behave the same way (walk the widget stack from top to
bottom), and properly handle the window stack shrinking shrinking
*and* growing.
Previously, broadcasting happened bottom-to-top and didn't really
handle the list shrinking/growing, while sending only handled the list
shrinking by a single element, and hopefully that element being the one
the event was just sent to.
These two items combined allowed us to optimize suboptimal
refresh behavior with Menu and other Menu classes when
opening/closing a document.
e.g., the "opening document" Notification is now properly regional,
and the "open last doc" option no longer flashes like a crazy person
anymore.
Plugins: Allow optimizing Menu refresh with custom menus, too.
Requires moving Menu's close_callback *after* onMenuSelect, which, eh,
probably makes sense, and is probably harmless in the grand scheme of
things.
2021-05-01 16:53:04 +00:00
|
|
|
assert.truthy(true)
|
2016-06-19 00:24:38 +00:00
|
|
|
end
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
UIManager:broadcastEvent("foo")
|
ReaderUI: Saner FM/RD lifecycle
* Ensure that going from one to the other tears down the former and
its plugins before instantiating the latter and its plugins.
UIManager: Unify Event sending & broadcasting
* Make the two behave the same way (walk the widget stack from top to
bottom), and properly handle the window stack shrinking shrinking
*and* growing.
Previously, broadcasting happened bottom-to-top and didn't really
handle the list shrinking/growing, while sending only handled the list
shrinking by a single element, and hopefully that element being the one
the event was just sent to.
These two items combined allowed us to optimize suboptimal
refresh behavior with Menu and other Menu classes when
opening/closing a document.
e.g., the "opening document" Notification is now properly regional,
and the "open last doc" option no longer flashes like a crazy person
anymore.
Plugins: Allow optimizing Menu refresh with custom menus, too.
Requires moving Menu's close_callback *after* onMenuSelect, which, eh,
probably makes sense, and is probably harmless in the grand scheme of
things.
2021-05-01 16:53:04 +00:00
|
|
|
assert.is.same(3, #UIManager._window_stack)
|
2016-06-19 00:24:38 +00:00
|
|
|
end)
|
2016-06-21 08:50:01 +00:00
|
|
|
|
|
|
|
it("should handle stack change when closing widgets", function()
|
|
|
|
local widget_1 = {handleEvent = function()end}
|
|
|
|
local widget_2 = {
|
|
|
|
handleEvent = function()
|
|
|
|
UIManager:close(widget_1)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
local widget_3 = {handleEvent = function()end}
|
|
|
|
UIManager._window_stack = {
|
|
|
|
{widget = widget_1},
|
|
|
|
{widget = widget_2},
|
|
|
|
{widget = widget_3},
|
|
|
|
}
|
|
|
|
UIManager:close(widget_2)
|
|
|
|
|
|
|
|
assert.is.same(1, #UIManager._window_stack)
|
|
|
|
assert.is.same(widget_3, UIManager._window_stack[1].widget)
|
|
|
|
end)
|
2015-12-26 20:52:07 +00:00
|
|
|
end)
|