2015-05-03 16:46:09 -07:00
|
|
|
function wrap(x, around)
|
|
|
|
return (x - 1) % around + 1
|
|
|
|
end
|
|
|
|
|
|
|
|
MenuItem = Class()
|
|
|
|
Text = Class(MenuItem)
|
|
|
|
Back = Class(Text)
|
|
|
|
Close = Back -- FIXME
|
2015-05-26 06:40:47 -07:00
|
|
|
LinkTo = Class(Text)
|
2015-05-03 16:46:09 -07:00
|
|
|
|
|
|
|
Active = Class(Text)
|
|
|
|
Toggle = Class(Active)
|
2015-05-26 07:01:37 -07:00
|
|
|
Radio = Class(Active)
|
2015-05-03 16:46:09 -07:00
|
|
|
Hold = Class(Active)
|
|
|
|
Oneshot = Class(Active)
|
|
|
|
Flags = Class(Active)
|
|
|
|
|
|
|
|
Screen = Class()
|
|
|
|
Menu = Class()
|
|
|
|
|
|
|
|
Callbacks = Class()
|
|
|
|
|
|
|
|
function Callbacks:init()
|
|
|
|
self.state = false
|
|
|
|
end
|
|
|
|
function Callbacks:on()
|
|
|
|
self.state = true
|
|
|
|
end
|
|
|
|
function Callbacks:off()
|
|
|
|
self.state = false
|
|
|
|
end
|
|
|
|
function Callbacks:hold()
|
|
|
|
end
|
|
|
|
function Callbacks:release()
|
|
|
|
end
|
|
|
|
|
|
|
|
function MenuItem:init()
|
|
|
|
self.focused = false
|
|
|
|
end
|
|
|
|
function MenuItem:run()
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
function MenuItem:hold()
|
|
|
|
self:release()
|
|
|
|
end
|
|
|
|
function MenuItem:focus()
|
|
|
|
self.focused = true
|
|
|
|
end
|
|
|
|
function MenuItem:unfocus()
|
|
|
|
self.focused = false
|
|
|
|
end
|
|
|
|
function MenuItem:release()
|
|
|
|
end
|
|
|
|
function MenuItem:draw(brush, y)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Text:init(text)
|
|
|
|
MenuItem.init(self)
|
|
|
|
self.text = text
|
|
|
|
end
|
|
|
|
function Text:draw(brush, y)
|
|
|
|
local color = self.focused and 'yellow' or 'white'
|
|
|
|
brush(0, y, color, self.text)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Back:init()
|
|
|
|
Text.init(self, 'back')
|
|
|
|
end
|
|
|
|
function Back:run()
|
|
|
|
return nil -- FIXME
|
|
|
|
end
|
|
|
|
|
2015-05-26 06:40:47 -07:00
|
|
|
function LinkTo:init(text, submenu)
|
|
|
|
Text.init(self, text)
|
|
|
|
self.submenu = submenu
|
|
|
|
end
|
|
|
|
function LinkTo:run()
|
|
|
|
return self.submenu
|
|
|
|
end
|
|
|
|
|
2015-05-03 16:46:09 -07:00
|
|
|
function Active:init(text, callbacks)
|
|
|
|
self.text = text
|
|
|
|
self.callbacks = callbacks or {}
|
|
|
|
end
|
|
|
|
|
|
|
|
function Toggle:init(text, callbacks)
|
|
|
|
Active.init(self, text, callbacks)
|
|
|
|
self.state = false
|
|
|
|
end
|
|
|
|
function Toggle:run()
|
|
|
|
self.state = not self.state
|
|
|
|
if self.state then
|
|
|
|
self.callbacks:on(true)
|
|
|
|
else
|
|
|
|
self.callbacks:off(false)
|
|
|
|
end
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
function Toggle:draw(brush, y)
|
|
|
|
local color = self.focused and 'yellow' or 'white'
|
|
|
|
brush(0, y, 'cyan', '[ ]')
|
|
|
|
if self.state then
|
2015-05-26 07:01:37 -07:00
|
|
|
brush(1, y, color, 'x')
|
|
|
|
end
|
|
|
|
brush(4, y, color, self.text)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Radio:init(text, group, callbacks)
|
|
|
|
Active.init(self, text, callbacks)
|
|
|
|
self.state = #group == 0
|
|
|
|
table.insert(group, self)
|
|
|
|
self.group = group
|
|
|
|
end
|
|
|
|
function Radio:run()
|
|
|
|
if self.state then
|
|
|
|
-- we're already selected!
|
|
|
|
self.callbacks:hold()
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, active in pairs(self.group) do
|
|
|
|
-- FIXME: shouldn't really be invading their namespace
|
|
|
|
if active ~= self then
|
|
|
|
active.state = false
|
|
|
|
active.callbacks:off(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
self.state = true
|
|
|
|
self.callbacks:on(true)
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
function Radio:draw(brush, y)
|
|
|
|
local color = self.focused and 'yellow' or 'white'
|
|
|
|
brush(0, y, 'cyan', '( )')
|
|
|
|
if self.state then
|
2015-05-03 16:46:09 -07:00
|
|
|
brush(1, y, color, 'x')
|
|
|
|
end
|
|
|
|
brush(4, y, color, self.text)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Oneshot:run()
|
|
|
|
self.callbacks:on()
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
|
|
|
function Hold:run()
|
|
|
|
self:hold()
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
function Hold:hold()
|
|
|
|
self.callbacks:hold()
|
|
|
|
end
|
|
|
|
function Hold:release()
|
|
|
|
self.callbacks:release()
|
|
|
|
end
|
|
|
|
|
|
|
|
--function Flags:init
|
|
|
|
|
|
|
|
function Screen:init(items)
|
|
|
|
self.items = items
|
|
|
|
self.item_sel = 1
|
|
|
|
end
|
|
|
|
|
|
|
|
function Screen:focus()
|
|
|
|
self.items[self.item_sel]:focus()
|
|
|
|
end
|
|
|
|
|
|
|
|
function Screen:unfocus()
|
|
|
|
self.items[self.item_sel]:unfocus()
|
|
|
|
end
|
|
|
|
|
|
|
|
function Screen:navigate(ctrl, pressed)
|
|
|
|
local i = self.item_sel
|
|
|
|
local old = self.items[i]
|
|
|
|
|
|
|
|
if pressed.down then i = i + 1 end
|
|
|
|
if pressed.up then i = i - 1 end
|
|
|
|
i = wrap(i, #self.items)
|
|
|
|
self.item_sel = i
|
|
|
|
|
|
|
|
local item = self.items[i]
|
|
|
|
|
|
|
|
if item ~= old then
|
|
|
|
old:unfocus()
|
|
|
|
old:release()
|
|
|
|
item:focus()
|
|
|
|
end
|
|
|
|
|
|
|
|
local focus = self
|
|
|
|
if pressed.enter then
|
|
|
|
focus = item:run()
|
|
|
|
elseif ctrl.enter then
|
|
|
|
item:hold()
|
|
|
|
else
|
|
|
|
item:release()
|
|
|
|
end
|
|
|
|
|
|
|
|
if focus == item then
|
|
|
|
focus = self
|
|
|
|
end
|
|
|
|
|
|
|
|
return focus
|
|
|
|
end
|
|
|
|
|
|
|
|
function Screen:draw(brush, y)
|
|
|
|
for i, item in ipairs(self.items) do
|
|
|
|
item:draw(brush, y + i - 1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function Menu:init(screens)
|
|
|
|
self.screens = screens
|
|
|
|
self.screen_sel = 1
|
|
|
|
end
|
|
|
|
|
|
|
|
function Menu:focus()
|
|
|
|
self.screens[self.screen_sel]:focus()
|
|
|
|
end
|
|
|
|
|
|
|
|
function Menu:unfocus()
|
|
|
|
self.screens[self.screen_sel]:unfocus()
|
|
|
|
end
|
|
|
|
|
|
|
|
function Menu:navigate(ctrl, pressed)
|
|
|
|
local s = self.screen_sel
|
|
|
|
local old = self.screens[s]
|
|
|
|
if pressed.left then s = s - 1 end
|
|
|
|
if pressed.right then s = s + 1 end
|
|
|
|
s = wrap(s, #self.screens)
|
|
|
|
self.screen_sel = s
|
|
|
|
|
|
|
|
local screen = self.screens[s]
|
|
|
|
if screen ~= old then
|
|
|
|
old:unfocus()
|
|
|
|
screen:focus()
|
|
|
|
end
|
|
|
|
|
|
|
|
local focus = screen:navigate(ctrl, pressed)
|
|
|
|
if focus == screen then focus = self end
|
|
|
|
|
|
|
|
return focus
|
|
|
|
end
|
|
|
|
|
|
|
|
function Menu:draw(brush, y)
|
|
|
|
self.screens[self.screen_sel]:draw(brush, y)
|
|
|
|
end
|