TradeSkillMaster/Core/UI/Elements/Container.lua

208 lines
6.3 KiB
Lua
Raw Normal View History

2020-11-13 14:13:12 -05:00
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--- Container UI Element Class.
-- A container is an abstract element class which simply contains other elements. It is a subclass of the @{Element} class.
-- @classmod Container
local _, TSM = ...
local TempTable = TSM.Include("Util.TempTable")
local Table = TSM.Include("Util.Table")
local Container = TSM.Include("LibTSMClass").DefineClass("Container", TSM.UI.Element, "ABSTRACT")
local UIElements = TSM.Include("UI.UIElements")
UIElements.Register(Container)
TSM.UI.Container = Container
local private = {}
-- ============================================================================
-- Public Class Methods
-- ============================================================================
function Container.__init(self, frame)
self.__super:__init(frame)
self._children = {}
self._layoutChildren = {}
self._noLayoutChildren = {}
end
function Container.Release(self)
self:ReleaseAllChildren()
self.__super:Release()
end
--- Release all child elements.
-- @tparam Container self The container object
function Container.ReleaseAllChildren(self)
for _, child in ipairs(self._children) do
child:Release()
end
wipe(self._children)
wipe(self._layoutChildren)
wipe(self._noLayoutChildren)
end
--- Add a child element.
-- @tparam Container self The container object
-- @tparam Element child The child element
-- @treturn Container The container object
function Container.AddChild(self, child)
self:_AddChildHelper(child, true)
return self
end
--- Add a child element when the required condition is true.
-- @tparam Container self The container object
-- @tparam boolean condition The required condition
-- @tparam Element child The child element
-- @treturn Container The container object
function Container.AddChildIf(self, condition, child)
if not condition then
child:Release()
return self
end
self:_AddChildHelper(child, true)
return self
end
--- Add a child element before another one.
-- @tparam Container self The container object
-- @tparam string beforeId The id of the child element to add this one before
-- @tparam Element child The child element
-- @treturn Container The container object
function Container.AddChildBeforeById(self, beforeId, child)
self:_AddChildHelper(child, true, beforeId)
return self
end
--- Add child elements using a function.
-- @tparam Container self The container object
-- @tparam function func The function to call and pass this container object
-- @tparam vararg ... Additional arguments to pass to the function
-- @treturn Container The container object
function Container.AddChildrenWithFunction(self, func, ...)
func(self, ...)
return self
end
--- Add a child element which is not involved in layout.
-- The layout of this child must be explicitly done by the application code.
-- @tparam Container self The container object
-- @tparam Element child The child element
-- @treturn Container The container object
function Container.AddChildNoLayout(self, child)
self:_AddChildHelper(child, false)
return self
end
--- Remove a child element.
-- @tparam Container self The container object
-- @tparam Element child The child element to remove
function Container.RemoveChild(self, child)
assert(child:__isa(TSM.UI.Element) and child:_GetBaseFrame():GetParent())
child:_GetBaseFrame():SetParent(nil)
Table.RemoveByValue(self._children, child)
Table.RemoveByValue(self._layoutChildren, child)
Table.RemoveByValue(self._noLayoutChildren, child)
child:_SetParentElement(nil)
end
function Container.HasChildById(self, childId)
for _, child in ipairs(self._children) do
if child._id == childId then
return true
end
end
return false
end
--- Gets the number of child elements involved in layout.
-- @tparam Container self The container object
-- @treturn number The number of elements
function Container.GetNumLayoutChildren(self)
local count = 0
for _ in self:LayoutChildrenIterator() do
count = count + 1
end
return count
end
--- Iterates through the child elements involved in layout.
-- @tparam Container self The container object
-- @return An iterator with the following fields: `index, child`
function Container.LayoutChildrenIterator(self)
local children = TempTable.Acquire()
for _, child in ipairs(self._layoutChildren) do
if child:IsVisible() then
tinsert(children, child)
end
end
return TempTable.Iterator(children)
end
--- Shows all child elements.
-- @tparam Container self The container object
function Container.ShowAllChildren(self)
for _, child in ipairs(self._layoutChildren) do
if not child:IsVisible() then
child:Show()
end
end
end
function Container.Draw(self)
self.__super:Draw()
for _, child in ipairs(self._children) do
child:Draw()
end
end
-- ============================================================================
-- Container - Private Class Methods
-- ============================================================================
function Container._AddChildHelper(self, child, layout, beforeId)
assert(child:__isa(TSM.UI.Element) and not child:_GetBaseFrame():GetParent())
child:_GetBaseFrame():SetParent(self:_GetBaseFrame())
tinsert(self._children, private.GetElementInsertIndex(self._children, beforeId), child)
if layout then
tinsert(self._layoutChildren, private.GetElementInsertIndex(self._layoutChildren, beforeId), child)
else
tinsert(self._noLayoutChildren, private.GetElementInsertIndex(self._noLayoutChildren, beforeId), child)
end
child:_SetParentElement(self)
child:Show()
end
function Container._ClearBaseElementCache(self)
self.__super:_ClearBaseElementCache()
for _, child in ipairs(self._children) do
child:_ClearBaseElementCache()
end
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetElementInsertIndex(tbl, beforeId)
if not beforeId then
return #tbl + 1
end
for i, element in ipairs(tbl) do
if element._id == beforeId then
return i
end
end
error("Invalid beforeId: "..tostring(beforeId))
end