From aea01043844975d0e6698574427f21abacc9e986 Mon Sep 17 00:00:00 2001 From: Vollmer Date: Sat, 31 Aug 2024 22:17:09 +0200 Subject: [PATCH] [Feature] Profile options (#43) * implement tab system for menu * update annotations * merge MenuFrame.lua into Menu.lua * ensure LoadLayoutDB is called when UnitFramesTab is opened * show and hide selected tab when menu hides * prevent ShowMenu running when menu is already shown * move Unit/Widget add fns into UnitFramesTab.lua * Limit when LoadPageDB runs * OnLoad hide blizzard frames based on CurrentLayoutTable instead of SelectedLayoutTable * implement GeneralTab * impl MasterLayout DB fns * properly update widgetList * use masterLayout for widgets profile * update layout when changing master layout * check against master layout when updating unit button layout * get raw value of masterlayout when determining which to use * change remaining widget updates to use current widget table * update annotation for IterateAllUnitButtons * add tooltip for master layout * update tab buttons positioning * only set widget as selected when in correct layout * better tooltip for master layout * add a title to the menu frame * impl copyLayoutFrom * a bit of cleanup * impl DB.CopyFullLayout * finish implementing copyLayoutFrom * make generalTab a bit shorter --- Annotations.lua | 2 + Cell_UnitFrames.toc | 3 +- Core/Init.lua | 1 + Core/OnLoad.lua | 4 +- Data/DBUtil.lua | 31 ++++ Data/Database.lua | 73 +++++--- Debug/Debug.lua | 2 +- Locales/enUS.lua | 20 +++ Menu/Builder.lua | 20 +-- Menu/GeneralTab.lua | 181 +++++++++++++++++++ Menu/Menu.lua | 206 +++++++++++++++++++--- Menu/{MenuFrame.lua => UnitFramesTab.lua} | 185 ++++++++++--------- UnitFrames/MenuOptions.lua | 12 +- Util/Handler.lua | 15 +- Util/Utils.lua | 30 +++- Widgets/Auras/Updater.lua | 2 +- Widgets/Bars/CastBar.lua | 2 +- Widgets/Bars/ShieldBar.lua | 2 +- Widgets/Texts/HealthText.lua | 2 +- Widgets/Texts/NameText.lua | 2 +- Widgets/Texts/PowerText.lua | 2 +- 21 files changed, 633 insertions(+), 164 deletions(-) create mode 100644 Menu/GeneralTab.lua rename Menu/{MenuFrame.lua => UnitFramesTab.lua} (59%) diff --git a/Annotations.lua b/Annotations.lua index 205bfcd..015edfd 100644 --- a/Annotations.lua +++ b/Annotations.lua @@ -43,6 +43,8 @@ ---@field SetSelected function ---@field SetFont function ---@field button button +---@field ClearSelected function +---@field GetSelected function ---@class CellColorPicker: Frame, BackdropTemplate ---@field SetColor function diff --git a/Cell_UnitFrames.toc b/Cell_UnitFrames.toc index 155d9d5..908d56f 100644 --- a/Cell_UnitFrames.toc +++ b/Cell_UnitFrames.toc @@ -34,8 +34,9 @@ Core/SlashCommands.lua Menu/Builder.lua Menu/AuraFilterList.lua -Menu/MenuFrame.lua Menu/Menu.lua +Menu/GeneralTab.lua +Menu/UnitFramesTab.lua Widgets/Common.lua diff --git a/Core/Init.lua b/Core/Init.lua index eb603d5..b63e553 100644 --- a/Core/Init.lua +++ b/Core/Init.lua @@ -30,5 +30,6 @@ CUF.Builder = {} ---@field testMode boolean ---@field isMenuOpen boolean ---@field isRetail boolean +---@field selectedTab string CUF.vars = {} CUF.unitButtons = {} diff --git a/Core/OnLoad.lua b/Core/OnLoad.lua index 5a545cc..da0ca53 100644 --- a/Core/OnLoad.lua +++ b/Core/OnLoad.lua @@ -20,7 +20,7 @@ local function OnCellInitialUpdateLayout(_layout) -- Hide Blizzard Unit Frames for _, unit in pairs(CUF.constants.UNIT) do - if CUF.DB.SelectedLayoutTable()[unit].enabled then + if CUF.DB.CurrentLayoutTable()[unit].enabled then CUF:HideBlizzardUnitFrame(unit) end end @@ -52,7 +52,7 @@ local function OnCellInitialUpdateLayout(_layout) function(kind) CUF:Fire("UpdateAppearance", kind) end) -- Init widgets - CUF:Fire("UpdateWidget", CUF.vars.selectedLayout) + CUF:Fire("UpdateWidget", CUF.DB.GetMasterLayout()) Cell:UnregisterCallback("UpdateLayout", "CUF_Initial_UpdateLayout") end diff --git a/Data/DBUtil.lua b/Data/DBUtil.lua index 60aaeee..4033cd0 100644 --- a/Data/DBUtil.lua +++ b/Data/DBUtil.lua @@ -13,6 +13,13 @@ DB.PropsToOnlyInit = { whitelist = true, } +-- Copy ALL settings from one layout to another +---@param from string +---@param to string +function DB.CopyFullLayout(from, to) + CellDB.layouts[to].CUFUnits = CUF.Util:CopyDeep(DB.GetLayoutTable(from)) +end + -- Make sure that we have an active CellDB and that it has all the UnitLayouts we need ---@return false? noCellDB If CellDB is not present function DB.VerifyDB() @@ -38,4 +45,28 @@ function DB.VerifyDB() end end end + + -- Make sure that we have a valid master layout + DB.VerifyMasterLayout() +end + +function DB.VerifyMasterLayout() + local masterLayout = DB.GetMasterLayout(true) + if masterLayout == "CUFLayoutMasterNone" then return end + + local masterLayoutIsValid = false + + for layoutName, _ in pairs(CellDB.layouts) do + if layoutName == masterLayout then + masterLayoutIsValid = true + end + end + + if not masterLayoutIsValid then + CUF:Warn("Master layout is not valid, setting to default") + DB.SetMasterLayout("default") + end end + +CUF:RegisterCallback("UpdateLayout", "CUF_VerifyMasterLayout", DB.VerifyMasterLayout) +CUF:RegisterCallback("LoadPageDB", "CUF_VerifyMasterLayout", DB.VerifyMasterLayout) diff --git a/Data/Database.lua b/Data/Database.lua index 1e79df9..9a5ba32 100644 --- a/Data/Database.lua +++ b/Data/Database.lua @@ -5,7 +5,7 @@ local CUF = select(2, ...) local DB = CUF.DB ----------------------------------------- --- Getters +-- MARK: Layout Getters ----------------------------------------- -- Returns CUF UnitLayoutTable from CellDB @@ -34,45 +34,78 @@ function DB.SelectedLayoutTable() return DB.GetLayoutTable(CUF.vars.selectedLayout) end --- Returns active layout table ----@return UnitLayoutTable -function DB.CurrentLayoutTable() - return DB.GetLayoutTable(Cell.vars.currentLayout) -end - ---@param unit Unit? ----@param layout string? ---@return WidgetTables -function DB.GetAllWidgetTables(unit, layout) - return DB.GetUnit(layout or CUF.vars.selectedLayout, unit or CUF.vars.selectedUnit).widgets +function DB.GetSelectedWidgetTables(unit) + return DB.GetUnit(CUF.vars.selectedLayout, unit or CUF.vars.selectedUnit).widgets end ---@param which WIDGET_KIND ---@param unit Unit? ----@param layout string? ---@return WidgetTable -function DB.GetWidgetTable(which, unit, layout) - return DB.GetAllWidgetTables(unit, layout)[which] +function DB.GetSelectedWidgetTable(which, unit) + return DB.GetSelectedWidgetTables(unit)[which] end ---@param which "buffs"|"debuffs" ---@param kind "blacklist"|"whitelist" ---@param unit Unit? ----@param layout string? ---@return table -function DB.GetAuraFilter(which, kind, unit, layout) - return DB.GetAllWidgetTables(unit, layout)[which].filter[kind] +function DB.GetAuraFilter(which, kind, unit) + return DB.GetSelectedWidgetTables(unit)[which].filter[kind] +end + +-- Returns active layout table +---@return UnitLayoutTable +function DB.CurrentLayoutTable() + return DB.GetLayoutTable(DB.GetMasterLayout()) +end + +---@param unit Unit +---@return WidgetTables +function DB.GetCurrentWidgetTables(unit) + return DB.CurrentLayoutTable()[unit].widgets +end + +---@param which WIDGET_KIND +---@param unit Unit +---@return WidgetTable +function DB.GetCurrentWidgetTable(which, unit) + return DB.GetCurrentWidgetTables(unit)[which] end ----------------------------------------- --- Setters +-- MARK: Layout Setters ----------------------------------------- ---@param which "buffs"|"debuffs" ---@param kind "blacklist"|"whitelist" ---@param value table ---@param unit Unit? ----@param layout string? -function DB.SetAuraFilter(which, kind, value, unit, layout) - DB.GetAllWidgetTables(unit, layout)[which].filter[kind] = value +function DB.SetAuraFilter(which, kind, value, unit) + DB.GetSelectedWidgetTables(unit)[which].filter[kind] = value +end + +----------------------------------------- +-- MARK: General Getters +----------------------------------------- + +---@param rawValue boolean? +---@return string +function DB.GetMasterLayout(rawValue) + local layout = CUF_DB.masterLayout + if layout == "CUFLayoutMasterNone" and not rawValue then + return Cell.vars.currentLayout + end + + return CUF_DB.masterLayout +end + +----------------------------------------- +-- MARK: General Setters +----------------------------------------- + +---@param layout string +function DB.SetMasterLayout(layout) + CUF_DB.masterLayout = layout end diff --git a/Debug/Debug.lua b/Debug/Debug.lua index 35df1e5..7882e79 100644 --- a/Debug/Debug.lua +++ b/Debug/Debug.lua @@ -18,7 +18,7 @@ function Debug:InitDebugWindow() self.window:AddVar( "selectedLayoutTable", function() CUF:DevAdd(CUF.DB.SelectedLayoutTable(), "selectedLayoutTable") end) self.window:AddVar("selectedWidgetTable", - function() CUF:DevAdd(CUF.DB.GetAllWidgetTables(), "selectedWidgetTable") end) + function() CUF:DevAdd(CUF.DB.GetSelectedWidgetTables(), "selectedWidgetTable") end) self.window:AddVar("CUF.vars", function() CUF:DevAdd(CUF.vars, "CUF.vars") end) self.window:AddVar("CUF_DB", function() CUF:DevAdd(CUF_DB, "CUF_DB") end) self.window:AddVar("Buttons", function() CUF:DevAdd(CUF.unitButtons, "unitButtons") end) diff --git a/Locales/enUS.lua b/Locales/enUS.lua index 3c18266..7a11bb1 100644 --- a/Locales/enUS.lua +++ b/Locales/enUS.lua @@ -5,6 +5,26 @@ local CUF = select(2, ...) local L = Cell.L CUF.L = L +-- Tabs +L.unitFramesTab = "Unit Frames" +L.generalTab = "General" + +L.MasterLayout = "Master Layout" +L.CUFLayoutMasterNone = "|cffffb5c5None|r" +L.MasterLayoutTooltip = [[The layout to use for |cFFFFD700Cell UnitFrames|r. + +Selecting a specific layout will always use that layout +regardless of |cFFFFD700Cell|r Auto Switch settings. + +Selecting |cffffb5c5None|r will Auto Switch to use the +currently active layout in |cFFFFD700Cell|r.]] + +L.CopyLayoutFrom = "Copy Layout From" +L.CopyFromTooltip = [[|cFFFF0000This will overwrite all settings in the current layout!|r + +Copy settings from another layout]] +L.CopyFromPopUp = "Copy settings from |cFFFFD700%s|r to |cFFFFD700%s|r?" + -- Units L.targettarget = "TargetTarget" L.player = "Player" diff --git a/Menu/Builder.lua b/Menu/Builder.lua index 2e25cfe..2b87932 100644 --- a/Menu/Builder.lua +++ b/Menu/Builder.lua @@ -63,7 +63,7 @@ Builder.MenuOptions = { ---@field pageName string ---@field options table ----@param settingsFrame MenuFrame.settingsFrame +---@param settingsFrame UnitsFramesTab.settingsFrame ---@param widgetName WIDGET_KIND ---@param ... MenuOptions ---@return WidgetMenuPage @@ -185,7 +185,7 @@ end ---@param optionPath string ---@param newValue any local function HandleWidgetOption(widgetName, optionPath, newValue) - local widgetTable = DB.GetWidgetTable(widgetName) + local widgetTable = DB.GetSelectedWidgetTable(widgetName) local function traversePath(tbl, pathParts, value) for i = 1, #pathParts - 1 do @@ -617,7 +617,7 @@ function Builder:CreateTextColorOptions(parent, widgetName, includePowerType) f.dropdown.Set_DB = function(...) HandleWidgetOption(...) - if DB.GetWidgetTable(widgetName).color.type == const.ColorType.CUSTOM then + if DB.GetSelectedWidgetTable(widgetName).color.type == const.ColorType.CUSTOM then f.colorPicker:Show() else f.colorPicker:Hide() @@ -631,7 +631,7 @@ function Builder:CreateTextColorOptions(parent, widgetName, includePowerType) local function LoadPageDB() f.colorPicker:SetColor(unpack(HandleWidgetOption(widgetName, "color.rgb"))) - if DB.GetWidgetTable(widgetName).color.type == const.ColorType.CUSTOM then + if DB.GetSelectedWidgetTable(widgetName).color.type == const.ColorType.CUSTOM then f.colorPicker:Show() else f.colorPicker:Hide() @@ -1186,16 +1186,16 @@ function Builder:CreateAuraFontOptions(parent, widgetName, kind) self:AnchorBelow(f.fontOptions.shadowCB, f.fontOptions.outlineDropdown) f.colorPicker = Cell:CreateColorPicker(f, L["Color"], false, function(r, g, b, a) - DB.GetWidgetTable(widgetName).font[kind].rgb[1] = r - DB.GetWidgetTable(widgetName).font[kind].rgb[2] = g - DB.GetWidgetTable(widgetName).font[kind].rgb[3] = b + DB.GetSelectedWidgetTable(widgetName).font[kind].rgb[1] = r + DB.GetSelectedWidgetTable(widgetName).font[kind].rgb[2] = g + DB.GetSelectedWidgetTable(widgetName).font[kind].rgb[3] = b end) self:AnchorBelow(f.colorPicker, f.fontOptions.sizeSlider) local function LoadPageDB() - f.colorPicker:SetColor(DB.GetWidgetTable(widgetName).font[kind].rgb[1], - DB.GetWidgetTable(widgetName).font[kind].rgb[2], - DB.GetWidgetTable(widgetName).font[kind].rgb[3]) + f.colorPicker:SetColor(DB.GetSelectedWidgetTable(widgetName).font[kind].rgb[1], + DB.GetSelectedWidgetTable(widgetName).font[kind].rgb[2], + DB.GetSelectedWidgetTable(widgetName).font[kind].rgb[3]) end Handler:RegisterOption(LoadPageDB, widgetName, "CheckBox") diff --git a/Menu/GeneralTab.lua b/Menu/GeneralTab.lua new file mode 100644 index 0000000..b4b765e --- /dev/null +++ b/Menu/GeneralTab.lua @@ -0,0 +1,181 @@ +---@class CUF +local CUF = select(2, ...) + +local Cell = CUF.Cell + +local L = CUF.L +local DB = CUF.DB + +local Menu = CUF.Menu + +---@class GeneralTab: Menu.Tab +local generalTab = {} +generalTab.id = "generalTab" +generalTab.height = 150 +generalTab.paneHeight = 17 + +Menu:AddTab(generalTab) + +function generalTab:IsShown() + return generalTab.window and generalTab.window:IsShown() +end + +--- Replaces "default" with _G.DEFAULT +---@param layoutName string +---@return string +local function normalizeLayoutName(layoutName) + ---@diagnostic disable-next-line: undefined-field + return layoutName == "default" and _G.DEFAULT or layoutName +end + +------------------------------------------------- +-- MARK: Copy From +------------------------------------------------- + +---@class CopyFrom: Frame +local copyLayoutFrom = {} + +function copyLayoutFrom.SetLayoutItems() + if not generalTab:IsShown() then return end + --CUF:Log("|cff00ccffgeneralTab SetCopyFromItems|r") + + local dropdownItems = {} + + for layoutName, _ in pairs(CellDB.layouts) do + if layoutName ~= DB.GetMasterLayout() then + tinsert(dropdownItems, { + ["text"] = normalizeLayoutName(layoutName), + ["value"] = layoutName, + ["onClick"] = function() + local popup = CUF:CreateConfirmPopup(Menu.window, 300, + string.format(L.CopyFromPopUp, normalizeLayoutName(layoutName), + normalizeLayoutName(DB.GetMasterLayout())), + function() + DB.CopyFullLayout(layoutName, DB.GetMasterLayout()) + CUF:Fire("UpdateUnitButtons") + CUF:Fire("UpdateWidget", DB.GetMasterLayout()) + end, nil, true) + popup:SetPoint("TOP", 0, -70) + copyLayoutFrom.layoutDropdown:ClearSelected() + end, + }) + end + end + + copyLayoutFrom.layoutDropdown:SetItems(dropdownItems) + copyLayoutFrom.layoutDropdown:ClearSelected() +end + +CUF:RegisterCallback("UpdateLayout", "CUF_CopyFrom_SetLayoutItems", copyLayoutFrom.SetLayoutItems) +CUF:RegisterCallback("LoadPageDB", "CUF_CopyFrom_SetLayoutItems", copyLayoutFrom.SetLayoutItems) + +function copyLayoutFrom:Create() + --CUF:Log("|cff00ccffgeneralTab CreateCopyFrom|r") + + local sectionWidth = (generalTab.window:GetWidth() / 2) - 5 + + local pane = Cell:CreateTitledPane(generalTab.window, L.CopyLayoutFrom, sectionWidth, generalTab.paneHeight) + pane:SetPoint("TOPRIGHT") + + ---@type CellDropdown + self.layoutDropdown = Cell:CreateDropdown(generalTab.window, sectionWidth - 10) + self.layoutDropdown:SetPoint("TOPLEFT", pane, "BOTTOMLEFT", 5, -10) + CUF:SetTooltips(self.layoutDropdown, "ANCHOR_TOPLEFT", 0, 3, L.CopyLayoutFrom, L.CopyFromTooltip) +end + +------------------------------------------------- +-- MARK: Layout Profile +------------------------------------------------- + +---@class LayoutProfile: Frame +local layoutProfile = {} + +function layoutProfile:SetLayoutItems() + if not generalTab:IsShown() then return end + --CUF:Log("|cff00ccffgeneralTab SetLayoutItems|r") + + local dropdownItems = { { + ["text"] = L.CUFLayoutMasterNone, + ["value"] = "CUFLayoutMasterNone", + ["onClick"] = function() + DB.SetMasterLayout("CUFLayoutMasterNone") + CUF:Fire("UpdateUnitButtons") + CUF:Fire("UpdateWidget", Cell.vars.currentLayout) + copyLayoutFrom.SetLayoutItems() + end, + } } + + for layoutName, _ in pairs(CellDB.layouts) do + tinsert(dropdownItems, { + ---@diagnostic disable-next-line: undefined-field + ["text"] = layoutName == "default" and _G.DEFAULT or layoutName, + ["value"] = layoutName, + ["onClick"] = function() + DB.SetMasterLayout(layoutName) + CUF:Fire("UpdateUnitButtons") + CUF:Fire("UpdateWidget", layoutName) + copyLayoutFrom.SetLayoutItems() + end, + }) + end + + layoutProfile.layoutDropdown:SetItems(dropdownItems) + layoutProfile.layoutDropdown:SetSelectedValue(DB.GetMasterLayout(true)) +end + +CUF:RegisterCallback("UpdateLayout", "CUF_LayoutProfile_SetLayoutItems", layoutProfile.SetLayoutItems) +CUF:RegisterCallback("LoadPageDB", "CUF_LayoutProfile_SetLayoutItems", layoutProfile.SetLayoutItems) + +function layoutProfile:Create() + --CUF:Log("|cff00ccffgeneralTab CreateLayoutProfile|r") + + local sectionWidth = (generalTab.window:GetWidth() / 2) - 5 + + local layoutPane = Cell:CreateTitledPane(generalTab.window, L.MasterLayout, sectionWidth, generalTab.paneHeight) + layoutPane:SetPoint("TOPLEFT") + + ---@type CellDropdown + self.layoutDropdown = Cell:CreateDropdown(generalTab.window, sectionWidth - 10) + self.layoutDropdown:SetPoint("TOPLEFT", layoutPane, "BOTTOMLEFT", 5, -10) + CUF:SetTooltips(self.layoutDropdown, "ANCHOR_TOPLEFT", 0, 3, L.MasterLayout, L.MasterLayoutTooltip) +end + +------------------------------------------------- +-- MARK: Show/Hide +------------------------------------------------- + +function generalTab:ShowTab() + CUF:Log("|cff00ccffShow generalTab|r") + if not self.window then + self:Create() + self.init = true + end + + self.window:Show() + layoutProfile:SetLayoutItems() + copyLayoutFrom:SetLayoutItems() +end + +function generalTab:HideTab() + if not self.window or not self.window:IsShown() then return end + CUF:Log("|cff00ccffHide generalTab|r") + self.window:Hide() +end + +------------------------------------------------- +-- MARK: Create +------------------------------------------------- + +function generalTab:Create() + CUF:Log("|cff00ccffCreate generalTab|r") + + local sectionWidth = Menu.tabAnchor:GetWidth() + + self.window = CUF:CreateFrame("CUF_Menu_UnitFrame", Menu.window, + sectionWidth, + self.height, true) + self.window:SetPoint("TOPLEFT", Menu.tabAnchor, "TOPLEFT") + + layoutProfile:Create() + copyLayoutFrom:Create() +end diff --git a/Menu/Menu.lua b/Menu/Menu.lua index 3d80d3a..7f64878 100644 --- a/Menu/Menu.lua +++ b/Menu/Menu.lua @@ -2,37 +2,31 @@ local CUF = select(2, ...) local Cell = CUF.Cell -local Util = CUF.Util +local F = Cell.funcs -local menuWindow = CUF.MenuWindow +local L = CUF.L +local Util = CUF.Util +local Handler = CUF.Handler ---@class CUF.Menu ----@field selectedWidgetTable WidgetTable ----@field unitsToAdd table ----@field widgetsToAdd table +---@field window CellCombatFrame +---@field tabs table +---@field tabsToAdd Menu.Tab[] +---@field tabButtons Menu.TabButton[] +---@field selectedTab Menu.Tab? local menu = {} -menu.window = menuWindow -menu.unitsToAdd = {} -menu.widgetsToAdd = {} +menu.tabs = {} +menu.tabsToAdd = {} +menu.tabButtons = {} menu.init = false menu.hookInit = false +menu.baseWidth = 450 +menu.paneHeight = 22 +menu.paneBuffer = 10 +menu.inset = 5 CUF.Menu = menu ----@param unit function -function menu:AddUnit(unit) - --CUF:Log("Menu - AddUnit") - table.insert(self.unitsToAdd, unit) -end - ----@param widgetName WIDGET_KIND ----@param ... MenuOptions -function menu:AddWidget(widgetName, ...) - --CUF:Log("Menu - AddWidget") - table.insert(self.widgetsToAdd, - { ["widgetName"] = widgetName, ["options"] = { ... } }) -end - ------------------------------------------------- -- MARK: Update vars ------------------------------------------------- @@ -52,7 +46,7 @@ function menu:UpdateSelectedPages(unit, widget) end -- Prevent excessive calls when initializing - if not menu.window.init then return end + if not menu.init then return end CUF:Fire("LoadPageDB", unit, widget) end @@ -63,17 +57,171 @@ end -- -- Fires `LoadPageDB` and `UpdateVisibility` callbacks ---@param layout string -local function LoadLayoutDB(layout) +function menu:LoadLayoutDB(layout) CUF:Log("|cff00ff00LoadLayoutDB:|r", layout, CUF.vars.selectedUnit, CUF.vars.selectedWidget) CUF.DB.VerifyDB() CUF.vars.selectedLayout = layout - menu.window:ShowMenu() + menu:ShowMenu() CUF:Fire("LoadPageDB", CUF.vars.selectedUnit, CUF.vars.selectedWidget) CUF:Fire("UpdateVisibility") end +------------------------------------------------- +-- MARK: Menu Window +------------------------------------------------- + +---@class Menu.Tab +---@field id string +---@field window Frame +---@field Create function +---@field ShowTab function +---@field HideTab function + +--- Initialize tabs buttons and adds them to the tab pane +function menu:InitTabs() + --CUF:Log("menu - InitUnits") + local prevButton + local prevAnchor + local idx = 1 + + for _, tab in pairs(self.tabsToAdd) do + ---@cast tab Menu.Tab + self.tabs[tab.id] = tab + + ---@class Menu.TabButton: CellButton + local tabButton = CUF:CreateButton(self.window, L[tab.id], { 100, self.paneHeight }) + tabButton.id = tab.id + + if prevButton then + -- Max 4 buttons per row + if idx % 4 == 0 then + tabButton:SetPoint("BOTTOMRIGHT", prevAnchor, "TOPRIGHT", 0, 0) + idx = 1 + prevAnchor = tabButton + + self.window:SetHeight(self.window:GetHeight() + self.paneHeight) + self.tabPane:SetHeight(self.tabPane:GetHeight() + self.paneHeight) + else + tabButton:SetPoint("TOPLEFT", prevButton, "TOPRIGHT", -1, 0) + idx = idx + 1 + end + else + tabButton:SetPoint("BOTTOMLEFT", self.tabPane, "BOTTOMLEFT", 0, 0) + prevAnchor = tabButton + end + prevButton = tabButton + + table.insert(self.tabButtons, tabButton) + end + + Cell:CreateButtonGroup(self.tabButtons, function(which, b) + self:SetTab(which) + end) +end + +--- Show the menu +--- +--- Initializes the menu if it hasn't been initialized yet +function menu:ShowMenu() + if self.window and self.window:IsShown() then return end + CUF:Log("|cff00ccffShow Menu|r") + if not self.window then + self:CreateMenu() + + self.window:Show() + + self.tabButtons[1]:Click() + + self.init = true + CUF.vars.isMenuOpen = true + + return + end + + self.window:Show() + self.selectedTab:ShowTab() + + CUF.vars.isMenuOpen = true +end + +--- Hide the menu and the current tab +function menu:HideMenu() + if not self.window or not self.window:IsShown() then return end + CUF:Log("|cff00ccffHide Menu|r") + self.window:Hide() + self.selectedTab:HideTab() + + CUF.vars.isMenuOpen = false +end + +---@param which string +function menu:SetTab(which) + -- Hide old unit + if self.selectedTab then + self.selectedTab:HideTab() + end + CUF.vars.selectedTab = which + + self.selectedTab = self.tabs[which] + self.selectedTab:ShowTab() + + self.window:SetHeight(self.selectedTab.window:GetHeight() + self.paneHeight + self.paneBuffer) +end + +---@param tab Menu.Tab +function menu:AddTab(tab) + table.insert(self.tabsToAdd, tab) +end + +function menu:CreateMenu() + CUF:Log("|cff00ccffCreate Menu|r") + local optionsFrame = Cell.frames.optionsFrame + + ---@class CellCombatFrame + self.window = CUF:CreateFrame("CUF_Menu", optionsFrame, self.baseWidth, 300) + self.window:SetPoint("TOPRIGHT", CellLayoutsPreviewButton, "BOTTOMRIGHT", 0, -self.inset) + + -- mask + F:ApplyCombatProtectionToFrame(self.window) + Cell:CreateMask(self.window, nil, { 1, -1, -1, 1 }) + self.window.mask:Hide() + + -- Title + local titleFrame = CUF:CreateFrame(nil, self.window, 120, 20, false, true) + titleFrame:SetPoint("BOTTOMLEFT", self.window, "TOPLEFT", 0, -1) + + local pad = 5 + + local title = titleFrame:CreateFontString(nil, "OVERLAY", CUF.constants.FONTS.CLASS_TITLE) + title:SetPoint("BOTTOMLEFT", pad, pad) + title:SetText("Cell UnitFrame") + title:SetTextScale(1.5) + titleFrame:SetHeight(title:GetStringHeight() + pad * 2) + titleFrame:SetWidth(title:GetStringWidth() + pad * 2) + + -- Tabs + self.tabPane = Cell:CreateTitledPane(self.window, nil, self.baseWidth, self.paneHeight) + self.tabPane:SetPoint("TOPLEFT") + + -- Repoint so it's anchored to bottom + self.tabPane.line:ClearAllPoints() + self.tabPane.line:SetPoint("BOTTOMLEFT", self.tabPane, "BOTTOMLEFT") + self.tabPane.line:SetPoint("BOTTOMRIGHT", self.tabPane, "BOTTOMRIGHT") + + local gap = self.inset * 2 + local anchorWidth = self.baseWidth - gap + self.tabAnchor = CUF:CreateFrame(nil, self.tabPane, anchorWidth, 1, true) + self.tabAnchor:SetPoint("TOPLEFT", self.tabPane, "BOTTOMLEFT", self.inset, -self.paneBuffer) + + self:InitTabs() + + hooksecurefunc(optionsFrame, "Hide", function() + self:HideMenu() + end) +end + ------------------------------------------------- -- MARK: Callbacks - Hooks ------------------------------------------------- @@ -103,11 +251,11 @@ local function UpdatePreview() hooksecurefunc(layoutDropdown, "SetSelectedValue", function(self) --CUF:Log("Cell_SetSelectedValue", self:GetSelected()) - LoadLayoutDB(self:GetSelected()) + menu:LoadLayoutDB(self:GetSelected()) end) -- Initial load - LoadLayoutDB(layoutDropdown:GetSelected()) + menu:LoadLayoutDB(layoutDropdown:GetSelected()) -- Unhook Cell:UnregisterCallback("UpdatePreview", "CUF_UpdatePreview") @@ -117,8 +265,8 @@ end local function ShowTab(tab) --CUF:Log("Cell_ShowTab", tab) if tab ~= "layouts" then - menuWindow:HideMenu() - elseif not menu.window.init then + menu:HideMenu() + elseif not menu.init then -- Inital hook Cell:RegisterCallback("UpdatePreview", "CUF_UpdatePreview", UpdatePreview) end diff --git a/Menu/MenuFrame.lua b/Menu/UnitFramesTab.lua similarity index 59% rename from Menu/MenuFrame.lua rename to Menu/UnitFramesTab.lua index 8b0321d..f1aece2 100644 --- a/Menu/MenuFrame.lua +++ b/Menu/UnitFramesTab.lua @@ -3,28 +3,46 @@ local CUF = select(2, ...) local Cell = CUF.Cell local L = CUF.L -local F = Cell.funcs local Builder = CUF.Builder local Handler = CUF.Handler ----@class MenuFrame ----@field window CellCombatFrame +---@class CUF.Menu +local Menu = CUF.Menu + +---@class UnitsFramesTab: Menu.Tab ---@field unitPages table ---@field unitPageButtons UnitMenuPageButton[] ---@field widgetPages table ---@field listButtons table -local menuWindow = {} -menuWindow.unitPages = {} -menuWindow.unitPageButtons = {} -menuWindow.widgetPages = {} -menuWindow.listButtons = {} -menuWindow.firstWidgetInList = nil +---@field selectedWidgetTable WidgetTable +---@field unitsToAdd table +---@field widgetsToAdd table +local unitFramesTab = {} +unitFramesTab.id = "unitFramesTab" +unitFramesTab.unitPages = {} +unitFramesTab.unitsToAdd = {} +unitFramesTab.widgetPages = {} +unitFramesTab.listButtons = {} +unitFramesTab.widgetsToAdd = {} +unitFramesTab.unitPageButtons = {} +unitFramesTab.firstWidgetInList = nil +unitFramesTab.widgetHeight = 400 +unitFramesTab.unitHeight = 180 +unitFramesTab.paneHeight = 17 + +Menu:AddTab(unitFramesTab) -CUF.MenuWindow = menuWindow +------------------------------------------------- +-- MARK: Setters +------------------------------------------------- + +function unitFramesTab:IsShown() + return unitFramesTab.window and unitFramesTab.window:IsShown() +end ---@param unit Unit -function menuWindow:SetUnitPage(unit) +function unitFramesTab:SetUnitPage(unit) -- Hide old unit if self.selectedUnitPage then self.selectedUnitPage.frame:Hide() @@ -33,13 +51,13 @@ function menuWindow:SetUnitPage(unit) self.selectedUnitPage = self.unitPages[unit] self.selectedUnitPage.frame:Show() - self:LoadWidgetList(unit) + self.LoadWidgetList(unit) CUF.Menu:UpdateSelectedPages(unit) end -- Update the selected widge ---@param widget WIDGET_KIND -function menuWindow:SetWidget(widget) +function unitFramesTab:SetWidget(widget) -- Hide old widget if self.selectedWidget then self.selectedWidget.frame:Hide() @@ -61,27 +79,30 @@ function menuWindow:SetWidget(widget) end ---@param unit Unit -function menuWindow:LoadWidgetList(unit) - self.widgetListFrame.scrollFrame:Reset() +function unitFramesTab.LoadWidgetList(unit) + if not unitFramesTab:IsShown() then return end + + unitFramesTab.widgetListFrame.scrollFrame:Reset() local optionCount = 0 - local widgetTable = CUF.DB.GetAllWidgetTables(unit) + local widgetTable = CUF.DB.GetSelectedWidgetTables(unit) local prevButton - self.firstWidgetInList = nil + unitFramesTab.firstWidgetInList = nil -- The list is ordered by load order from .toc - for _, widgetPage in pairs(CUF.Menu.widgetsToAdd) do + for _, widgetPage in pairs(unitFramesTab.widgetsToAdd) do local widgetName = widgetPage.widgetName local widget = widgetTable[widgetName] if widget then - if not self.listButtons[widgetName] then - self.listButtons[widgetName] = CUF:CreateButton(self.widgetListFrame.scrollFrame.content, " ", + if not unitFramesTab.listButtons[widgetName] then + unitFramesTab.listButtons[widgetName] = CUF:CreateButton( + unitFramesTab.widgetListFrame.scrollFrame.content, " ", { 20, 20 }, nil, "transparent-accent") end ---@class WidgetMenuPageButton: CellButton - local button = self.listButtons[widgetName] + local button = unitFramesTab.listButtons[widgetName] button:SetText(L[widgetName]) button:GetFontString():ClearAllPoints() button:GetFontString():SetPoint("LEFT", 5, 0) @@ -96,7 +117,7 @@ function menuWindow:LoadWidgetList(unit) button:SetTextColor(0.466, 0.466, 0.466, 1) end - button:SetParent(self.widgetListFrame.scrollFrame.content) + button:SetParent(unitFramesTab.widgetListFrame.scrollFrame.content) button:SetPoint("RIGHT") if not prevButton then button:SetPoint("TOPLEFT") @@ -106,45 +127,48 @@ function menuWindow:LoadWidgetList(unit) button:Show() prevButton = button - if not self.firstWidgetInList then - self.firstWidgetInList = widgetName + if not unitFramesTab.firstWidgetInList then + unitFramesTab.firstWidgetInList = widgetName end end end - self.widgetListFrame.scrollFrame:SetContentHeight(20, optionCount, -1) + unitFramesTab.widgetListFrame.scrollFrame:SetContentHeight(20, optionCount, -1) - Cell:CreateButtonGroup(self.listButtons, function(widget, b) - self:SetWidget(widget) + Cell:CreateButtonGroup(unitFramesTab.listButtons, function(widget, b) + unitFramesTab:SetWidget(widget) end) -- Make sure that the currently selected widget is valid - if self.selectedWidget then - if not widgetTable[self.selectedWidget.id] then - self.listButtons[self.firstWidgetInList]:Click() + if unitFramesTab.selectedWidget then + if not widgetTable[unitFramesTab.selectedWidget.id] then + unitFramesTab.listButtons[unitFramesTab.firstWidgetInList]:Click() end end end +CUF:RegisterCallback("LoadPageDB", "unitFramesTab_LoadWidgetList", unitFramesTab.LoadWidgetList) + ---@param layout string? ---@param unit Unit? ---@param widgetName WIDGET_KIND? -function menuWindow.UpdateWidgetListEnabled(layout, unit, widgetName, setting) +function unitFramesTab.UpdateWidgetListEnabled(layout, unit, widgetName, setting) + if not unitFramesTab:IsShown() then return end if not widgetName then return end if not setting == CUF.constants.OPTION_KIND.ENABLED then return end - if not menuWindow.listButtons[widgetName] then return end + if not unitFramesTab.listButtons[widgetName] then return end - if CUF.DB.GetWidgetTable(widgetName, unit, layout).enabled then - menuWindow.listButtons[widgetName]:SetTextColor(1, 1, 1, 1) + if CUF.DB.GetSelectedWidgetTable(widgetName, unit).enabled then + unitFramesTab.listButtons[widgetName]:SetTextColor(1, 1, 1, 1) else - menuWindow.listButtons[widgetName]:SetTextColor(0.466, 0.466, 0.466, 1) + unitFramesTab.listButtons[widgetName]:SetTextColor(0.466, 0.466, 0.466, 1) end end -CUF:RegisterCallback("UpdateWidget", "UpdateWidgetListEnabled", menuWindow.UpdateWidgetListEnabled) +CUF:RegisterCallback("UpdateWidget", "unitFramesTab_UpdateWidgetListEnabled", unitFramesTab.UpdateWidgetListEnabled) -function menuWindow:ShowMenu() - CUF:Log("|cff00ccffShow Menu|r") +function unitFramesTab:ShowTab() + CUF:Log("|cff00ccffShow unitFramesTab|r") if not self.window then self:Create() @@ -154,21 +178,21 @@ function menuWindow:ShowMenu() self.listButtons[self.firstWidgetInList]:Click() self.init = true - CUF.vars.isMenuOpen = true return end + Menu:LoadLayoutDB(CUF.vars.selectedLayout) + self.window:Show() - CUF.vars.isMenuOpen = true end -function menuWindow:HideMenu() - if not self.window or not self.window:IsShown() then return end - CUF:Log("|cff00ccffHide Menu|r") +function unitFramesTab:HideTab() + if not unitFramesTab:IsShown() then return end + CUF:Log("|cff00ccffHide unitFramesTab|r") self.window:Hide() - CUF.vars.isMenuOpen = false + -- Reset selected widget to hide previews Handler.UpdateSelected() end @@ -176,13 +200,13 @@ end -- MARK: Init ------------------------------------------------- -function menuWindow:InitUnits() +function unitFramesTab:InitUnits() --CUF:Log("menuWindow - InitUnits") local prevButton local prevAnchor local idx = 1 - for _, fn in pairs(CUF.Menu.unitsToAdd) do + for _, fn in pairs(self.unitsToAdd) do ---@type UnitsMenuPage local unit = fn(self) @@ -211,50 +235,47 @@ function menuWindow:InitUnits() end end -function menuWindow:InitWidgets() - --CUF:Log("menuWindow - InitWidgets") - - for _, widget in pairs(CUF.Menu.widgetsToAdd) do - ---@type WidgetMenuPage +function unitFramesTab:InitWidgets() + for _, widget in pairs(self.widgetsToAdd) do local widgetPage = Builder:CreateWidgetMenuPage(self.settingsFrame, widget.widgetName, unpack(widget.options)) self.widgetPages[widgetPage.id] = widgetPage end end +---@param unit function +function Menu:AddUnit(unit) + table.insert(unitFramesTab.unitsToAdd, unit) +end + +---@param widgetName WIDGET_KIND +---@param ... MenuOptions +function Menu:AddWidget(widgetName, ...) + table.insert(unitFramesTab.widgetsToAdd, + { ["widgetName"] = widgetName, ["options"] = { ... } }) +end + ------------------------------------------------- -- MARK: Create ------------------------------------------------- -function menuWindow:Create() - CUF:Log("|cff00ccffCreate Menu|r") - local optionsFrame = Cell.frames.optionsFrame +function unitFramesTab:Create() + CUF:Log("|cff00ccffCreate UnitFramesTab|r") - self.unitHeight = 180 - self.widgetHeight = 400 - self.baseWidth = 450 - self.paneHeight = 17 - - local buffer = 5 - local gap = buffer * 2 + local inset = Menu.inset local windowHeight = self.unitHeight + self.widgetHeight + (self.paneHeight * 2) - local sectionWidth = self.baseWidth - gap - ---@class CellCombatFrame - self.window = CUF:CreateFrame("CUF_Menu", optionsFrame, - self.baseWidth, - windowHeight) - self.window:SetPoint("TOPRIGHT", CellLayoutsPreviewButton, "BOTTOMRIGHT", 0, -buffer) + local sectionWidth = Menu.tabAnchor:GetWidth() - -- mask - F:ApplyCombatProtectionToFrame(self.window) - Cell:CreateMask(self.window, nil, { 1, -1, -1, 1 }) - self.window.mask:Hide() + self.window = CUF:CreateFrame("CUF_Menu_UnitFrame", Menu.window, + sectionWidth, + windowHeight, true) + self.window:SetPoint("TOPLEFT", Menu.tabAnchor, "TOPLEFT") -- Unit Buttons self.unitPane = Cell:CreateTitledPane(self.window, L.UnitFrames, sectionWidth, self.paneHeight) - self.unitPane:SetPoint("TOPLEFT", buffer, -buffer) + self.unitPane:SetPoint("TOPLEFT") -- Repoint so it's anchored to bottom self.unitPane.line:ClearAllPoints() @@ -262,7 +283,7 @@ function menuWindow:Create() self.unitPane.line:SetPoint("BOTTOMRIGHT", self.unitPane, "BOTTOMRIGHT") -- Unit Settings - self.unitSection = CUF:CreateFrame("CUF_Menu_Unit", self.unitPane, + self.unitSection = CUF:CreateFrame("CUF_Menu_UnitFrame_Unit", self.unitPane, sectionWidth, self.unitHeight, true, true) self.unitSection:SetPoint("TOPLEFT", self.unitPane, "BOTTOMLEFT") @@ -283,34 +304,30 @@ function menuWindow:Create() self.widgetPane.line:SetPoint("BOTTOMRIGHT", self.widgetPane, "BOTTOMRIGHT") -- settings frame - ---@class MenuFrame.settingsFrame: Frame + ---@class UnitsFramesTab.settingsFrame: Frame ---@field scrollFrame CellScrollFrame - self.settingsFrame = CUF:CreateFrame("CUF_Menu_Widget", self.widgetPane, + self.settingsFrame = CUF:CreateFrame("CUF_Menu_UnitFrame_Widget", self.widgetPane, sectionWidth, (self.widgetHeight - self.paneHeight), true, true) - self.settingsFrame:SetPoint("TOPLEFT", self.widgetPane, "BOTTOMLEFT", 0, -buffer) + self.settingsFrame:SetPoint("TOPLEFT", self.widgetPane, "BOTTOMLEFT", 0, -inset) Cell:CreateScrollFrame(self.settingsFrame) self.settingsFrame.scrollFrame:SetScrollStep(50) self:InitWidgets() - local widgetListWindow = CUF:CreateFrame("CUF_Menu_WidgetList", self.window, + local widgetListWindow = CUF:CreateFrame("CUF_Menu_UnitFrame_WidgetList", self.window, sectionWidth / 3, self.settingsFrame:GetHeight(), false, true) - widgetListWindow:SetPoint("BOTTOMRIGHT", self.window, "BOTTOMLEFT", 1, 0) + widgetListWindow:SetPoint("BOTTOMRIGHT", self.window, "BOTTOMLEFT", 1 - inset, 0) - ---@class MenuFrame.widgetListFrame: Frame + ---@class UnitsFramesTab.widgetListFrame: Frame ---@field scrollFrame CellScrollFrame - self.widgetListFrame = CUF:CreateFrame("CUF_Menu_WidgetListFrame", widgetListWindow, + self.widgetListFrame = CUF:CreateFrame("CUF_Menu_UnitFrame_WidgetListFrame", widgetListWindow, widgetListWindow:GetWidth(), widgetListWindow:GetHeight(), false, true) self.widgetListFrame:SetPoint("TOPLEFT", widgetListWindow, "TOPLEFT", 0, 0) Cell:CreateScrollFrame(self.widgetListFrame) self.widgetListFrame.scrollFrame:SetScrollStep(25) - - hooksecurefunc(optionsFrame, "Hide", function() - self:HideMenu() - end) end diff --git a/UnitFrames/MenuOptions.lua b/UnitFrames/MenuOptions.lua index 9ef67b3..98e64fb 100644 --- a/UnitFrames/MenuOptions.lua +++ b/UnitFrames/MenuOptions.lua @@ -5,13 +5,13 @@ local Cell = CUF.Cell local L = CUF.L local function UpdateSize() - if CUF.vars.selectedLayout == Cell.vars.currentLayout then + if CUF.vars.selectedLayout == CUF.DB.GetMasterLayout() then CUF:Fire("UpdateLayout", CUF.vars.selectedLayout, CUF.vars.selectedUnit .. "-size") end end local function UpdateArrangement() - if CUF.vars.selectedLayout == Cell.vars.currentLayout then + if CUF.vars.selectedLayout == CUF.DB.GetMasterLayout() then CUF:Fire("UpdateLayout", CUF.vars.selectedLayout, CUF.vars.selectedUnit .. "-arrangement") end end @@ -59,7 +59,7 @@ end local function AddUnitsToMenu() for _, unit in pairs(CUF.constants.UNIT) do CUF.Menu:AddUnit( - ---@param parent MenuFrame + ---@param parent UnitsFramesTab ---@return UnitsMenuPage function(parent) ---@class UnitsMenuPage @@ -82,7 +82,7 @@ local function AddUnitsToMenu() .Frame, function(checked) CUF.DB.SelectedLayoutTable()[unit].enabled = checked - if CUF.vars.selectedLayout == Cell.vars.currentLayout then + if CUF.vars.selectedLayout == CUF.DB.GetMasterLayout() then CUF:Fire("UpdateLayout", CUF.vars.selectedLayout, unit) end CUF:Fire("UpdateVisibility", unit) @@ -103,7 +103,7 @@ local function AddUnitsToMenu() -- update size and power UpdateSize() - if CUF.vars.selectedLayout == Cell.vars.currentLayout then + if CUF.vars.selectedLayout == CUF.DB.GetMasterLayout() then CUF:Fire("UpdateLayout", CUF.vars.selectedLayout, unit .. "-power") end end) @@ -128,7 +128,7 @@ local function AddUnitsToMenu() unitPage.powerSizeSlider = Cell:CreateSlider(L["Power Size"], unitPage.frame, 0, 100, 117, 1, function(value) CUF.DB.SelectedLayoutTable()[unit].powerSize = value - if CUF.vars.selectedLayout == Cell.vars.currentLayout then + if CUF.vars.selectedLayout == CUF.DB.GetMasterLayout() then CUF:Fire("UpdateLayout", CUF.vars.selectedLayout, unit .. "-power") end end) diff --git a/Util/Handler.lua b/Util/Handler.lua index 4074f85..c2a75d3 100644 --- a/Util/Handler.lua +++ b/Util/Handler.lua @@ -29,7 +29,7 @@ local function IterateGenericSetters(button, unit, widgetName, setting, subSetti if not button:HasWidget(widgetName) then return end local widget = button.widgets[widgetName] ---@type Widget - local styleTable = DB.GetWidgetTable(widgetName, unit) + local styleTable = DB.GetCurrentWidgetTable(widgetName, unit) if (not setting or setting == "enabled") and type(widget.SetEnabled) == "function" then widget:SetEnabled(styleTable) @@ -60,7 +60,7 @@ end function Handler.UpdateWidgets(layout, unit, widgetName, setting, ...) CUF:Log("|cffff7777UpdateWidgets:|r", layout, unit, widgetName, setting, ...) - if layout and layout ~= Cell.vars.currentLayout then return end + if layout and layout ~= DB.GetMasterLayout() then return end for name, func in pairs(Handler.widgets) do if not widgetName or name == widgetName then @@ -94,22 +94,29 @@ end ---@param selectedWidget WIDGET_KIND? function Handler.UpdateSelected(selectedUnit, selectedWidget) CUF:Log("|cffff7777Handler.UpdateSelected:|r", selectedUnit, selectedWidget, CUF.vars.isMenuOpen) + local isCorrectLayout = CUF.vars.selectedLayout == DB.GetMasterLayout() Util:IterateAllUnitButtons( - ---@param button CUFUnitButton function(button) button._isSelected = button.states.unit == selectedUnit and CUF.vars.isMenuOpen for _, widget in pairs(const.WIDGET_KIND) do if button:HasWidget(widget) then - local isSelected = widget == selectedWidget and button._isSelected + local isSelected = widget == selectedWidget and button._isSelected and isCorrectLayout button.widgets[widget]:_SetIsSelected(isSelected) end end end) end +--- Load the widget table for the selected unit and widget +--- +--- This is called when we selected a unit or widget in the menu. +--- Or when a layout is loaded. ---@param page Unit ---@param subPage WIDGET_KIND function Handler.LoadPageDB(page, subPage) + if not CUF.vars.isMenuOpen then return end + if CUF.vars.selectedTab ~= "unitFramesTab" then return end + -- Both params are only present when LoadLayoutDB is called if not page or not subPage then if (page and page == Handler.previousPage) diff --git a/Util/Utils.lua b/Util/Utils.lua index 667ae83..2b78652 100644 --- a/Util/Utils.lua +++ b/Util/Utils.lua @@ -75,11 +75,27 @@ function Util:RenameProp(table, oldKey, newKey) end end +---@param table table +---@param seen table? +---@return table +function Util:CopyDeep(table, seen) + -- Handle non-tables and previously-seen tables. + if type(table) ~= 'table' then return table end + if seen and seen[table] then return seen[table] end + + -- New table; mark it as seen an copy recursively. + local s = seen or {} + local res = {} + s[table] = res + for k, v in next, table do res[self:CopyDeep(k, s)] = self:CopyDeep(v, s) end + return setmetatable(res, getmetatable(table)) +end + ------------------------------------------------- -- MARK: IterateAllUnitButtons ------------------------------------------------- ----@param func function +---@param func fun(button: CUFUnitButton, unit: string, ...) ---@param unitToIterate string? function Util:IterateAllUnitButtons(func, unitToIterate, ...) for _, unit in pairs(CUF.constants.UNIT) do @@ -291,6 +307,18 @@ function CUF:CreateEditBox(parent, width, height, text, isTransparent, isMultiLi return editBox end +---@param parent Frame +---@param width number +---@param text string +---@param onAccept function? +---@param onReject function? +---@param mask boolean? +---@param hasEditBox boolean? +---@param dropdowns boolean? +function CUF:CreateConfirmPopup(parent, width, text, onAccept, onReject, mask, hasEditBox, dropdowns) + return Cell:CreateConfirmPopup(parent, width, text, onAccept, onReject, mask, hasEditBox, dropdowns) +end + ---@param frame Frame ---@param anchor "ANCHOR_TOP" | "ANCHOR_BOTTOM" | "ANCHOR_LEFT" | "ANCHOR_RIGHT" | "ANCHOR_TOPLEFT" | "ANCHOR_TOPRIGHT" | "ANCHOR_BOTTOMLEFT" | "ANCHOR_BOTTOMRIGHT" | "ANCHOR_CURSOR" ---@param x number diff --git a/Widgets/Auras/Updater.lua b/Widgets/Auras/Updater.lua index e8ab7dc..0a7abf9 100644 --- a/Widgets/Auras/Updater.lua +++ b/Widgets/Auras/Updater.lua @@ -20,7 +20,7 @@ function W.UpdateAuraWidget(button, unit, which, setting, subSetting, ...) ---@type CellAuraIcons local auras = button.widgets[which] - local styleTable = DB.GetWidgetTable(which, unit) --[[@as AuraWidgetTable]] + local styleTable = DB.GetCurrentWidgetTable(which, unit) --[[@as AuraWidgetTable]] if not setting or setting == const.AURA_OPTION_KIND.FONT or const.AURA_OPTION_KIND.POSITION then auras:SetFont(styleTable.font) diff --git a/Widgets/Bars/CastBar.lua b/Widgets/Bars/CastBar.lua index 6bd5bdc..5bb90de 100644 --- a/Widgets/Bars/CastBar.lua +++ b/Widgets/Bars/CastBar.lua @@ -35,7 +35,7 @@ menu:AddWidget(const.WIDGET_KIND.CAST_BAR, ---@param subSetting string function W.UpdateCastBarWidget(button, unit, setting, subSetting, ...) local castBar = button.widgets.castBar - local styleTable = DB.GetWidgetTable(const.WIDGET_KIND.CAST_BAR, unit) + local styleTable = DB.GetCurrentWidgetTable(const.WIDGET_KIND.CAST_BAR, unit) if not setting or setting == const.OPTION_KIND.COLOR then if not subSetting or subSetting == const.OPTION_KIND.TEXTURE then diff --git a/Widgets/Bars/ShieldBar.lua b/Widgets/Bars/ShieldBar.lua index b439f5a..4b3e409 100644 --- a/Widgets/Bars/ShieldBar.lua +++ b/Widgets/Bars/ShieldBar.lua @@ -32,7 +32,7 @@ menu:AddWidget(const.WIDGET_KIND.SHIELD_BAR, ---@param subSetting string function W.UpdateShieldBarWidget(button, unit, setting, subSetting, ...) local widget = button.widgets.shieldBar - local styleTable = DB.GetWidgetTable(const.WIDGET_KIND.SHIELD_BAR, unit) --[[@as ShieldBarWidgetTable]] + local styleTable = DB.GetCurrentWidgetTable(const.WIDGET_KIND.SHIELD_BAR, unit) --[[@as ShieldBarWidgetTable]] if not setting or setting == const.OPTION_KIND.RGBA then widget:SetColor(unpack(styleTable.rgba)) diff --git a/Widgets/Texts/HealthText.lua b/Widgets/Texts/HealthText.lua index b601fcc..6980234 100644 --- a/Widgets/Texts/HealthText.lua +++ b/Widgets/Texts/HealthText.lua @@ -36,7 +36,7 @@ menu:AddWidget(const.WIDGET_KIND.HEALTH_TEXT, ---@param subSetting string function W.UpdateHealthTextWidget(button, unit, setting, subSetting, ...) local widget = button.widgets.healthText - local styleTable = DB.GetWidgetTable(const.WIDGET_KIND.HEALTH_TEXT, unit) --[[@as HealthTextWidgetTable]] + local styleTable = DB.GetCurrentWidgetTable(const.WIDGET_KIND.HEALTH_TEXT, unit) --[[@as HealthTextWidgetTable]] if not setting or setting == const.OPTION_KIND.FORMAT then widget:SetFormat(styleTable.format) diff --git a/Widgets/Texts/NameText.lua b/Widgets/Texts/NameText.lua index cd87207..01b53aa 100644 --- a/Widgets/Texts/NameText.lua +++ b/Widgets/Texts/NameText.lua @@ -39,7 +39,7 @@ menu:AddWidget(const.WIDGET_KIND.NAME_TEXT, ---@param subSetting string function W.UpdateNameTextWidget(button, unit, setting, subSetting) local widget = button.widgets.nameText - local styleTable = DB.GetWidgetTable(const.WIDGET_KIND.NAME_TEXT, unit) --[[@as NameTextWidgetTable]] + local styleTable = DB.GetCurrentWidgetTable(const.WIDGET_KIND.NAME_TEXT, unit) --[[@as NameTextWidgetTable]] if not setting or setting == const.OPTION_KIND.WIDTH then widget.width = styleTable.width diff --git a/Widgets/Texts/PowerText.lua b/Widgets/Texts/PowerText.lua index a68f7ab..082f21e 100644 --- a/Widgets/Texts/PowerText.lua +++ b/Widgets/Texts/PowerText.lua @@ -36,7 +36,7 @@ menu:AddWidget(const.WIDGET_KIND.POWER_TEXT, ---@param subSetting string function W.UpdatePowerTextWidget(button, unit, setting, subSetting) local widget = button.widgets.powerText - local styleTable = DB.GetWidgetTable(const.WIDGET_KIND.POWER_TEXT, unit) --[[@as PowerTextWidgetTable]] + local styleTable = DB.GetCurrentWidgetTable(const.WIDGET_KIND.POWER_TEXT, unit) --[[@as PowerTextWidgetTable]] if not setting or setting == const.OPTION_KIND.FORMAT then widget:SetFormat(styleTable.format)