initial commit
This commit is contained in:
258
Core/UI/Elements/QueryScrollingTable.lua
Normal file
258
Core/UI/Elements/QueryScrollingTable.lua
Normal file
@@ -0,0 +1,258 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- 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
|
||||
Reference in New Issue
Block a user