208 lines
6.3 KiB
Lua
208 lines
6.3 KiB
Lua
-- ------------------------------------------------------------------------------ --
|
|
-- 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
|