259 lines
8.4 KiB
Lua
259 lines
8.4 KiB
Lua
-- ------------------------------------------------------------------------------ --
|
|
-- TradeSkillMaster --
|
|
-- https://tradeskillmaster.com --
|
|
-- All Rights Reserved - Detailed license information included with addon. --
|
|
-- ------------------------------------------------------------------------------ --
|
|
|
|
--- Query Scrolling Table UI ScrollingTable Class.
|
|
-- A query scrolling table contains a scrollable list of rows with a fixed set of columns. It is a subclass of the
|
|
-- @{ScrollingTable} class.
|
|
-- @classmod QueryScrollingTable
|
|
|
|
local _, TSM = ...
|
|
local QueryScrollingTable = TSM.Include("LibTSMClass").DefineClass("QueryScrollingTable", TSM.UI.ScrollingTable)
|
|
local TempTable = TSM.Include("Util.TempTable")
|
|
local Table = TSM.Include("Util.Table")
|
|
local UIElements = TSM.Include("UI.UIElements")
|
|
UIElements.Register(QueryScrollingTable)
|
|
TSM.UI.QueryScrollingTable = QueryScrollingTable
|
|
local private = {}
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Public Class Methods
|
|
-- ============================================================================
|
|
|
|
function QueryScrollingTable.__init(self)
|
|
self.__super:__init()
|
|
self._query = nil
|
|
self._sortCol = nil
|
|
self._sortAscending = nil
|
|
self._autoReleaseQuery = false
|
|
end
|
|
|
|
function QueryScrollingTable.Release(self)
|
|
if self._query then
|
|
self._query:SetUpdateCallback()
|
|
if self._autoReleaseQuery then
|
|
self._query:Release()
|
|
end
|
|
self._query = nil
|
|
end
|
|
self._sortCol = nil
|
|
self._sortAscending = nil
|
|
self._autoReleaseQuery = false
|
|
self.__super:Release()
|
|
end
|
|
|
|
--- Sets the @{DatabaseQuery} source for this table.
|
|
-- This query is used to populate the entries in the query scrolling table.
|
|
-- @tparam QueryScrollingTable self The query scrolling table object
|
|
-- @tparam DatabaseQuery query The query object
|
|
-- @tparam[opt=false] bool redraw Whether or not to redraw the scrolling table
|
|
-- @treturn QueryScrollingTable The query scrolling table object
|
|
function QueryScrollingTable.SetQuery(self, query, redraw)
|
|
if query == self._query and not redraw then
|
|
return self
|
|
end
|
|
if self._query then
|
|
self._query:SetUpdateCallback()
|
|
end
|
|
self._query = query
|
|
self._query:SetUpdateCallback(private.QueryUpdateCallback, self)
|
|
|
|
self:_UpdateSortFromQuery()
|
|
self:_ForceLastDataUpdate()
|
|
self:UpdateData(redraw)
|
|
return self
|
|
end
|
|
|
|
--- Sets whether or not the @{DatabaseQuery} is automatically released.
|
|
-- @tparam QueryScrollingTable self The query scrolling table object
|
|
-- @tparam bool autoRelease Whether or not to auto-release the query
|
|
-- @treturn QueryScrollingTable The query scrolling table object
|
|
function QueryScrollingTable.SetAutoReleaseQuery(self, autoRelease)
|
|
self._autoReleaseQuery = autoRelease
|
|
return self
|
|
end
|
|
|
|
--- Sets the selected record.
|
|
-- @tparam QueryScrollingTable self The query scrolling table object
|
|
-- @param selection The selected record or nil to clear the selection
|
|
-- @tparam[opt=false] bool redraw Whether or not to redraw the scrolling table
|
|
-- @treturn QueryScrollingTable The query scrolling table object
|
|
function QueryScrollingTable.SetSelection(self, selection, redraw)
|
|
if selection == self._selection then
|
|
return self
|
|
elseif selection and self._selectionValidator and not self:_selectionValidator(self._query:GetResultRowByUUID(selection)) then
|
|
return self
|
|
end
|
|
local index = nil
|
|
if selection then
|
|
index = Table.KeyByValue(self._data, selection)
|
|
assert(index)
|
|
end
|
|
self:_IgnoreLastDataUpdate()
|
|
self._selection = selection
|
|
if selection then
|
|
-- set the scroll so that the selection is visible if necessary
|
|
local rowHeight = self._rowHeight
|
|
local firstVisibleIndex = ceil(self._vScrollValue / rowHeight) + 1
|
|
local lastVisibleIndex = floor((self._vScrollValue + self:_GetDimension("HEIGHT")) / rowHeight)
|
|
if lastVisibleIndex > firstVisibleIndex and (index < firstVisibleIndex or index > lastVisibleIndex) then
|
|
self:_OnScrollValueChanged(min((index - 1) * rowHeight, self:_GetMaxScroll()))
|
|
end
|
|
end
|
|
for _, row in ipairs(self._rows) do
|
|
if not row:IsMouseOver() and row:IsVisible() and row:GetData() ~= selection then
|
|
row:SetHighlightState(nil)
|
|
elseif row:IsMouseOver() and row:IsVisible() then
|
|
row:SetHighlightState(row:GetData() == selection and "selectedHover" or "hover")
|
|
elseif row:IsVisible() and row:GetData() == selection then
|
|
row:SetHighlightState("selected")
|
|
end
|
|
end
|
|
if self._onSelectionChangedHandler then
|
|
self:_onSelectionChangedHandler()
|
|
end
|
|
if redraw then
|
|
self:Draw()
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Gets the currently selected row.
|
|
-- @tparam QueryScrollingTable self The scrolling table object
|
|
-- @return The selected row or nil if there's nothing selected
|
|
function QueryScrollingTable.GetSelection(self)
|
|
return self._selection and self._query:GetResultRowByUUID(self._selection) or nil
|
|
end
|
|
|
|
--- Registers a script handler.
|
|
-- @tparam QueryScrollingTable self The scrolling table object
|
|
-- @tparam string script The script to register for (supported scripts: `OnDataUpdated`, `OnSelectionChanged`, `OnRowClick`)
|
|
-- @tparam function handler The script handler which will be called with the scrolling table object followed by any
|
|
-- arguments to the script
|
|
-- @treturn QueryScrollingTable The scrolling table object
|
|
function QueryScrollingTable.SetScript(self, script, handler)
|
|
if script == "OnDataUpdated" then
|
|
self._onDataUpdated = handler
|
|
else
|
|
self.__super:SetScript(script, handler)
|
|
end
|
|
return self
|
|
end
|
|
|
|
function QueryScrollingTable.Draw(self)
|
|
self._query:SetUpdatesPaused(true)
|
|
if self._lastDataUpdate == nil then
|
|
self:_IgnoreLastDataUpdate()
|
|
end
|
|
self.__super:Draw()
|
|
self._header:SetSort(self._sortCol, self._sortAscending)
|
|
self._query:SetUpdatesPaused(false)
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Private Class Methods
|
|
-- ============================================================================
|
|
|
|
function QueryScrollingTable._CreateScrollingTableInfo(self)
|
|
return TSM.UI.Util.QueryScrollingTableInfo()
|
|
end
|
|
|
|
function QueryScrollingTable._UpdateSortFromQuery(self)
|
|
if self._tableInfo:_IsSortEnabled() then
|
|
local sortField, sortAscending = self._query:GetLastOrderBy()
|
|
if sortField then
|
|
self._sortCol = self._tableInfo:_GetIdBySortField(sortField)
|
|
self._sortAscending = sortAscending
|
|
else
|
|
self._sortCol = nil
|
|
self._sortAscending = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function QueryScrollingTable._UpdateData(self)
|
|
-- we need to fix up the data within the rows updated to avoid errors with trying to access old DatabaseQueryResultRows
|
|
local prevRowIndex = TempTable.Acquire()
|
|
local newRowData = TempTable.Acquire()
|
|
for i, row in ipairs(self._rows) do
|
|
if row:IsVisible() then
|
|
prevRowIndex[row:GetData()] = i
|
|
end
|
|
end
|
|
local prevSelection = self._selection
|
|
wipe(self._data)
|
|
self._selection = nil
|
|
for _, uuid in self._query:UUIDIterator() do
|
|
if uuid == prevSelection then
|
|
self._selection = uuid
|
|
end
|
|
if prevRowIndex[uuid] then
|
|
newRowData[prevRowIndex[uuid]] = uuid
|
|
end
|
|
tinsert(self._data, uuid)
|
|
end
|
|
for i, row in ipairs(self._rows) do
|
|
if row:IsVisible() then
|
|
if newRowData[i] then
|
|
row:SetData(newRowData[i])
|
|
else
|
|
row:ClearData()
|
|
end
|
|
end
|
|
end
|
|
TempTable.Release(prevRowIndex)
|
|
TempTable.Release(newRowData)
|
|
if prevSelection and not self._selection then
|
|
-- select the first row since we weren't able to find the previously-selected row
|
|
self:SetSelection(self._data[1])
|
|
end
|
|
if self._onDataUpdated then
|
|
self:_onDataUpdated()
|
|
end
|
|
end
|
|
|
|
function QueryScrollingTable._ToggleSort(self, id)
|
|
local sortField = self._tableInfo:_GetSortFieldById(id)
|
|
if not self._sortCol or not self._query or not sortField then
|
|
-- sorting disabled so ignore
|
|
return
|
|
end
|
|
|
|
if id == self._sortCol then
|
|
self._sortAscending = not self._sortAscending
|
|
else
|
|
self._sortCol = id
|
|
self._sortAscending = true
|
|
end
|
|
|
|
self._query:UpdateLastOrderBy(sortField, self._sortAscending)
|
|
self:_UpdateData()
|
|
self:Draw()
|
|
end
|
|
|
|
function QueryScrollingTable._HandleRowClick(self, uuid, mouseButton)
|
|
if self._onRowClickHandler then
|
|
self:_onRowClickHandler(self._query:GetResultRowByUUID(uuid), mouseButton)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Private Helper Functions
|
|
-- ============================================================================
|
|
|
|
function private.QueryUpdateCallback(_, uuid, self)
|
|
self:_SetLastDataUpdate(uuid)
|
|
if not uuid then
|
|
self:_UpdateData()
|
|
end
|
|
self:Draw()
|
|
end
|