TradeSkillMaster/Core/UI/Elements/ApplicationGroupTree.lua

190 lines
7.1 KiB
Lua

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--- ApplicationGroupTree UI Element Class.
-- An application group tree displays the group tree in a way which allows the user to select any number of them. This
-- element is used wherever the user needs to select groups to perform some action on. It is a subclass of the
-- @{GroupTree} class.
-- @classmod ApplicationGroupTree
local _, TSM = ...
local TempTable = TSM.Include("Util.TempTable")
local UIElements = TSM.Include("UI.UIElements")
local ApplicationGroupTree = TSM.Include("LibTSMClass").DefineClass("ApplicationGroupTree", TSM.UI.GroupTree)
UIElements.Register(ApplicationGroupTree)
TSM.UI.ApplicationGroupTree = ApplicationGroupTree
-- ============================================================================
-- Public Class Methods
-- ============================================================================
function ApplicationGroupTree.__init(self)
self.__super:__init()
self._selectedGroupsChangedHandler = nil
end
function ApplicationGroupTree.Release(self)
self._selectedGroupsChangedHandler = nil
self.__super:Release()
end
--- Registers a script handler.
-- @tparam ApplicationGroupTree self The application group tree object
-- @tparam string script The script to register for (supported scripts: `OnGroupSelectionChanged`)
-- @tparam function handler The script handler which will be called with the application group tree object followed by
-- any arguments to the script
-- @treturn ApplicationGroupTree The application group tree object
function ApplicationGroupTree.SetScript(self, script, handler)
if script == "OnGroupSelectionChanged" then
self._selectedGroupsChangedHandler = handler
else
error("Unknown ApplicationGroupTree script: "..tostring(script))
end
return self
end
--- Iterates through the selected groups.
-- @tparam ApplicationGroupTree self The application group tree object
-- @return Iterator with the following fields: `index, groupPath`
function ApplicationGroupTree.SelectedGroupsIterator(self)
local groups = TempTable.Acquire()
for _, groupPath in ipairs(self._allData) do
if self:_IsSelected(groupPath) then
tinsert(groups, groupPath)
end
end
return TempTable.Iterator(groups)
end
--- Sets the context table.
-- This table can be used to preserve selection state across lifecycles of the application group tree and even WoW
-- sessions if it's within the settings DB.
-- @see GroupTree.SetContextTable
-- @tparam ApplicationGroupTree self The application group tree object
-- @tparam table tbl The context table
-- @tparam table defaultTbl The default table (required fields: `unselected` OR `selected`, `collapsed`)
-- @treturn ApplicationGroupTree The application group tree object
function ApplicationGroupTree.SetContextTable(self, tbl, defaultTbl)
if defaultTbl.unselected then
assert(type(defaultTbl.unselected) == "table" and not defaultTbl.selected)
tbl.unselected = tbl.unselected or CopyTable(defaultTbl.unselected)
tbl.selected = nil
else
assert(type(defaultTbl.selected) == "table" and not defaultTbl.unselected)
tbl.selected = tbl.selected or CopyTable(defaultTbl.selected)
tbl.unselected = nil
end
self.__super:SetContextTable(tbl, defaultTbl)
return self
end
--- Gets whether or not a group is currently selected.
-- @tparam ApplicationGroupTree self The application group tree object
-- @tparam string groupPath The group to check
-- @treturn boolean Whether or not the group is selected
function ApplicationGroupTree.IsGroupSelected(self, groupPath)
return self:_IsSelected(groupPath)
end
--- Gets whether or not a group is currently selected.
-- @tparam ApplicationGroupTree self The application group tree object
-- @tparam string groupPath The group to set the selected state of
-- @tparam boolean selected Whether or not the group should be selected
-- @treturn ApplicationGroupTree The application group tree object
function ApplicationGroupTree.SetGroupSelected(self, groupPath, selected)
self:_SetSelected(groupPath, selected)
return self
end
--- Gets whether or not the selection is cleared.
-- @tparam ApplicationGroupTree self The application group tree object
-- @tparam[opt=false] boolean updateData Whether or not to update the data first
-- @treturn boolean Whether or not the selection is cleared
function ApplicationGroupTree.IsSelectionCleared(self, updateData)
if updateData then
self:_UpdateData()
end
for _, groupPath in ipairs(self._searchStr == "" and self._allData or self._data) do
if self:_IsSelected(groupPath) then
return false
end
end
return true
end
--- Toggle the selection state of the application group tree.
-- @tparam ApplicationGroupTree self The application group tree object
-- @treturn ApplicationGroupTree The application group tree object
function ApplicationGroupTree.ToggleSelectAll(self)
local isCleared = self:IsSelectionCleared()
for _, groupPath in ipairs(self._searchStr == "" and self._allData or self._data) do
self:_SetSelected(groupPath, isCleared)
end
self:Draw()
if self._selectedGroupsChangedHandler then
self:_selectedGroupsChangedHandler()
end
return self
end
-- ============================================================================
-- Private Class Methods
-- ============================================================================
function ApplicationGroupTree._UpdateData(self)
self.__super:_UpdateData()
-- remove data which is no longer present from _contextTable
local selectedGroups = TempTable.Acquire()
for _, groupPath in ipairs(self._allData) do
if self:_IsSelected(groupPath) then
selectedGroups[groupPath] = true
end
end
wipe(self._contextTable.selected or self._contextTable.unselected)
for _, groupPath in ipairs(self._allData) do
self:_SetSelected(groupPath, selectedGroups[groupPath])
end
TempTable.Release(selectedGroups)
end
function ApplicationGroupTree._IsSelected(self, data)
if self._contextTable.unselected then
return not self._contextTable.unselected[data]
else
return self._contextTable.selected[data]
end
end
function ApplicationGroupTree._SetSelected(self, data, selected)
if self._contextTable.unselected then
self._contextTable.unselected[data] = not selected or nil
else
self._contextTable.selected[data] = selected or nil
end
end
function ApplicationGroupTree._HandleRowClick(self, data, mouseButton)
if mouseButton == "RightButton" then
self.__super:_HandleRowClick(data, mouseButton)
return
end
self:_SetSelected(data, not self:_IsSelected(data))
-- also set the selection for all child groups to the same as this group
for _, groupPath in ipairs(self._allData) do
if TSM.Groups.Path.IsChild(groupPath, data) and data ~= TSM.CONST.ROOT_GROUP_PATH then
self:_SetSelected(groupPath, self:_IsSelected(data))
end
end
self:Draw()
if self._selectedGroupsChangedHandler then
self:_selectedGroupsChangedHandler()
end
end