153 lines
3.4 KiB
Lua
153 lines
3.4 KiB
Lua
-- state
|
|
local context = {maxid = 0}
|
|
local draw_items = {n = 0}
|
|
local NO_WIDGET = function()end
|
|
|
|
local function generateID()
|
|
context.maxid = context.maxid + 1
|
|
return context.maxid
|
|
end
|
|
|
|
local function setHot(id) context.hot = id end
|
|
local function isHot(id) return context.hot == id end
|
|
|
|
local function setActive(id) context.active = id end
|
|
local function isActive(id) return context.active == id end
|
|
|
|
local function setKeyFocus(id) context.keyfocus = id end
|
|
local function hasKeyFocus(id) return context.keyfocus == id end
|
|
|
|
-- input
|
|
local mouse = {x = 0, y = 0, down = false}
|
|
local keyboard = {key = nil, code = -1}
|
|
|
|
function mouse.inRect(x,y,w,h)
|
|
return mouse.x >= x and mouse.x <= x+w and mouse.y >= y and mouse.y <= y+h
|
|
end
|
|
|
|
function mouse.updateState(id, x,y,w,h)
|
|
if mouse.inRect(x,y,w,h) then
|
|
setHot(id)
|
|
if not context.active and mouse.down then
|
|
setActive(id)
|
|
end
|
|
end
|
|
end
|
|
|
|
function mouse.releasedOn(id)
|
|
return not mouse.down and isHot(id) and isActive(id)
|
|
end
|
|
|
|
function keyboard.pressed(key, code)
|
|
keyboard.key = key
|
|
keyboard.code = code
|
|
end
|
|
|
|
function keyboard.tryGrab(id)
|
|
if not context.keyfocus then
|
|
context.keyfocus = id
|
|
end
|
|
end
|
|
|
|
local function makeTabable(id)
|
|
keyboard.tryGrab(id)
|
|
if hasKeyFocus(id) and keyboard.key == 'tab' then
|
|
if love.keyboard.isDown('rshift', 'lshift') then
|
|
setKeyFocus(context.lastwidget)
|
|
else
|
|
setKeyFocus(nil)
|
|
end
|
|
keyboard.key = nil
|
|
end
|
|
context.lastwidget = id
|
|
end
|
|
|
|
-- helper functions
|
|
local function strictAnd(...)
|
|
local n = select("#", ...)
|
|
local ret = true
|
|
for i = 1,n do ret = select(i, ...) and ret end
|
|
return ret
|
|
end
|
|
|
|
local function strictOr(...)
|
|
local n = select("#", ...)
|
|
local ret = false
|
|
for i = 1,n do ret = select(i, ...) or ret end
|
|
return ret
|
|
end
|
|
|
|
-- allow packed nil
|
|
local function save_pack(...)
|
|
return {n = select('#', ...), ...}
|
|
end
|
|
|
|
local function save_unpack(t, i)
|
|
i = i or 1
|
|
if i >= t.n then return t[i] end
|
|
return t[i], save_unpack(t, i+1)
|
|
end
|
|
|
|
local function registerDraw(id, f, ...)
|
|
assert(type(f) == 'function' or (getmetatable(f) or {}).__call,
|
|
'Drawing function is not a callable type!')
|
|
|
|
local state = 'normal'
|
|
if isHot(id) or hasKeyFocus(id) then
|
|
state = isActive(id) and 'active' or 'hot'
|
|
end
|
|
local rest = save_pack(...)
|
|
draw_items.n = draw_items.n + 1
|
|
draw_items[draw_items.n] = function() f(state, save_unpack(rest)) end
|
|
end
|
|
|
|
-- actually update-and-draw
|
|
local function draw()
|
|
-- close frame state
|
|
if not mouse.down then -- released
|
|
setActive(nil)
|
|
elseif not context.active then -- clicked outside
|
|
setActive(NO_WIDGET)
|
|
end
|
|
|
|
for i = 1,draw_items.n do draw_items[i]() end
|
|
|
|
-- prepare for next frame
|
|
draw_items.n = 0
|
|
context.maxid = 0
|
|
|
|
-- update mouse status
|
|
setHot(nil)
|
|
mouse.x, mouse.y = love.mouse.getPosition()
|
|
mouse.down = love.mouse.isDown('l')
|
|
|
|
-- clear keyboard focus if nobody wants it
|
|
if keyboard.key == 'tab' then
|
|
context.keyboardfocus = nil
|
|
end
|
|
keyboard.key, keyboard.code = nil, -1
|
|
end
|
|
|
|
return {
|
|
mouse = mouse,
|
|
keyboard = keyboard,
|
|
|
|
generateID = generateID,
|
|
setHot = setHot,
|
|
setActive = setActive,
|
|
setKeyFocus = setKeyFocus,
|
|
isHot = isHot,
|
|
isActive = isActive,
|
|
hasKeyFocus = hasKeyFocus,
|
|
makeTabable = makeTabable,
|
|
|
|
style = require((...):match("(.-)[^%.]+$") .. '.style-default'),
|
|
color = color,
|
|
registerDraw = registerDraw,
|
|
draw = draw,
|
|
|
|
strictAnd = strictAnd,
|
|
strictOr = strictOr,
|
|
save_pack = save_pack,
|
|
save_unpack = save_unpack,
|
|
}
|