Files
Bagshui/Components/Inventory.Menus.Settings.lua
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

700 lines
30 KiB
Lua

-- Bagshui Inventory Prototype: Settings Menu
Bagshui:AddComponent(function()
local Inventory = Bagshui.prototypes.Inventory
-- Maximum number of previously selected colors to store.
local COLOR_HISTORY_LIMIT = 10
-- Do-nothing function to be used when a setting doesn't have an update function.
local function emptyFunction() end
--- Show the Inventory settings menu.
---@param menu table Menu table.
function Inventory:OpenSettingsMenu(menu)
-- Docked frames should show the parent frame's menu.
if self.dockTo then
Bagshui.components[self.dockTo].menus:OpenMenu("Settings")
return
end
-- This is where the menu should anchor, in theory. See comments on
-- Inventory:FixSettingsMenuPosition() for more.
self.lastSettingsAnchor = self.settings.windowAnchorYPoint .. self.settings.windowAnchorXPoint
self.lastSettingsXOffset = BsSkin.menuShiftRight * (self.settings.windowAnchorXPoint == "LEFT" and 1 or -1)
-- Special property
Bagshui.menuFrame.bagshuiData.noFirstLevelRepositionNeeded = true
-- Open the menu.
self.menus:ShowMenu(
"Settings",
self.uiFrame,
self.lastSettingsXOffset,
0,
self.lastSettingsAnchor,
BsUtil.FlipAnchorPointComponent(self.lastSettingsAnchor, 2)
)
-- Anchor the menu to the side of the main window.
self:FixSettingsMenuPosition()
-- Prevent the settings menu from disappearing after 2 seconds.
self.menus:BlockAutoMenuClose(1, 3, "Settings")
end
--- The goal is to keep the settings menu anchored to the corner of the main window.
--- This is initially done naively by simply anchoring it to the opposite side of the window anchor.
--- Most of the time, it's probably ok, but if the window has been moved to the opposite side without changing
--- the anchor, the menu could be offscreen. This is addressed by a second pass where the menu is checked
--- to see if an X-adjustment would be necessary to bring it back onscreen. If so, move it to the other side.
--- There's also a bug in Blizzard's ToggleDropDownMenu() where custom menu positions aren't truly respected,
--- so we end up working around that here as well. It could probably be generalized into the
--- `Bagshui:ToggleDropDownMenu()` hook by checking the menu frame's anchor as compared to what was desired,
--- but since this is the only time we're trying for something other than `TOPLEFT` as the menu anchor it's
--- fine for now.
function Inventory:FixSettingsMenuPosition(secondPass)
if not self.menus then
return
end
if self.menus:IsMenuOpen("Settings") then
local menu = _G.DropDownList1 -- Grab the dropdown menu reference.
if not secondPass then
menu:ClearAllPoints()
menu:SetPoint(
self.lastSettingsAnchor,
self.uiFrame,
BsUtil.FlipAnchorPointComponent(self.lastSettingsAnchor, 2),
self.lastSettingsXOffset,
0
)
-- Trigger second pass position check on next frame update.
Bagshui:QueueClassCallback(self, self.FixSettingsMenuPosition, nil, nil, true)
else
local positionChanged = false
-- Check to see if the Settings menu has been positioned offscreen horizontally
-- or is overlapping the Inventory window, and if so, move it to the other side.
if
(BsUtil.GetFrameOffscreenAmount(menu, "x") ~= 0)
or (
(menu:GetLeft() or 0) >= (self.uiFrame:GetLeft() or 0)
and (menu:GetRight() or 0) <= (self.uiFrame:GetRight() or 0)
)
then
self.lastSettingsAnchor = BsUtil.FlipAnchorPointComponent(self.lastSettingsAnchor, 2)
self.lastSettingsXOffset = -self.lastSettingsXOffset
positionChanged = true
end
-- Vertical adjustment to keep the entire menu onscreen.
local yOffset = BsUtil.GetFrameOffscreenAmount(menu, "y")
if positionChanged or yOffset ~= 0 then
menu:ClearAllPoints()
menu:SetPoint(
self.lastSettingsAnchor,
self.uiFrame,
BsUtil.FlipAnchorPointComponent(self.lastSettingsAnchor, 2),
self.lastSettingsXOffset,
yOffset
)
end
end
end
end
--- Construct the Settings menu table based on the Settings configuration. Can be called recursively for nested settings.
---@param configTable table Settings configuration table from Config\Settings.lua.
---@param menuBaseTable table Menu table to place the items in as generated by `Menus:AddMenu()`.
---@param menuLevel number Level in which to place items (1-3).
---@param menuValue any Used to set the `value` property of the menu item.
function Inventory:BuildSettingsMenuFromConfig(configTable, menuBaseTable, menuLevel, menuValue)
assert((menuLevel > 1 and menuValue ~= nil) or menuLevel <= 1, "menuValue must be provided when menuLevel > 1")
-- The menu level default is 1.
local level = menuLevel or 1
-- Level 1 of menu tables is flat, but submenu tables all have a value key.
local menuTable = level > 1 and menuBaseTable.levels[level][menuValue] or menuBaseTable.levels[level]
-- Pre-colored Control+Alt+Shift+Click hint.
local settingResetHint = GRAY_FONT_COLOR_CODE .. L.Setting_Reset_TooltipText .. FONT_COLOR_CODE_CLOSE
-- Loop through the given settings configuration table.
for _, settingInfo in ipairs(configTable) do
-- Omit hidden settings.
if not settingInfo.hidden and (type(settingInfo.hideFunc) ~= "function" or not settingInfo.hideFunc()) then
if type(settingInfo.settings) == "table" then
-- Recurse for nested submenu, indicated by the presence of settingInfo.settings.
-- However, if there's no submenuName or we've reached the cap of menu levels, nothing can be done with it.
if settingInfo.submenuName and level < _G.UIDROPDOWNMENU_MAXLEVELS then
local submenuValue = settingInfo.submenuValue or settingInfo.submenuName
-- Create a parent item to open the submenu.
table.insert(menuTable, {
text = settingInfo.submenuName,
tooltipTitle = settingInfo.tooltipTitle or settingInfo.submenuName,
tooltipText = settingInfo.tooltipText,
value = submenuValue,
hasArrow = true,
})
-- Initialize the submenu table.
menuBaseTable.levels[level + 1][submenuValue] = {}
-- Recurse to build it.
self:BuildSettingsMenuFromConfig(settingInfo.settings, menuBaseTable, level + 1, submenuValue)
end
elseif settingInfo.mainTitle then
-- The mainTitle property creates an automatically-named menu item
-- with the Close button graphic as its icon, providing an obvious
-- way to dismiss the menu.
local menuItem = {
text = BS_FONT_COLOR.BAGSHUI
.. string.format(L.Menu_Settings, self.inventoryTypeLocalized)
.. FONT_COLOR_CODE_CLOSE,
_bagshuiFakeTitle = true,
func = function()
self:CloseMenusAndClearFocuses()
end,
}
BsSkin.closeButtonSkinFunc(menuItem)
table.insert(menuTable, menuItem)
elseif settingInfo.menuTitle then
-- This is just a title, not a setting.
table.insert(menuTable, {
text = settingInfo.menuTitle,
isTitle = true,
notCheckable = true,
keepShownOnClick = true,
})
else
assert(
BsUtil.TableContainsValue(BS_SETTING_TYPE, settingInfo.type),
tostring(settingInfo.name) .. " does not have a valid type."
)
-- Now we've found a setting.
local settingName = settingInfo.name or ""
local settingFriendlyName = settingInfo.title or L[settingInfo.name] or settingInfo.name
-- There are situations (like an inline CHOICES setting) where we don't actually
-- want `menuItem` added because it will be taken care of already.
local skipAddingToMenu = false
-- Base menu item.
local menuItem = {
_bagshuiSettingName = settingInfo.name,
_bagshuiSettingFriendlyName = settingFriendlyName, -- Store the base friendly name so we can manipulate the text property later.
_bagshuiFakeTitle = settingInfo.fakeTitle, -- Fake titles are styled like titles but are can be clicked and can have submenus.
_bagshuiAlpha = (settingInfo.faded and 0.6 or 1),
text = settingFriendlyName,
notCheckable = settingInfo.notCheckable,
notClickable = settingInfo.notClickable,
disabled = settingInfo.disabled,
tooltipTitle = L_nil[settingName .. "_TooltipTitle"] or settingInfo.tooltipTitle or settingFriendlyName,
tooltipText = (L_nil[settingName .. "_TooltipText"] or settingInfo.tooltipText),
keepShownOnClick = true,
}
-- Add scope indicators.
local scopeTooltipText = ""
if settingInfo.scope == BS_SETTING_SCOPE.ACCOUNT then
scopeTooltipText = L.SettingScope_Account
menuItem.icon = BsUtil.GetFullTexturePath("Icons\\Characters")
menuItem._bagshuiTextureA = 0.45
elseif settingInfo.scope == BS_SETTING_SCOPE.CHARACTER then
scopeTooltipText = L.SettingScope_Character
menuItem.icon = BsUtil.GetFullTexturePath("Icons\\Character")
menuItem._bagshuiTextureA = 0.45
end
if string.len(scopeTooltipText) > 0 then
scopeTooltipText = GRAY_FONT_COLOR_CODE .. scopeTooltipText .. FONT_COLOR_CODE_CLOSE
menuItem.tooltipText = (menuItem.tooltipText and (menuItem.tooltipText .. BS_NEWLINE) or "")
.. scopeTooltipText
end
-- Choices, numbers, and colors need submenus.
if
settingInfo.type == BS_SETTING_TYPE.CHOICES
or settingInfo.type == BS_SETTING_TYPE.NUMBER
or settingInfo.type == BS_SETTING_TYPE.COLOR
then
menuItem.hasArrow = true
local subLevel = level + 1
local subMenu
if not settingInfo.inline then
menuBaseTable.levels[subLevel][settingInfo.name] = {}
subMenu = menuBaseTable.levels[subLevel][settingInfo.name]
end
if
settingInfo.type == BS_SETTING_TYPE.CHOICES
or (settingInfo.type == BS_SETTING_TYPE.NUMBER and settingInfo.choices)
then
-- Choices / Numbers with a static list of choices.
if settingInfo.choicesAutoSplitMenuType then
-- This setting has an auto-split menu instead of a static list of choices.
-- Upvalues here for auto-split menu functions.
local settings = self.settings
local settingName = settingInfo.name
local func = settingInfo.choicesAutoSplitMenuFunc
local tooltipTextFunc = settingInfo.choicesAutoSplitMenuTooltipTextFunc
-- Triggering value and parameters for auto-split menu.
menuItem.value = {
autoSplitMenuType = settingInfo.choicesAutoSplitMenuType,
menuLevel = 1,
func = function(menuLevel, settingValue)
if type(func) == "function" then
func(settings, settingName, settingValue)
end
self.settings[settingName] = settingValue
self.menus:Refresh(menuLevel)
end,
checkFunc = function(menuOption)
return self.settings[settingName] == menuOption
end,
tooltipTitleFunc = settingInfo.choicesAutoSplitMenuTooltipTitleFunc or function(_, defaultTitle)
-- Only provide a tooltip title if none was provided by the menu.
return defaultTitle or menuItem.tooltipTitle
end,
tooltipTextFunc = function(objectId, tooltipText)
if tooltipTextFunc then
tooltipText = tooltipTextFunc(objectId, tooltipText, self)
end
return tooltipText
end,
omitFunc = settingInfo.choicesAutoSplitMenuOmitFunc,
keepShownOnClick = true,
}
menuItem.hasArrow = true
elseif settingInfo.choices then
-- Static list of choices.
for _, choice in ipairs(settingInfo.choices) do
local choiceTooltipText = choice.tooltipText
and (choice.tooltipText .. BS_NEWLINE .. scopeTooltipText)
or ((menuItem.tooltipText or "") .. (choice.tooltip and " " .. choice.tooltip or ""))
choiceTooltipText = (
string.len(choiceTooltipText or "") > 0 and choiceTooltipText .. BS_NEWLINE or ""
) .. settingResetHint
table.insert(
-- Add at current level or to submenu.
settingInfo.inline and menuTable or subMenu,
{
_bagshuiSettingName = settingInfo.name,
text = choice.text or choice.value,
value = choice.value,
tooltipTitle = choice.tooltipTitle or menuItem.tooltipTitle,
tooltipText = choiceTooltipText,
textR = choice.textR,
textG = choice.textG,
textB = choice.textB,
-- Copy scope indicators.
icon = menuItem.icon,
_bagshuiTextureA = menuItem._bagshuiTextureA,
}
)
end
-- When inline, don't add the parent menu item because everything is already done.
skipAddingToMenu = settingInfo.inline
end
elseif settingInfo.type == BS_SETTING_TYPE.NUMBER then
-- Numbers.
-- Range of values for the submenu.
if type(settingInfo.min) == "number" and type(settingInfo.max) == "number" then
for i = settingInfo.min, settingInfo.max, (settingInfo.step or 1) do
table.insert(subMenu, {
_bagshuiSettingName = settingInfo.name,
text = type(settingInfo.valueDisplayFunc) == "function" and settingInfo.valueDisplayFunc(i) or i,
value = i,
tooltipTitle = menuItem.tooltipTitle,
tooltipText = (menuItem.tooltipText and menuItem.tooltipText .. BS_NEWLINE or "")
.. settingResetHint,
-- Copy scope indicators.
icon = menuItem.icon,
_bagshuiTextureA = menuItem._bagshuiTextureA,
})
end
end
elseif settingInfo.type == BS_SETTING_TYPE.COLOR then
-- Colors.
-- Create submenu for color history.
self.menus:InitializeEmptyMenu(subMenu, {
_bagshuiSettingName = settingInfo.name,
_bagshuiSettingUpdateFunction = menuItem._bagshuiSettingUpdateFunction,
})
end
end
-- Apply text modifications.
if type(settingInfo.nameFunc) == "function" then
menuItem.text = settingInfo.nameFunc(menuItem.text)
menuItem.tooltipTitle = settingInfo.nameFunc(menuItem.tooltipTitle)
menuItem.tooltipText = settingInfo.nameFunc(menuItem.tooltipText)
end
-- Add the reset hint last because submenu items get it as needed.
if settingInfo.type ~= BS_SETTING_TYPE.TRIGGER then
menuItem.tooltipText = (menuItem.tooltipText and (menuItem.tooltipText .. BS_NEWLINE) or "")
.. "~1~" -- Insertion point for tooltip modifications.
.. GRAY_FONT_COLOR_CODE
.. L.Setting_Reset_TooltipText
.. FONT_COLOR_CODE_CLOSE
end
-- Store a backup copy of menu texts so they can be modified at display-time.
-- This probably could have been done in a more sane way but a quick hack is good enough.
menuItem._bagshuiOriginalText = menuItem.text
menuItem._bagshuiOriginalTooltipTitle = menuItem.tooltipTitle
menuItem._bagshuiOriginalTooltipText = menuItem.tooltipText
if not skipAddingToMenu then
table.insert(menuTable, menuItem)
end
end
end
end
end
--- Prepare a Settings menu item for display. Called from `Menus:LoadMenu()` when a menu item
--- has a `_bagshuiSettingName` property to build out the menu item properties.
---@param menuItem table Properties for the menu item, which will be modified in-place.
---@param menu table[] Parent table of `menuItem`.
---@param menuLevel number Menu level, 1-3.
---@param itemNum number Index of `menuItem` within `menu`.
---@param menuType string Identifier for a menu that has been registered via `AddMenu()`.
function Inventory:GenerateSettingsMenuItem(menuItem, menu, menuLevel, itemNum, menuType)
local settingName = menuItem._bagshuiSettingName
local settingsStorage = menuItem._bagshuiSettingsStorage or self.settings
local settingInfo = menuItem._bagshuiSettingInfo or self.settings:GetSettingInfo(settingName)
local currentSettingValue = settingsStorage[settingName]
local defaultValue = settingInfo.defaultValue
local settingUpdateFunction = menuItem._bagshuiSettingUpdateFunction or emptyFunction
local disabledByFunc
if type(settingInfo.disableFunc) == "function" then
disabledByFunc = settingInfo.disableFunc(settingName, settingsStorage)
end
if not self._generateSettingsMenuItem_ResetOnModifierKeys then
--- Wrapper for `self:ResetSettingOnModifierKeys()`.
---@param arg1 table Argument table containing `settingName`, `settingStorage`, and `menuLevel`.
self._generateSettingsMenuItem_ResetOnModifierKeys = function(arg1)
self:ResetSettingOnModifierKeys(arg1)
end
end
-- Update texts at display-time.
if menuItem._bagshuiOriginalText then
menuItem.text = menuItem._bagshuiOriginalText
if type(settingInfo.textDisplayFunc) == "function" then
menuItem.text = settingInfo.textDisplayFunc(menuItem.text, settingInfo.name, self.settings)
end
end
if menuItem._bagshuiOriginalTooltipText then
menuItem.tooltipText = menuItem._bagshuiOriginalTooltipText
if type(settingInfo.tooltipTextDisplayFunc) == "function" then
menuItem.tooltipText = settingInfo.tooltipTextDisplayFunc(menuItem.tooltipText, settingInfo.name, self.settings)
end
menuItem.tooltipText = string.gsub(menuItem.tooltipText, "~1~", "")
end
-- Add arg1 for use with ResetSettingOnModifierKeys().
if type(menuItem.arg1) ~= "table" then
menuItem.arg1 = {}
end
menuItem.arg1.settingName = settingName
menuItem.arg1.settingsStorage = settingsStorage
-- Need to store menu level because the global menu level variable will be wrong
-- for items with submenus.
menuItem.arg1.menuLevel = menuLevel
-- Figure out what the display text for the setting should be, when a `text`
-- property is available for the selected value within a list of choices.
local currentSettingFriendlyValue = currentSettingValue
if
settingInfo.choices
and (
(settingInfo.type == BS_SETTING_TYPE.CHOICES and not settingInfo.autoSplitMenuType)
or settingInfo.type == BS_SETTING_TYPE.NUMBER
)
then
for _, choice in ipairs(settingInfo.choices) do
if choice.value == currentSettingValue then
currentSettingFriendlyValue = choice.text or choice.value
end
end
end
-- Apply value display translation if available.
if type(settingInfo.valueDisplayFunc) == "function" then
currentSettingFriendlyValue = settingInfo.valueDisplayFunc(currentSettingFriendlyValue)
end
-- Process each type of setting into the appropriate menu item.
if settingInfo.choicesAutoSplitMenuType then
-- Stupid hack on our own code to pass menuLevel through to `arg1 of the
-- auto-split menu `func`'set up in `BuildSettingsMenuFromConfig()`.
menuItem.value.objectId = menuLevel
elseif settingInfo.type == BS_SETTING_TYPE.BOOLEAN then
-- Boolean -- checked/unchecked, toggle setting on click.
menuItem.checked = settingsStorage[settingName]
menuItem.keepShownOnClick = true
menuItem.func = function()
if not self:ResetSettingOnModifierKeys(menuItem.arg1, nil, true) then
settingsStorage[settingName] = not settingsStorage[settingName]
self.menus:Refresh(menuLevel)
end
end
elseif settingInfo.type == BS_SETTING_TYPE.CHOICES or settingInfo.type == BS_SETTING_TYPE.NUMBER then
-- Choices / Numbers -- submenu with choices, update setting to selected choice on click.
-- Determine whether this is INSIDE a submenu or whether an arrow to open the submenu is needed.
if menuItem.value and not menuItem.hasArrow then
-- Inside submenu -- checked/unchecked based on current value, change setting on click.
-- Need to use tostring() here so we don't get caught by float nonsense where 1 somehow doesn't equal 1.
menuItem.checked = type(settingInfo.choicesCheckedFunc) == "function"
and settingInfo.choicesCheckedFunc(settingName, settingsStorage, menuItem.value)
or tostring(menuItem.value) == tostring(currentSettingValue)
menuItem.keepShownOnClick = true
menuItem.func = function()
if not self:ResetSettingOnModifierKeys(menuItem.arg1, nil, true) then
settingsStorage[settingName] = _G.this.value
settingUpdateFunction()
self.menus:Refresh()
self.menus:Refresh(menuLevel, true)
end
end
if disabledByFunc ~= nil then
menuItem.disabled = true
end
else
-- Parent menu item to open the submenu.
menuItem.value = settingName
menuItem.hasArrow = true
-- Append current value to menu text.
menuItem.text = menuItem._bagshuiSettingFriendlyName
.. GRAY_FONT_COLOR_CODE
.. " ["
.. currentSettingFriendlyValue
.. "]"
.. FONT_COLOR_CODE_CLOSE
menuItem.func = self._generateSettingsMenuItem_ResetOnModifierKeys
end
elseif settingInfo.type == BS_SETTING_TYPE.COLOR then
-- Colors -- display swatch and prepare color history.
menuItem.opacity = nil
-- Determine whether this is INSIDE a submenu or whether an arrow to open the submenu is needed.
if menuItem.value and not menuItem.hasArrow then
-- Inside submenu -- populate color history, change setting on click.
if Bagshui.colorHistory[itemNum] and itemNum < COLOR_HISTORY_LIMIT then
local color = Bagshui.colorHistory[itemNum]
menuItem.text = " "
menuItem.tooltipTitle = L.Menu_Settings_ColorHistory_TooltipTitle
menuItem._bagshuiHide = false
menuItem._bagshuiColorSwatchRightAnchor = -20
menuItem.hasColorSwatch = true
menuItem.notCheckable = true
menuItem.r = color[1]
menuItem.g = color[2]
menuItem.b = color[3]
menuItem.opacity = color[4]
menuItem.func = function()
Bagshui:CloseMenus(_G.UIDROPDOWNMENU_MENU_LEVEL, nil, true)
settingsStorage[settingName] = color
settingUpdateFunction()
self.menus:Refresh(menuLevel, true)
self:AddToColorHistory(color)
end
menuItem._bagshuiColorSwatchFunc = menuItem.func
else
menuItem._bagshuiHide = true
end
else
-- Parent menu item to open the submenu -- add color swatch and related functions
-- to properly update colors as the color picker is changed, while handling things
-- correctly so that the value is only saved if Okay is clicked.
-- Opacity management variables that will be captured into the cancelFunc closure below.
-- This is necessary because since we don't receive opacity as a parameter to cancelFunc.
local hasOpacity = false
local currentOpacity = (currentSettingValue and currentSettingValue[4])
or (defaultValue and defaultValue[4])
or 1
-- Menu item updates
menuItem.hasArrow = true
menuItem.value = settingName
menuItem.hasColorSwatch = true
menuItem.r = (currentSettingValue and currentSettingValue[1]) or (defaultValue and defaultValue[1]) or 1
menuItem.g = (currentSettingValue and currentSettingValue[2]) or (defaultValue and defaultValue[2]) or 1
menuItem.b = (currentSettingValue and currentSettingValue[3]) or (defaultValue and defaultValue[3]) or 1
if settingInfo.hasOpacity then
hasOpacity = true
menuItem.hasOpacity = true
-- Inverting opacity slider because it's insane that 100% means transparent and 0% means opaque.
menuItem.opacity = 1.0 - currentOpacity
end
local oldColor = { menuItem.r, menuItem.g, menuItem.b, menuItem.opacity }
-- Shared function to reopen the menu that triggered the color picker.
-- Getting submenus to open would take more digging than is worth it.
local function reopenMenu()
if
self.menus._openMenu_last_MenuType == menuType
and _G.UIDROPDOWNMENU_OPEN_MENU == Bagshui.menuFrame.bagshuiData.name
then
self.menus:OpenMenu(
menuType,
self.menus._openMenu_last_Arg1,
self.menus._openMenu_last_Arg2,
_G.UIParent,
self.menus._openMenu_last_UIParentXOffset,
self.menus._openMenu_last_UIParentYOffset
)
end
end
-- Change setting on color / opacity change.
local swatchFuncCallCount = 0
menuItem.swatchFunc = function()
local color = { _G.ColorPickerFrame:GetColorRGB() }
if hasOpacity then
-- Un-invert opacity value since we're inverting it for the UI (see menuItem.opacity note above).
table.insert(color, 1.0 - _G.OpacitySliderFrame:GetValue())
end
settingsStorage[settingName] = color
settingUpdateFunction()
-- Only perform actions when Okay is clicked. swatchFunc() gets called
-- immediately when the ColorPickerFrame is opened, so we skip it the
-- first time. After that, we can tell whether Okay was clicked by
-- checking whether ColorPickerFrame is still visible.
if swatchFuncCallCount > 0 and not _G.ColorPickerFrame:IsVisible() then
self:AddToColorHistory(oldColor)
self:AddToColorHistory(color)
reopenMenu()
end
swatchFuncCallCount = swatchFuncCallCount + 1
end
menuItem.opacityFunc = menuItem.swatchFunc
-- Color picker Cancel button click -- revert the setting.
menuItem.cancelFunc = function(previousValues)
local color
-- Allow reverting a color setting to nil for Groups, which need
-- nil to indicate the default color should be used.
if currentSettingValue ~= nil then
color = {
previousValues.r,
previousValues.g,
previousValues.b,
}
-- Use upvalues that were created above since previousValues doesn't contain opacity.
if hasOpacity then
table.insert(color, currentOpacity)
end
end
settingsStorage[settingName] = color
settingUpdateFunction()
reopenMenu()
end
menuItem.func = self._generateSettingsMenuItem_ResetOnModifierKeys
end
elseif settingInfo.type == BS_SETTING_TYPE.TRIGGER then
-- Triggers -- just update the setting to true and the Settings class takes care of the rest.
menuItem.checked = false
menuItem.keepShownOnClick = false
menuItem.func = function()
settingsStorage[settingName] = true
end
end
-- Decide whether the menu item should be disabled.
if disabledByFunc ~= nil then
menuItem.disabled = disabledByFunc
end
end
--- Add the given color to the global Bagshui color picker history.
--- @param color table Color to add: `{ r, g, b, [a] }`.
function Inventory:AddToColorHistory(color)
-- Due to float shenanigans, colors values may not be seen as equal unless we round them.
for i = 1, 4 do
color[i] = BsUtil.Round(color[i], 4)
end
-- Add color to first position if it's not already there.
if
not Bagshui.colorHistory[1]
or (
Bagshui.colorHistory[1][1] ~= color[1]
or Bagshui.colorHistory[1][2] ~= color[2]
or Bagshui.colorHistory[1][3] ~= color[3]
or Bagshui.colorHistory[1][4] ~= color[4]
)
then
table.insert(Bagshui.colorHistory, 1, color)
end
-- Remove any duplicates.
for i = table.getn(Bagshui.colorHistory), 2, -1 do
if
Bagshui.colorHistory[i][1] == color[1]
and Bagshui.colorHistory[i][2] == color[2]
and Bagshui.colorHistory[i][3] == color[3]
and Bagshui.colorHistory[i][4] == color[4]
then
table.remove(Bagshui.colorHistory, i)
end
end
-- Trim history if needed.
while table.getn(Bagshui.colorHistory) > COLOR_HISTORY_LIMIT do
table.remove(Bagshui.colorHistory)
end
end
--- When certain modifier keys are held down, reset the setting provided in the
--- arg1 table to default.
---@param arg1 table Menu item information for setting:
--- ```
--- {
--- settingName [string] = name of setting,
--- settingsStorage [table] = Settings class instance,
--- menuLevel [number] = Level of menu item,
--- }
--- ```
---@param arg2 any? Ignored.
---@param onlyRefreshOnReset boolean? Don't refresh the menu unless the setting was reset.
---@return boolean settingWasReset
function Inventory:ResetSettingOnModifierKeys(arg1, arg2, onlyRefreshOnReset)
if _G.IsAltKeyDown() and _G.IsControlKeyDown() and _G.IsShiftKeyDown() then
arg1.settingsStorage:SetDefaults(true, nil, nil, arg1.settingName)
self.menus:Refresh(arg1.menuLevel)
return true
elseif not onlyRefreshOnReset then
self.menus:Refresh(arg1.menuLevel)
end
return false
end
end)