Files
OEVG 896f46f0d1
enUS Localization Update Announcement / localization-update-announcement (push) Canceled after 0s
Bagshui 1.6.4
2026-10-30 15:55:43 +00:00

351 lines
14 KiB
Lua

-- Bagshui Sort Order Management UI
Bagshui:AddComponent(function()
local SortOrders = BsSortOrders
--- Subclass override for InitUI() to handle class-specific details.
function SortOrders:InitUi()
-- ObjectList:InitUi() has the same check, but let's avoid doing any unnecessary work
-- since the superclass function isn't called immediately.
if self.objectManager then
return
end
-- Custom menus.
self.menus = Bagshui.prototypes.Menus:New()
-- Reusable table for pruning sort fields out of the Add menu
self._addSortField_IdsToOmit = {}
-- Menu for Add Sort Field button.
self.menus:AddMenu(
"AddSortField",
-- Level 1 is an auto-split SortFields menu full replacement.
{
autoSplitMenuType = BS_AUTO_SPLIT_MENU_TYPE.SORT_FIELDS,
func = function(listFrame, fieldId)
-- Construct a sort field entry to be added to the list.
local fieldInfo = SortOrders.sortFields[fieldId]
local sortFieldEntry = {
field = fieldInfo.property,
lookup = fieldInfo.lookup,
direction = "asc",
}
-- Figure out where in the list it belongs.
-- When nothing is selected, put it at the end.
-- If an item is selected, put it directly after.
local insertPoint = table.getn(listFrame.bagshuiData.entries) + 1
if listFrame.bagshuiData.selectedEntry then
for i = 1, insertPoint do
if listFrame.bagshuiData.entries[i] == listFrame.bagshuiData.selectedEntry then
insertPoint = i + 1
break
end
end
end
-- Add to list and refresh display.
table.insert(listFrame.bagshuiData.entries, insertPoint, sortFieldEntry)
self.objectManager.ui:PopulateScrollableList(listFrame, nil, true, true)
self.objectManager.ui:SetScrollableListSelection(listFrame, sortFieldEntry, nil, true)
end,
notCheckable = true,
},
-- Level 2/3 are empty.
nil,
nil,
-- The pre-open callback handles getting information across to the func callback.
function(menu, button, listFrame)
-- Figure out which fields are already in the Sort Order and omit them from the dropdown.
BsUtil.TableClear(self._addSortField_IdsToOmit)
for _, entry in ipairs(listFrame.bagshuiData.entries) do
table.insert(self._addSortField_IdsToOmit, SortOrders:GetFieldIdentifier(entry.field, entry.lookup))
end
menu.levels[1].idsToOmit = self._addSortField_IdsToOmit
-- Pass listFrame through to func as the first argument.
menu.levels[1].objectId = listFrame
end
)
-- Custom object editor for Sort Orders.
local sortingEditor = {}
-- Calls ObjectList:InitUi().
self._super.InitUi(
self,
nil, -- No custom Object Manager needed.
sortingEditor, -- This is our custom Object Editor.
-- All the overrides.
{
-- Basic Object Manager settings.
managerWidth = 575,
managerHeight = 400,
managerColumns = {
{
field = "name",
title = L.ObjectManager_Column_Name,
widthPercent = "78",
currentSortOrder = "ASC",
lastSortOrder = "ASC",
},
{
field = "builtin",
title = L.ObjectManager_Column_Source,
widthPercent = "12",
lastSortOrder = "ASC",
},
{
field = "inUse",
title = L.ObjectManager_Column_InUse,
widthPercent = "10",
lastSortOrder = "ASC",
},
},
-- Basic Object Editor settings.
editorWidth = 500,
editorHeight = 350,
editorFields = {
"name",
"fields",
},
-- Configuration for editor fields.
editorFieldProperties = {
name = {
required = true,
},
fields = {
widgetType = "ScrollableList",
scrollableListType = "SortOrder", -- Unique ID for custom list.
noSearchBox = true,
widgetHeight = 250,
widgetWidth = 275,
-- Open AddSortField menu when the Add button is clicked.
addButtonOnClick = function(listFrame)
self.menus:OpenMenu("AddSortField", _G.this, listFrame, _G.this, 0, 0, "TOPLEFT", "BOTTOMLEFT")
end,
extraButtons = {
-- Move sort field up.
{
scrollableList_ButtonName = BS_UI_SCROLLABLE_LIST_BUTTON_NAME.UP,
scrollableList_AutomaticAnchor = true,
anchorPoint = "TOPLEFT",
anchorToPoint = "BOTTOMLEFT",
xOffset = 0,
yOffset = -BsSkin.toolbarGroupSpacing,
},
-- Move sort field down.
{
scrollableList_ButtonName = BS_UI_SCROLLABLE_LIST_BUTTON_NAME.DOWN,
scrollableList_AutomaticAnchor = true,
anchorPoint = "TOPLEFT",
anchorToPoint = "BOTTOMLEFT",
xOffset = 0,
yOffset = -BsSkin.toolbarSpacing,
},
},
-- Additional processing to do when a new list frame in the sort field list is created.
entryFrameCreationFunc = function(entryFrameName, entryFrame, ui)
local buttonSize = 12
local buttonPadding = 5
local buttonSpacing = 8
local directionButton = ui:CreateIconButton({
name = "Direction",
namePrefix = entryFrameName,
parentFrame = entryFrame,
texture = "SortDirectionAsc",
textureDir = "UI",
anchorPoint = "RIGHT",
anchorToFrame = entryFrame,
anchorToPoint = "RIGHT",
width = buttonSize,
height = buttonSize,
xOffset = -buttonPadding,
tooltipTitle = "Sort Direction", -- Text here doesn't matter since it gets replaced real-time.
tooltipText = "Click for the opposite", -- Text here doesn't matter since it gets replaced real-time.
noTooltipDelayShorting = true,
onClick = function()
entryFrame.bagshuiData.scrollableListEntry.direction = string.lower(
entryFrame.bagshuiData.scrollableListEntry.direction or ""
) == "desc" and "asc" or "desc"
ui:PopulateScrollableList(entryFrame.bagshuiData.listFrame, nil, true, true)
end,
})
directionButton.bagshuiData.listFrame = entryFrame.bagshuiData.listFrame
local reverseButton = ui:CreateIconButton({
name = "Reverse",
namePrefix = entryFrameName,
parentFrame = entryFrame,
texture = "ReverseWordsOff",
textureDir = "UI",
anchorPoint = "RIGHT",
anchorToFrame = directionButton,
anchorToPoint = "LEFT",
width = buttonSize,
height = buttonSize,
xOffset = -buttonSpacing,
tooltipTitle = "Word Order", -- Text here doesn't matter since it gets replaced real-time.
tooltipText = "Click for the opposite", -- Text here doesn't matter since it gets replaced real-time.
noTooltipDelayShorting = true,
onClick = function()
entryFrame.bagshuiData.scrollableListEntry.reverseWords = not entryFrame.bagshuiData.scrollableListEntry.reverseWords
and true
or nil
ui:PopulateScrollableList(entryFrame.bagshuiData.listFrame, nil, true, true)
end,
})
reverseButton.bagshuiData.listFrame = entryFrame.bagshuiData.listFrame
entryFrame.bagshuiData.directionButton = directionButton
entryFrame.bagshuiData.reverseButton = reverseButton
-- Decrease the available width used to figure out how wide the text frame
-- should be (consumed by Ui:GetAvailableScrollableListEntryFrame()).
entryFrame.bagshuiData.widthOffset = entryFrame.bagshuiData.widthOffset
+ (buttonSize * 2)
+ buttonPadding
+ buttonSpacing
end,
-- Via entryInfoFunc we're going to return a completely
-- different set of data to `Ui:PopulateScrollableListEntry()`.
entryDisplayProperty = "friendlyName",
-- For the two callbacks below, ObjectManager automatically sets the
-- entryFrameCallbacksExtraParam to the sortingEditorInstance.
entryInfoFunc = function(entry, sortingEditorInstance)
return sortingEditorInstance:GetSortFieldInfo(entry)
end,
-- Additional processing to do when a list frame in the sort field list is populated.
entryFramePopulateFunc = function(listFrame, entryFrame, entry, ui, sortingEditorInstance)
sortingEditorInstance:UpdateSortOrderFieldState(entryFrame, entry, ui)
end,
},
},
}
)
--- Set correct state of a sort order field button (sort direction, reversed words) in the list.
---@param entryFrame table Scrollable list frame.
---@param button table Button to update.
---@param ui table Bagshui Ui class instance.
---@param texturePrefix string Prefix to which the appropriate state texture suffix will be added.
---@param isStateA boolean True to use the stateA* parameters, false to use the stateB* parameters.
---@param stateATextureSuffix string Texture suffix to use when isStateA == true.
---@param stateATooltipTitle string Tooltip title to use when isStateA == true.
---@param stateATooltipText string Tooltip text to use when isStateA == true.
---@param stateBTextureSuffix string Texture suffix to use when isStateA ~= true.
---@param stateBTooltipTitle string Tooltip title to use when isStateA ~= true.
---@param stateBTooltipText string Tooltip text to use when isStateA ~= true.
function sortingEditor:UpdateSortOrderIconButton(
entryFrame,
button,
ui,
texturePrefix,
isStateA,
stateATextureSuffix,
stateATooltipTitle,
stateATooltipText,
stateBTextureSuffix,
stateBTooltipTitle,
stateBTooltipText
)
ui:SetIconButtonTexture(button, texturePrefix .. (isStateA and stateATextureSuffix or stateBTextureSuffix))
button.bagshuiData.tooltipTitle = (isStateA and stateATooltipTitle or stateBTooltipTitle)
button.bagshuiData.tooltipText = (isStateA and stateATooltipText or stateBTooltipText)
-- Keep buttons clickable.
-- For whatever reason, this needs to reference the list frame's (parent of the entry frame)
-- FrameLevel, not the entry frame's FrameLevel, as the list frame's level increases when
-- frames are shuffled around, but the entry frame's level doesn't.
button:SetFrameLevel(entryFrame.bagshuiData.listFrame:GetFrameLevel() + 5)
-- Enable/disable based on read-only status.
button[(self.originalObject.readOnly and "Disable" or "Enable")](button)
end
--- Find information about a given sort field for use in the UI.
---@param entry string Sort field identifier.
---@return any
function sortingEditor:GetSortFieldInfo(entry)
if not entry then
return
end
local sortFieldInfo = BsSortOrders.sortFields[BsSortOrders:GetFieldIdentifier(entry.field, entry.lookup, "::")]
if not sortFieldInfo then
Bagshui:PrintError(
"Sort field `"
.. BsSortOrders:GetFieldIdentifier(entry.field, entry.lookup, " ")
.. "` not found while updating Sort Order editor UI. This shouldn't happen!"
)
return entry
end
return sortFieldInfo
end
--- Update the UI to match active sort field configuration.
---@param entryFrame table Scrollable list frame.
---@param entry table Sort field configuration.
---@param ui table Bagshui Ui class instance.
function sortingEditor:UpdateSortOrderFieldState(entryFrame, entry, ui)
if not entry then
return
end
local sortFieldInfo = entryFrame.bagshuiData.scrollableListEntryInfo or self:GetSortFieldInfo(entry)
-- Update Direction button.
self:UpdateSortOrderIconButton(
entryFrame,
entryFrame.bagshuiData.directionButton,
ui,
"UI\\SortDirection", -- texturePrefix
string.lower(entry.direction or "") == "desc", -- isStateA
-- stateA parameters:
"Desc",
string.format(L.Prefix_Sort, L.Descending),
string.format(L.Prefix_ClickFor, L.Ascending),
-- stateB parameters:
"Asc",
string.format(L.Prefix_Sort, L.Ascending),
string.format(L.Prefix_ClickFor, L.Descending)
)
-- Update Reverse Words button.
if sortFieldInfo.allowReverseWords then
self:UpdateSortOrderIconButton(
entryFrame,
entryFrame.bagshuiData.reverseButton,
ui,
"UI\\ReverseWords", -- texturePrefix
entry.reverseWords, -- isStateA
-- stateA parameters:
"On",
L.SortOrderEditor_ReverseWordOrder,
string.format(L.Prefix_ClickFor, L.SortOrderEditor_NormalWordOrder),
-- stateB parameters:
"Off",
L.SortOrderEditor_NormalWordOrder,
string.format(L.Prefix_ClickFor, L.SortOrderEditor_ReverseWordOrder)
)
entryFrame.bagshuiData.reverseButton:Show()
else
entryFrame.bagshuiData.reverseButton:Hide()
end
end
end
end)