192 lines
4.0 KiB
Lua
192 lines
4.0 KiB
Lua
local Event = require("gfx.event")
|
|
local Element = require("gfx.element")
|
|
local List = Element:new{
|
|
children = {},
|
|
vertical = false
|
|
}
|
|
|
|
local function adjustPositions(elements, vertical, from)
|
|
local newDims = 1
|
|
local getDim = vertical and function(e) return e:getHeight() end or function(e) return e:getWidth() end
|
|
for i=1,from-1 do
|
|
newDims = newDims + getDim(elements[i])
|
|
end
|
|
|
|
local setDim = vertical and function(e, dim) e:setPos(1, dim) end or function(e, dim) e:setPos(dim, 1) end
|
|
for i=from,#elements do
|
|
setDim(elements[i], newDims)
|
|
newDims = newDims + getDim(elements[i])
|
|
end
|
|
end
|
|
|
|
function List:insertChild(child, atIndex)
|
|
local index = math.min(math.max(1, atIndex or #self.children), #self.children)
|
|
table.insert(self.children, index, child)
|
|
|
|
-- Update window references
|
|
self:_reload()
|
|
end
|
|
|
|
function List:removeChild(child)
|
|
local index
|
|
local searchType = type(child)
|
|
if searchType == "string" then
|
|
for i,v in ipairs(self.children) do
|
|
if v:getId() == child then
|
|
index = i
|
|
break
|
|
end
|
|
end
|
|
return false, nil
|
|
elseif searchType == "table" then
|
|
for i,v in ipairs(self.children) do
|
|
if v == child then
|
|
index = i
|
|
end
|
|
end
|
|
return false, nil
|
|
else
|
|
index = child
|
|
end
|
|
|
|
if index <= 0 or index > #self.children then
|
|
return false, nil
|
|
end
|
|
|
|
local removed = table.remove(self.children, index)
|
|
self:_reload()
|
|
|
|
return true, removed
|
|
end
|
|
|
|
function List:isVertical()
|
|
return self.vertical
|
|
end
|
|
|
|
function List:isHorizontal()
|
|
return not self:isVertical()
|
|
end
|
|
|
|
function List:setDirty(fullInvalidate)
|
|
Element.setDirty(self, fullInvalidate)
|
|
if fullInvalidate then
|
|
for _,child in self.children do
|
|
child:setDirty(fullInvalidate)
|
|
end
|
|
end
|
|
end
|
|
|
|
function List:draw()
|
|
local dirty = Element.draw(self)
|
|
if dirty then
|
|
self:_getWindow().clear()
|
|
for _,child in ipairs(self.children) do
|
|
child:draw()
|
|
end
|
|
end
|
|
return dirty
|
|
end
|
|
|
|
local function maxOrSum(shouldSum, values, getValue)
|
|
if shouldSum then
|
|
local sum = 0
|
|
for _,v in ipairs(values) do
|
|
sum = sum + getValue(v)
|
|
end
|
|
return sum
|
|
else
|
|
local max = 0
|
|
for _,v in ipairs(values) do
|
|
max = math.max(max, getValue(v))
|
|
end
|
|
return max
|
|
end
|
|
end
|
|
|
|
function List:getHeight()
|
|
return maxOrSum(self:isVertical(), self.children, function(e) return e:getHeight() end)
|
|
end
|
|
|
|
function List:getWidth()
|
|
return maxOrSum(self:isHorizontal(), self.children, function(e) return e:getWidth() end)
|
|
end
|
|
|
|
function List:findById(id)
|
|
local find = Element.findById(self, id)
|
|
if find then
|
|
return find
|
|
end
|
|
|
|
for _,v in ipairs(self.children) do
|
|
local result = v:findById(id)
|
|
if result then
|
|
return result
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function List:handleEvent(evt)
|
|
evt = Event.repositionEvent(evt, 1 - self:getX(), 1 - self:getY())
|
|
if Element.handleEvent(self, evt) then
|
|
return true
|
|
end
|
|
|
|
if Event.isClickEvent(evt) then
|
|
-- If click is not inside list bounds, we can safely ignore it
|
|
if not Event.containsClick(self, evt) then
|
|
return false
|
|
end
|
|
|
|
local wOffset = 0
|
|
local hOffset = 0
|
|
for _,child in ipairs(self.children) do
|
|
if child:handleEvent(evt) then
|
|
return true
|
|
end
|
|
|
|
if self:isVertical() then
|
|
hOffset = hOffset + child:getHeight()
|
|
else
|
|
wOffset = wOffset + child:getWidth()
|
|
end
|
|
end
|
|
return false
|
|
else
|
|
for _,child in ipairs(self.children) do
|
|
if child:handleEvent(evt) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
end
|
|
|
|
function List:_isDirty()
|
|
if Element._isDirty(self) then
|
|
return true
|
|
end
|
|
|
|
for _,child in ipairs(self.children) do
|
|
if child:_isDirty() then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function List:_reload()
|
|
Element._reload(self)
|
|
|
|
-- Reload child windows
|
|
local win = self:_getWindow()
|
|
for _,child in ipairs(self.children) do
|
|
if child:_getWindow() ~= win then
|
|
child:setParent(win)
|
|
end
|
|
end
|
|
|
|
adjustPositions(self.children, self:isVertical(), 1)
|
|
end
|
|
|
|
return List |