TradeSkillMaster/Core/UI/Elements/SelectionScrollingTable.lua

251 lines
8.3 KiB
Lua

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--- SelectionScrollingTable UI Element Class.
-- A selection scrolling table is a scrolling table which allows for selecting and deselecting individual rows. It is a
-- subclass of the @{QueryScrollingTable} class.
-- @classmod SelectionScrollingTable
local _, TSM = ...
local Table = TSM.Include("Util.Table")
local TempTable = TSM.Include("Util.TempTable")
local UIElements = TSM.Include("UI.UIElements")
local SelectionScrollingTable = TSM.Include("LibTSMClass").DefineClass("SelectionScrollingTable", TSM.UI.QueryScrollingTable)
UIElements.Register(SelectionScrollingTable)
TSM.UI.SelectionScrollingTable = SelectionScrollingTable
local private = {
querySelectionScrollingTableLookup = {},
sortValuesTemp = {},
tempContextTable = {},
}
local TEMP_CONTEXT_TABLE_DEFAULT = {
colWidth = {
selected = 16,
},
colHidden = {},
}
-- ============================================================================
-- Public Class Methods
-- ============================================================================
function SelectionScrollingTable.__init(self)
self.__super:__init()
self._selectedData = {}
self._selectionEnabledFunc = nil
self._rightClickToggle = true
end
function SelectionScrollingTable.Acquire(self)
self.__super:Acquire()
-- temporarily set a context table so we can create the table columns (should be overridden later)
wipe(private.tempContextTable)
self.__super:SetContextTable(private.tempContextTable, TEMP_CONTEXT_TABLE_DEFAULT)
self:GetScrollingTableInfo()
:NewColumn("selected", true)
:SetTitleIcon("iconPack.14x14/Checkmark/Default")
:SetWidth(14)
:SetIconSize(12)
:SetFont("ITEM_BODY3")
:SetJustifyH("CENTER")
:SetIconInfo(nil, private.GetSelectedIcon)
:DisableHiding()
:Commit()
:Commit()
end
function SelectionScrollingTable.Release(self)
private.querySelectionScrollingTableLookup[self._query] = nil
wipe(self._selectedData)
self._selectionEnabledFunc = nil
self.__super:Release()
end
--- Sets the @{DatabaseQuery} source for this table.
-- This query is used to populate the entries in the selection scrolling table.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @tparam DatabaseQuery query The query object
-- @tparam[opt=false] bool redraw Whether or not to redraw the selection scrolling table
-- @treturn SelectionScrollingTable The selection scrolling table object
function SelectionScrollingTable.SetQuery(self, query, redraw)
if self._query then
private.querySelectionScrollingTableLookup[self._query] = nil
end
private.querySelectionScrollingTableLookup[query] = self
self.__super:SetQuery(query, redraw)
return self
end
--- Selects all items.
-- @tparam SelectionScrollingTable self The selection scrolling table object
function SelectionScrollingTable.SelectAll(self)
for _, uuid in ipairs(self._data) do
self._selectedData[uuid] = true
end
self:_UpdateData()
self:Draw()
if self._onSelectionChangedHandler then
self._onSelectionChangedHandler(self)
end
end
--- Clear the selection.
-- @tparam SelectionScrollingTable self The selection scrolling table object
function SelectionScrollingTable.ClearSelection(self)
wipe(self._selectedData)
self:_UpdateData()
self:Draw()
if self._onSelectionChangedHandler then
self._onSelectionChangedHandler(self)
end
end
--- Sets a selection enabled function.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @tparam function func A funciton which gets called with data to determine if it's selectable or not
-- @treturn SelectionScrollingTable The selection scrolling table object
function SelectionScrollingTable.SetIsSelectionEnabledFunc(self, func)
self._selectionEnabledFunc = func
return self
end
--- Toggles the selection of a record.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @tparam ?table data The record to toggle the selection of
-- @treturn SelectionScrollingTable The selection scrolling table object
function SelectionScrollingTable.SetSelection(self, data)
if data and self._selectionValidator and not self:_selectionValidator(self._query:GetResultRowByUUID(data)) then
assert(not self._selectedData[data])
return self
end
self._selectedData[data] = not self._selectedData[data] or nil
for _, row in ipairs(self._rows) do
if row:GetData() == data then
self:_SetRowData(row, data)
break
end
end
if self._sortCol == "selected" then
self:_UpdateData()
self:Draw()
end
if self._onSelectionChangedHandler then
self._onSelectionChangedHandler(self)
end
return self
end
--- Gets whether or not all of the items are currently selected.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @treturn boolean Whether or not all of the selection is selected
function SelectionScrollingTable.IsAllSelected(self)
for _, uuid in ipairs(self._data) do
if not self._selectedData[uuid] then
return false
end
end
return true
end
--- Gets whether or not the selection is currently cleared.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @treturn boolean Whether or not the selection is cleared
function SelectionScrollingTable.IsSelectionCleared(self)
return not next(self._selectedData)
end
--- Gets the current selection table.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @treturn table A table where the key is the data and the value is whether or not it's selected (only selected entries
-- are in the table)
function SelectionScrollingTable.SelectionIterator(self)
return private.SelectionIteratorHelper, self
end
--- Sets the context table.
-- This table can be used to preserve the table configuration across lifecycles of the scrolling table and even WoW
-- sessions if it's within the settings DB.
-- @tparam SelectionScrollingTable self The selection scrolling table object
-- @tparam table tbl The context table
-- @tparam table defaultTbl The default table (required fields: `colWidth`)
-- @treturn SelectionScrollingTable The selection scrolling table object
function SelectionScrollingTable.SetContextTable(self, tbl, defaultTbl)
assert(defaultTbl.colWidth.selected)
self.__super:SetContextTable(tbl, defaultTbl)
return self
end
-- ============================================================================
-- Private Class Methods
-- ============================================================================
function SelectionScrollingTable._IsSelected(self, data)
return self._selectedData[data] == 1
end
function SelectionScrollingTable._UpdateData(self)
self.__super:_UpdateData()
-- clear any old selection context
local hasData = TempTable.Acquire()
for _, data in ipairs(self._data) do
hasData[data] = true
end
for data in pairs(self._selectedData) do
if not hasData[data] then
self._selectedData[data] = nil
end
end
TempTable.Release(hasData)
if self._sortCol == "selected" then
local selectedValue = self._sortAscending and -1 or 1
for _, uuid in ipairs(self._data) do
private.sortValuesTemp[uuid] = self._selectedData[uuid] and selectedValue or 0
end
Table.SortWithValueLookup(self._data, private.sortValuesTemp)
wipe(private.sortValuesTemp)
end
end
function SelectionScrollingTable._ToggleSort(self, id)
if id ~= "selected" then
return self.__super:_ToggleSort(id)
end
if id == self._sortCol then
self._sortAscending = not self._sortAscending
else
self._sortCol = id
self._sortAscending = true
end
self:_UpdateData()
self:Draw()
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.SelectionIteratorHelper(self, uuid)
uuid = next(self._selectedData, uuid)
if not uuid then
return
end
return uuid, self._query:GetResultRowByUUID(uuid)
end
function private.GetSelectedIcon(row)
local self = private.querySelectionScrollingTableLookup[row:GetQuery()]
return self._selectedData[row:GetUUID()] and "iconPack.14x14/Checkmark/Default" or 0
end