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) if Element.handleEvent(self, evt) then return true end if Event.isClickEvent(evt) then local wOffset = 0 local hOffset = 0 for _,child in ipairs(self.children) do if child:handleEvent({Event.repositionEvent(evt, -wOffset, -hOffset)}) 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