diff --git a/Titan/Titan.lua b/Titan/Titan.lua index 698b4ad..7d10a9c 100644 --- a/Titan/Titan.lua +++ b/Titan/Titan.lua @@ -916,7 +916,7 @@ local function handle_profile_cmds(cmd_list) if (not cmd == "profile") then return end - AceConfigDialog:Open("Titan Panel Addon Chars") + AceConfigDialog:Open("Titan Panel Addon Profiles") end ---local Helper to handle 'silent' commands - Toggle "Silenced" setting. @@ -2312,7 +2312,7 @@ local function GeneratorFunction(owner, rootDescription) Titan_Menu.AddCommand(root, id, L["TITAN_PANEL_MENU_PROFILES"] .. " " .. L["TITAN_PANEL_MENU_CONFIGURATION"], function() TitanUpdateConfig("init") - AceConfigDialog:Open("Titan Panel Addon Chars") + AceConfigDialog:Open("Titan Panel Addon Profiles") end ) diff --git a/Titan/Titan.toc b/Titan/Titan.toc index 1577b85..56ffd30 100644 --- a/Titan/Titan.toc +++ b/Titan/Titan.toc @@ -36,7 +36,7 @@ libs\Ace\AceGUI-3.0\AceGUI-3.0.xml libs\Ace\AceConfig-3.0\AceConfig-3.0.xml libs\Ace\AceLocale-3.0\AceLocale-3.0.xml libs\LibSharedMedia-3.0\lib.xml -libs\Ace\LibQTip-1.0\lib.xml +libs\LibQTip-1.0\lib.xml libs\LibDeflate\LibDeflate.lua libs\LibDataBroker-1.1.lua diff --git a/Titan/TitanConfig.lua b/Titan/TitanConfig.lua index 8802466..9cf0550 100644 --- a/Titan/TitanConfig.lua +++ b/Titan/TitanConfig.lua @@ -1206,14 +1206,7 @@ end --============= Profiles ----local Allow the user to load / delete / reset / sync profile data ----@param pos number Order of options ----@return table Config options -local function CreateProfiles(pos) - -- AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") - local p_info = {} -- used to hold info about each toon in players - local p_sync = {} -- profiles used as Sync - +local function GenProfileInfo(p_info, p_sync) -- Rip through the players (with server name) to sort them for index, id in TitanUtils_PlayerIter() do -- collect some info on THIS toon for the config @@ -1260,6 +1253,17 @@ local function CreateProfiles(pos) table.sort(p_info, function(a, b) return a.name < b.name end) +end + +---local Allow the user to load / delete / reset / sync profile data +---@param pos number Order of options +---@return table Config options +local function CreateProfiles(pos) + -- AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") + local p_info = {} -- used to hold info about each toon in players + local p_sync = {} -- profiles used as Sync + + GenProfileInfo(p_info, p_sync) local opts = {} opts.name = Config_locale.topic.profiles @@ -1442,7 +1446,7 @@ local function CreateProfiles(pos) L["TITAN_PANEL_MENU_POST_CLEAR_DESC"] .. " > " .. this_toon.name .. "" , "info") - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, -- Should be able to clear any specific toon info --disabled = (this_toon.is_player or g_sync), @@ -1499,7 +1503,7 @@ local function CreateProfiles(pos) L["TITAN_PANEL_MENU_LOAD_SETTINGS"] .. " > " .. this_toon.name .. "" , "info") - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, -- does not make sense to load current character profile disabled = (this_toon.is_player or g_sync), @@ -1530,8 +1534,13 @@ local function CreateProfiles(pos) .. " " .. this_toon.name .. " " .. L["TITAN_PANEL_MENU_PROFILE_DELETED"] , "info") - --TitanUpdateChars() -- rebuild the toons - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + -- bit of a hammer but trying to get Ace to reflect changes is not working... + C_Timer.After(0.1, function() +---@diagnostic disable-next-line: param-type-mismatch + C_Timer.After(0.1, AceConfigDialog:CloseAll()) + end) + --CreateProfiles(120) -- rebuild the toons + --AceConfigRegistry:NotifyChange(config_parent) end, -- can not delete current character profile disabled = (this_toon.is_player @@ -1589,7 +1598,7 @@ local function CreateProfiles(pos) , "info") --TitanUpdateChars() - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, disabled = not (this_toon.is_player), } @@ -1612,7 +1621,7 @@ local function CreateProfiles(pos) func = function(info, v) TitanPanel_SaveCustomProfile(this_toon.name) -- will output message on write --TitanUpdateChars() -- rebuild the toons - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, } position = position + 1 @@ -1668,7 +1677,7 @@ local function CreateProfiles(pos) -- TitanVariables_UseSettings(nil, this_toon.name, TITAN_PROFILE_USE) TitanVariables_UseSettings(nil, TitanUtils_GetPlayer(), TITAN_PROFILE_USE) --TitanUpdateChars() - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, -- cannot sync to yourself or if sync already set disabled = (this_toon.is_player or this_toon.sync_set or g_sync), @@ -1704,7 +1713,7 @@ local function CreateProfiles(pos) , "info") --TitanUpdateChars() - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, disabled = (not this_toon.sync_set) or g_sync, } @@ -1757,7 +1766,7 @@ local function CreateProfiles(pos) -- Change over to new profile TitanVariables_UseSettings(nil, TitanUtils_GetPlayer(), TITAN_PROFILE_USE) --TitanUpdateChars() - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, -- Can allows set global sync --disabled = this_toon.is_player or this_toon.sync_set, @@ -1786,7 +1795,7 @@ local function CreateProfiles(pos) TitanVariables_UseSettings(nil, TitanUtils_GetPlayer(), TITAN_PROFILE_USE) --TitanUpdateChars() - AceConfigRegistry:NotifyChange("Titan Panel Addon Chars") + AceConfigRegistry:NotifyChange("Titan Panel Addon Profiles") end, disabled = (not g_sync), } @@ -3602,7 +3611,7 @@ local function BuiltTitanStructure() titan_options.args.optionsAddons = CreateConfigAddons(90) titan_options.args.optionsAddonAttempts = CreateAddonAttempts(100) titan_options.args.optionsExtras = CreateExtras(110) - titan_options.args.optionsChars = CreateProfiles(120) + titan_options.args.optionsProfiles = CreateProfiles(120) titan_options.args.optionsImportExport = CreateImportExportList(130) titan_options.args.optionsAdvanced = CreateAdvanced(140) titan_options.args.changeHistory = CreateHistory(150) @@ -3655,7 +3664,7 @@ local function BuildAll() AceConfig:RegisterOptionsTable("Titan Panel Addon Control", titan_options.args.optionsAddons) AceConfig:RegisterOptionsTable("Titan Panel Addon Attempts", titan_options.args.optionsAddonAttempts) AceConfig:RegisterOptionsTable("Titan Panel Addon Extras", titan_options.args.optionsExtras) - AceConfig:RegisterOptionsTable("Titan Panel Addon Chars", titan_options.args.optionsChars) + AceConfig:RegisterOptionsTable("Titan Panel Addon Profiles", titan_options.args.optionsProfiles) AceConfig:RegisterOptionsTable("Titan Panel Addon Im_Ex", titan_options.args.optionsImportExport) AceConfig:RegisterOptionsTable("Titan Panel Addon Advanced", titan_options.args.optionsAdvanced) AceConfig:RegisterOptionsTable("Titan Panel Addon Changes", titan_options.args.changeHistory) @@ -3684,7 +3693,7 @@ local function BuildAll() AceConfigDialog:AddToBlizOptions("Titan Panel Adjust", titan_options.args.optionsAdjust.name, config_parent) AceConfigDialog:AddToBlizOptions("Titan Panel Addon Control", titan_options.args.optionsAddons.name, config_parent) - AceConfigDialog:AddToBlizOptions("Titan Panel Addon Chars", titan_options.args.optionsChars.name, + AceConfigDialog:AddToBlizOptions("Titan Panel Addon Profiles", titan_options.args.optionsProfiles.name, config_parent) AceConfigDialog:AddToBlizOptions("Titan Panel Addon Im_Ex", titan_options.args.optionsImportExport.name, config_parent) @@ -3741,7 +3750,7 @@ function TitanUpdateConfig(action) AceConfig:RegisterOptionsTable("Titan Panel Addon Control", nuked) AceConfig:RegisterOptionsTable("Titan Panel Addon Attempts", nuked) AceConfig:RegisterOptionsTable("Titan Panel Addon Extras", nuked) - AceConfig:RegisterOptionsTable("Titan Panel Addon Chars", nuked) + AceConfig:RegisterOptionsTable("Titan Panel Addon Profiles", nuked) AceConfig:RegisterOptionsTable("Titan Panel Addon Advanced", nuked) AceConfig:RegisterOptionsTable("Titan Panel Addon Changes", nuked) AceConfig:RegisterOptionsTable("Titan Panel Addon Slash", nuked) diff --git a/Titan/_Titan_Lib_Notes.txt b/Titan/_Titan_Lib_Notes.txt index 0dd0bb4..0cf0990 100644 --- a/Titan/_Titan_Lib_Notes.txt +++ b/Titan/_Titan_Lib_Notes.txt @@ -1,14 +1,27 @@ From: Ace3 - https://www.curseforge.com/wow/addons/ace3 +- AceAddon +- AceConfig +- AceGUI +- AceHook +- AceLocale +- AceSerializer +- AceTimer +- CallbackHandler +- LibStib +- and Ace files (.toc plus) LibQTip-1.0 - https://www.curseforge.com/wow/addons/libqtip-1-0 LibSharedMedia-3.0 - https://www.wowace.com/projects/libsharedmedia-3-0 : https://www.curseforge.com/wow/addons/libsharedmedia-3-0 +*** 2026-May **** +- Ace update from Release-r1390 2026-02-03 +- Moved LibQTip from /Ace to /libs + *** 2025-Nov **** - Ace update from Release-r1377 2024-10-28 - *** 2025-Sep* - Dropped !LibUIDropDownMenu, again; updated wrappers to Blizz version LibUIDropDownMenu - https://www.curseforge.com/wow/addons/libuidropdownmenu diff --git a/Titan/libs/Ace/Ace3.toc b/Titan/libs/Ace/Ace3.toc index b0d60df..8669440 100644 --- a/Titan/libs/Ace/Ace3.toc +++ b/Titan/libs/Ace/Ace3.toc @@ -1,4 +1,4 @@ -## Interface: 11508, 11507, 20504, 30405, 40402, 50501, 50502, 110205, 110207, 120000 +## Interface: 11508, 11507, 20505, 30405, 38000, 40402, 50503, 50502, 120001, 110207, 120000 ## Title: Lib: Ace3 ## Notes: AddOn development framework @@ -6,7 +6,7 @@ ## X-Website: http://www.wowace.com ## X-Category: Library ## X-License: Limited BSD -## Version: Release-r1377 +## Version: Release-r1390 LibStub\LibStub.lua CallbackHandler-1.0\CallbackHandler-1.0.xml diff --git a/Titan/libs/Ace/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua b/Titan/libs/Ace/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua index 904458a..4558a8e 100644 --- a/Titan/libs/Ace/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua +++ b/Titan/libs/Ace/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua @@ -1,13 +1,13 @@ --- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables. -- @class file -- @name AceConfigDialog-3.0 --- @release $Id: AceConfigDialog-3.0.lua 1372 2025-10-05 05:38:34Z nevcairiel $ +-- @release $Id: AceConfigDialog-3.0.lua 1386 2025-12-11 18:25:02Z nevcairiel $ local LibStub = LibStub local gui = LibStub("AceGUI-3.0") local reg = LibStub("AceConfigRegistry-3.0") -local MAJOR, MINOR = "AceConfigDialog-3.0", 89 +local MAJOR, MINOR = "AceConfigDialog-3.0", 92 local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not AceConfigDialog then return end @@ -1083,6 +1083,11 @@ local function InjectInfo(control, options, option, path, rootframe, appName) control:SetCallback("OnRelease", CleanUserData) control:SetCallback("OnLeave", OptionOnMouseLeave) control:SetCallback("OnEnter", OptionOnMouseOver) + + -- forward custom arg data directly + if control.SetCustomData and option.arg then + safecall(control.SetCustomData, control, option.arg) + end end local function CreateControl(userControlType, fallbackControlType) @@ -1436,12 +1441,15 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin if control then if control.width ~= "fill" then local width = GetOptionsMemberValue("width",v,options,path,appName) + local relWidth = GetOptionsMemberValue("relWidth",v,options,path,appName) if width == "double" then control:SetWidth(width_multiplier * 2) elseif width == "half" then control:SetWidth(width_multiplier / 2) elseif (type(width) == "number") then control:SetWidth(width_multiplier * width) + elseif width == "relative" and relWidth then + control:SetRelativeWidth(relWidth) elseif width == "full" then control.width = "fill" else @@ -1945,6 +1953,8 @@ else AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {} end +AceConfigDialog.BlizOptionsIDMap = AceConfigDialog.BlizOptionsIDMap or {} + local function FeedToBlizPanel(widget, event) local path = widget:GetUserData("path") AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(path or emptyTbl)) @@ -1966,16 +1976,17 @@ end -- has to be a head-level note. -- -- This function returns a reference to the container frame registered with the Interface --- Options. You can use this reference to open the options with the API function --- `InterfaceOptionsFrame_OpenToCategory`. +-- Options, as well as the registered ID. You can use the ID to open the options with +-- the API function `Settings.OpenToCategory`. -- @param appName The application name as given to `:RegisterOptionsTable()` -- @param name A descriptive name to display in the options tree (defaults to appName) -- @param parent The parent to use in the interface options tree. -- @param ... The path in the options table to feed into the interface options panel. -- @return The reference to the frame registered into the Interface Options. --- @return The category ID to pass to Settings.OpenToCategory (or InterfaceOptionsFrame_OpenToCategory) +-- @return The category ID to pass to Settings.OpenToCategory function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...) local BlizOptions = AceConfigDialog.BlizOptions + local BlizOptionsIDMap = AceConfigDialog.BlizOptionsIDMap local key = appName for n = 1, select("#", ...) do @@ -2001,29 +2012,32 @@ function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...) end group:SetCallback("OnShow", FeedToBlizPanel) group:SetCallback("OnHide", ClearBlizPanel) - if Settings and Settings.RegisterCanvasLayoutCategory then - local categoryName = name or appName - if parent then - local category = Settings.GetCategory(parent) - if not category then - error(("The parent category '%s' was not found"):format(parent), 2) - end - local subcategory = Settings.RegisterCanvasLayoutSubcategory(category, group.frame, categoryName) - -- force the generated ID to be used for subcategories, as these can have very simple names like "Profiles" - group:SetName(subcategory.ID, parent) - else - local category = Settings.RegisterCanvasLayoutCategory(group.frame, categoryName) - -- using appName here would be cleaner, but would not be 100% compatible - -- but for top-level categories it should be fine, as these are typically addon names - category.ID = categoryName - group:SetName(categoryName, parent) - Settings.RegisterAddOnCategory(category) + local categoryName = name or appName + if parent then + local parentID = BlizOptionsIDMap[parent] or parent + local category = Settings.GetCategory(parentID) + if not category then + error(("The parent category '%s' was not found"):format(parent), 2) end + local subcategory = Settings.RegisterCanvasLayoutSubcategory(category, group.frame, categoryName) + group:SetName(subcategory.ID, parentID) else - group:SetName(name or appName, parent) - InterfaceOptions_AddCategory(group.frame) + if BlizOptionsIDMap[categoryName] then + error(("%s has already been added to the Blizzard Options Window with the given name: %s"):format(appName, categoryName), 2) + end + + local category = Settings.RegisterCanvasLayoutCategory(group.frame, categoryName) + if not (C_SettingsUtil and C_SettingsUtil.OpenSettingsPanel) then + -- override the ID so the name can be used in Settings.OpenToCategory + -- unfortunately with incoming API changes in 12.0 (and likely classic at some point) this override is no longer possible + category.ID = categoryName + end + group:SetName(category.ID) + BlizOptionsIDMap[categoryName] = category.ID + Settings.RegisterAddOnCategory(category) end + return group.frame, group.frame.name else error(("%s has already been added to the Blizzard Options Window with the given path"):format(appName), 2) diff --git a/Titan/libs/Ace/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua b/Titan/libs/Ace/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua index e0f5962..8adbe79 100644 --- a/Titan/libs/Ace/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua +++ b/Titan/libs/Ace/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua @@ -8,10 +8,10 @@ -- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName". -- @class file -- @name AceConfigRegistry-3.0 --- @release $Id: AceConfigRegistry-3.0.lua 1296 2022-11-04 18:50:10Z nevcairiel $ +-- @release $Id: AceConfigRegistry-3.0.lua 1385 2025-12-06 11:26:20Z nevcairiel $ local CallbackHandler = LibStub("CallbackHandler-1.0") -local MAJOR, MINOR = "AceConfigRegistry-3.0", 21 +local MAJOR, MINOR = "AceConfigRegistry-3.0", 22 local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR) if not AceConfigRegistry then return end @@ -92,6 +92,7 @@ local basekeys={ func=optmethodfalse, arg={["*"]=true}, width=optstringnumber, + relWidth=optnumber, } local typedkeys={ diff --git a/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua b/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua index 7900937..fef4557 100644 --- a/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua +++ b/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua @@ -2,7 +2,7 @@ TreeGroup Container Container that uses a tree control to switch between groups. -------------------------------------------------------------------------------]] -local Type, Version = "TreeGroup", 48 +local Type, Version = "TreeGroup", 49 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -206,7 +206,7 @@ local function Button_OnEnter(frame) tooltip:SetOwner(frame, "ANCHOR_NONE") tooltip:ClearAllPoints() tooltip:SetPoint("LEFT",frame,"RIGHT") - tooltip:SetText(frame.text:GetText() or "", 1, .82, 0, true) + tooltip:SetText(frame.text:GetText() or "", 1, .82, 0, 1, true) tooltip:Show() end diff --git a/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua b/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua index 0c779dc..ee5a83b 100644 --- a/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua +++ b/Titan/libs/Ace/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua @@ -2,7 +2,7 @@ Keybinding Widget Set Keybindings in the Config UI. -------------------------------------------------------------------------------]] -local Type, Version = "Keybinding", 26 +local Type, Version = "Keybinding", 27 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -31,12 +31,14 @@ local function Keybinding_OnClick(frame, button) if self.waitingForKey then frame:EnableKeyboard(false) frame:EnableMouseWheel(false) + frame:EnableGamePadButton(false) self.msgframe:Hide() frame:UnlockHighlight() self.waitingForKey = nil else frame:EnableKeyboard(true) frame:EnableMouseWheel(true) + frame:EnableGamePadButton(true) self.msgframe:Show() frame:LockHighlight() self.waitingForKey = true @@ -72,6 +74,7 @@ local function Keybinding_OnKeyDown(frame, key) frame:EnableKeyboard(false) frame:EnableMouseWheel(false) + frame:EnableGamePadButton(false) self.msgframe:Hide() frame:UnlockHighlight() self.waitingForKey = nil @@ -119,6 +122,7 @@ local methods = { self:SetDisabled(false) self.button:EnableKeyboard(false) self.button:EnableMouseWheel(false) + self.button:EnableGamePadButton(false) end, -- ["OnRelease"] = nil, @@ -195,10 +199,12 @@ local function Constructor() button:SetScript("OnKeyDown", Keybinding_OnKeyDown) button:SetScript("OnMouseDown", Keybinding_OnMouseDown) button:SetScript("OnMouseWheel", Keybinding_OnMouseWheel) + button:SetScript("OnGamePadButtonDown", Keybinding_OnKeyDown) button:SetPoint("BOTTOMLEFT") button:SetPoint("BOTTOMRIGHT") button:SetHeight(24) button:EnableKeyboard(false) + button:EnableGamePadButton(false) local text = button:GetFontString() text:SetPoint("LEFT", 7, 0) diff --git a/Titan/libs/Ace/CHANGES.txt b/Titan/libs/Ace/CHANGES.txt index 14b4f42..7cfb6ba 100644 --- a/Titan/libs/Ace/CHANGES.txt +++ b/Titan/libs/Ace/CHANGES.txt @@ -1,189 +1,113 @@ ------------------------------------------------------------------------ -r1376 | nevcairiel | 2025-10-28 22:06:01 +0000 (Tue, 28 Oct 2025) | 1 line +r1389 | nevcairiel | 2026-02-03 18:39:11 +0000 (Tue, 03 Feb 2026) | 1 line Changed paths: M /trunk/changelog.txt Update changelog ------------------------------------------------------------------------ -r1375 | funkehdude | 2025-10-24 04:07:54 +0000 (Fri, 24 Oct 2025) | 1 line +r1388 | funkehdude | 2026-01-22 23:05:57 +0000 (Thu, 22 Jan 2026) | 1 line Changed paths: - M /trunk/Ace3.toc - -Bump toc ------------------------------------------------------------------------- -r1374 | funkehdude | 2025-10-15 17:12:41 +0000 (Wed, 15 Oct 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc + M /trunk/.luacheckrc + M /trunk/AceTab-3.0/AceTab-3.0.lua -Bump toc +AceTab-3.0/AceTab-3.0: `NUM_CHAT_WINDOWS` was replaced by `Constants.ChatFrameConstants.MaxChatWindows` ------------------------------------------------------------------------ -r1373 | funkehdude | 2025-10-13 14:09:48 +0000 (Mon, 13 Oct 2025) | 1 line +r1387 | funkehdude | 2026-01-13 16:57:21 +0000 (Tue, 13 Jan 2026) | 1 line Changed paths: M /trunk/Ace3.toc Bump toc ------------------------------------------------------------------------ -r1372 | nevcairiel | 2025-10-05 05:38:34 +0000 (Sun, 05 Oct 2025) | 1 line +r1386 | nevcairiel | 2025-12-11 18:25:02 +0000 (Thu, 11 Dec 2025) | 5 lines Changed paths: M /trunk M /trunk/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua -AceConfigDialog-3.0: Consistently provide an alpha value for GameTooltip:SetText ------------------------------------------------------------------------- -r1371 | nevcairiel | 2025-10-03 10:25:33 +0000 (Fri, 03 Oct 2025) | 1 line -Changed paths: - M /trunk - M /trunk/AceComm-3.0/ChatThrottleLib.lua +AceConfigDialog-3.0: Forward the "arg" option table member to widgets -ChatThrottleLib: Use C_BattleNet namespace, if available +Widgets will receive the data through the SetCustomData function, if +available, and can act on it as needed. This provides a clear lifecycle +function before layout where the data is being made available. ------------------------------------------------------------------------ -r1370 | nevcairiel | 2025-10-03 00:16:25 +0000 (Fri, 03 Oct 2025) | 1 line +r1385 | nevcairiel | 2025-12-06 11:26:20 +0000 (Sat, 06 Dec 2025) | 1 line Changed paths: M /trunk - M /trunk/.luacheckrc + M /trunk/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua + M /trunk/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua -Update luacheck for chat changes +AceConfig-3.0: Bump library versions for relative width support ------------------------------------------------------------------------ -r1369 | nevcairiel | 2025-10-02 23:56:28 +0000 (Thu, 02 Oct 2025) | 1 line +r1384 | nevcairiel | 2025-12-06 10:23:20 +0000 (Sat, 06 Dec 2025) | 3 lines Changed paths: M /trunk - M /trunk/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua - M /trunk/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua + M /trunk/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua -AceGUI-3.0: EditBox: Fix InsertLink hook for 12.0 ------------------------------------------------------------------------- -r1368 | nevcairiel | 2025-10-02 23:52:43 +0000 (Thu, 02 Oct 2025) | 1 line -Changed paths: - M /trunk - M /trunk/AceComm-3.0/ChatThrottleLib.lua +AceGUI-3.0: Keybinding: Add gamepad support -ChatThrottleLib: Properly use the right namespace for SendChatMessage +Gamepad bindings are completely in line with the rest of the keybinding system in WoW, so all that's really necessary to make them work in AceGUI is to add a handler to catch bindings. ------------------------------------------------------------------------ -r1367 | funkehdude | 2025-09-08 17:06:01 +0000 (Mon, 08 Sep 2025) | 1 line +r1383 | nevcairiel | 2025-12-06 10:19:35 +0000 (Sat, 06 Dec 2025) | 8 lines Changed paths: + M /trunk M /trunk/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua + M /trunk/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua -AceConfigDialog-3.0: Remove untranslated text "Usage:" from input boxes that define a usage field ------------------------------------------------------------------------- -r1366 | funkehdude | 2025-09-03 15:34:16 +0000 (Wed, 03 Sep 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc +AceConfig-3.0: Widget width can be defined to be relative to the container -Bump toc ------------------------------------------------------------------------- -r1365 | funkehdude | 2025-07-11 17:08:49 +0000 (Fri, 11 Jul 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc +Syntax in the config table: +width = "relative" +relWidth = "0.25" -Bump toc +This will result in a widget that takes up a quarter of the container's +width. ------------------------------------------------------------------------ -r1364 | nevcairiel | 2025-07-05 16:01:08 +0000 (Sat, 05 Jul 2025) | 1 line +r1382 | nevcairiel | 2025-12-05 08:44:39 +0000 (Fri, 05 Dec 2025) | 11 lines Changed paths: M /trunk - M /trunk/AceDB-3.0/AceDB-3.0.lua + M /trunk/.luacheckrc + M /trunk/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua -AceDB-3.0: Avoid hitting the metatable when looking up the keys ------------------------------------------------------------------------- -r1363 | nevcairiel | 2025-07-05 15:42:11 +0000 (Sat, 05 Jul 2025) | 3 lines -Changed paths: - M /trunk - M /trunk/AceDB-3.0/AceDB-3.0.lua +AceConfigDialog-3.0: Preserve the original ID for BlizzOptions categories -AceDB-3.0: Aggressively cleanout empty profiles tables inside namespace on logout +In Midnight, the ID must be numeric, so we can no longer use the name, +and this may prevent taint spread by the ID field, since the +automatically generated value is assigned securely. -This should help cleanup unloaded empty namespaces ------------------------------------------------------------------------- -r1362 | funkehdude | 2025-06-19 17:08:39 +0000 (Thu, 19 Jun 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc +To open the settings panel through Settings.OpenToCategory, the ID needs +to be passed, which is returned as the second value from :AddToBlizzOptions -Bump toc +This change becomes effective when the new C_SettingsUtil API is added +to the various clients, currently in 12.0 ------------------------------------------------------------------------ -r1361 | nevcairiel | 2025-05-17 12:20:39 +0000 (Sat, 17 May 2025) | 6 lines +r1381 | nevcairiel | 2025-12-05 08:43:15 +0000 (Fri, 05 Dec 2025) | 4 lines Changed paths: M /trunk - M /trunk/AceDB-3.0/AceDB-3.0.lua + M /trunk/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua -AceDB-3.0: Cleanup empty namespace tables +AceConfigDialog-3.0: Remove InterfaceOptions_AddCategory support -Some addons use a large amount of namespaces which rarely get used, and -empty tables can clutter the SV. Cleaning up empty tables is consistent -with the other cleanup tasks done at logout, as they'll be re-created if -needed. +All supported WoW versions have moved on to the new Settings interface, +so this was unused. ------------------------------------------------------------------------ -r1360 | funkehdude | 2025-05-01 22:54:00 +0000 (Thu, 01 May 2025) | 1 line +r1380 | funkehdude | 2025-12-03 00:09:20 +0000 (Wed, 03 Dec 2025) | 1 line Changed paths: M /trunk/Ace3.toc Bump toc ------------------------------------------------------------------------ -r1359 | funkehdude | 2025-03-21 19:41:37 +0000 (Fri, 21 Mar 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc - -bump toc ------------------------------------------------------------------------- -r1358 | funkehdude | 2025-03-21 19:37:45 +0000 (Fri, 21 Mar 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc - -bump toc ------------------------------------------------------------------------- -r1357 | funkehdude | 2025-01-23 06:13:10 +0000 (Thu, 23 Jan 2025) | 1 line -Changed paths: - M /trunk/Ace3.toc - -bump toc ------------------------------------------------------------------------- -r1356 | nevcairiel | 2024-12-05 06:15:30 +0000 (Thu, 05 Dec 2024) | 1 line +r1379 | nevcairiel | 2025-11-27 18:58:03 +0000 (Thu, 27 Nov 2025) | 3 lines Changed paths: M /trunk M /trunk/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua -AceGUI-3.0: TreeGroup: Re-factor button hiding to help avoid bizarre button breakage ------------------------------------------------------------------------- -r1355 | funkehdude | 2024-11-20 01:54:56 +0000 (Wed, 20 Nov 2024) | 1 line -Changed paths: - M /trunk/Ace3.toc - -bump toc ------------------------------------------------------------------------- -r1354 | funkehdude | 2024-09-10 14:01:06 +0000 (Tue, 10 Sep 2024) | 1 line -Changed paths: - M /trunk/Ace3.toc - -bump toc ------------------------------------------------------------------------- -r1353 | nevcairiel | 2024-08-27 13:37:35 +0000 (Tue, 27 Aug 2024) | 8 lines -Changed paths: - M /trunk - M /trunk/AceDB-3.0/AceDB-3.0.lua - -AceDB-3.0: Handle unloaded namespaces in Reset/Copy/Delete functions +AceGUI-3.0: TreeGroup: Pass an explicit alpha value to SetText -When applying profile changes to namespaces, we should also handle -namespaces that are not currently loaded. - -These may be from optional Load-on-Demand parts that are not currently -loaded, but the expectation is that the database behaves consistent -no matter what is currently active. +Fixes CF-#685 ------------------------------------------------------------------------ -r1352 | funkehdude | 2024-07-24 18:29:31 +0000 (Wed, 24 Jul 2024) | 1 line -Changed paths: - M /trunk/.luacheckrc - -Update luacheck ------------------------------------------------------------------------- -r1351 | funkehdude | 2024-07-24 18:23:24 +0000 (Wed, 24 Jul 2024) | 1 line -Changed paths: - M /trunk/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua - -AceConfigDialog-3.0: Don't change keyboard input propagation in combat when showing the popup ------------------------------------------------------------------------- -r1350 | funkehdude | 2024-07-24 17:55:50 +0000 (Wed, 24 Jul 2024) | 1 line +r1378 | funkehdude | 2025-11-19 19:46:34 +0000 (Wed, 19 Nov 2025) | 1 line Changed paths: M /trunk/Ace3.toc -Restore old toc versions, these are here purely to compensate for bad addon updaters, we don't actually care if we fully support these versions of wow +Bump toc ------------------------------------------------------------------------ diff --git a/Titan/libs/Ace/LibQTip-1.0/CHANGELOG.md b/Titan/libs/Ace/LibQTip-1.0/CHANGELOG.md deleted file mode 100644 index 442bb65..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# Lib: QTip-1.0 - -## [10.0.7.1](https://github.com/Torhal/LibQTip-1.0/tree/10.0.7.1) (2023-03-29) -[Full Changelog](https://github.com/Torhal/LibQTip-1.0/compare/9.0.1.2...10.0.7.1) [Previous Releases](https://github.com/Torhal/LibQTip-1.0/releases) - -- Create release.yml - Add release configuration for the BigWigs Packager. -- Update ToC Interface and add X-Curse-Project-ID to support the BigWigs Packager. -- Create README.md -- update for WoW 9.1.5's new TooltipBackdropTemplate diff --git a/Titan/libs/Ace/LibQTip-1.0/LICENSE.txt b/Titan/libs/Ace/LibQTip-1.0/LICENSE.txt deleted file mode 100644 index 9bc7b5c..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/LICENSE.txt +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2008, LibQTip Development Team - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Redistribution of a stand alone version is strictly prohibited without - prior written authorization from the Lead of the LibQTip Development Team. - * Neither the name of the LibQTip Development Team nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Titan/libs/Ace/LibQTip-1.0/LibQTip-1.0.lua b/Titan/libs/Ace/LibQTip-1.0/LibQTip-1.0.lua deleted file mode 100644 index bb38c75..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/LibQTip-1.0.lua +++ /dev/null @@ -1,1565 +0,0 @@ -local MAJOR = "LibQTip-1.0" -local MINOR = 49 -- Should be manually increased -local LibStub = _G.LibStub - -assert(LibStub, MAJOR .. " requires LibStub") - -local lib, oldMinor = LibStub:NewLibrary(MAJOR, MINOR) - -if not lib then - return -end -- No upgrade needed - ------------------------------------------------------------------------------- --- Upvalued globals ------------------------------------------------------------------------------- -local table = _G.table -local tinsert = table.insert -local tremove = table.remove -local wipe = table.wipe - -local error = error -local math = math -local min, max = math.min, math.max -local next = next -local pairs, ipairs = pairs, ipairs -local select = select -local setmetatable = setmetatable -local tonumber, tostring = tonumber, tostring -local type = type - -local CreateFrame = _G.CreateFrame -local GameTooltip = _G.GameTooltip -local UIParent = _G.UIParent - -local geterrorhandler = _G.geterrorhandler - ------------------------------------------------------------------------------- --- Tables and locals ------------------------------------------------------------------------------- -lib.frameMetatable = lib.frameMetatable or {__index = CreateFrame("Frame")} - -lib.tipPrototype = lib.tipPrototype or setmetatable({}, lib.frameMetatable) -lib.tipMetatable = lib.tipMetatable or {__index = lib.tipPrototype} - -lib.providerPrototype = lib.providerPrototype or {} -lib.providerMetatable = lib.providerMetatable or {__index = lib.providerPrototype} - -lib.cellPrototype = lib.cellPrototype or setmetatable({}, lib.frameMetatable) -lib.cellMetatable = lib.cellMetatable or {__index = lib.cellPrototype} - -lib.activeTooltips = lib.activeTooltips or {} - -lib.tooltipHeap = lib.tooltipHeap or {} -lib.frameHeap = lib.frameHeap or {} -lib.timerHeap = lib.timerHeap or {} -lib.tableHeap = lib.tableHeap or {} - -lib.onReleaseHandlers = lib.onReleaseHandlers or {} - -local tipPrototype = lib.tipPrototype -local tipMetatable = lib.tipMetatable - -local providerPrototype = lib.providerPrototype -local providerMetatable = lib.providerMetatable - -local cellPrototype = lib.cellPrototype -local cellMetatable = lib.cellMetatable - -local activeTooltips = lib.activeTooltips - -local highlightFrame = CreateFrame("Frame", nil, UIParent) -highlightFrame:SetFrameStrata("TOOLTIP") -highlightFrame:Hide() - -local DEFAULT_HIGHLIGHT_TEXTURE_PATH = [[Interface\QuestFrame\UI-QuestTitleHighlight]] - -local highlightTexture = highlightFrame:CreateTexture(nil, "OVERLAY") -highlightTexture:SetTexture(DEFAULT_HIGHLIGHT_TEXTURE_PATH) -highlightTexture:SetBlendMode("ADD") -highlightTexture:SetAllPoints(highlightFrame) - ------------------------------------------------------------------------------- --- Private methods for Caches and Tooltip ------------------------------------------------------------------------------- -local AcquireTooltip, ReleaseTooltip -local AcquireCell, ReleaseCell -local AcquireTable, ReleaseTable - -local InitializeTooltip, SetTooltipSize, ResetTooltipSize, FixCellSizes -local ClearTooltipScripts -local SetFrameScript, ClearFrameScripts - ------------------------------------------------------------------------------- --- Cache debugging. ------------------------------------------------------------------------------- --- @debug @ -local usedTables, usedFrames, usedTooltips = 0, 0, 0 ---@end-debug@]==] - ------------------------------------------------------------------------------- --- Internal constants to tweak the layout ------------------------------------------------------------------------------- -local TOOLTIP_PADDING = 10 -local CELL_MARGIN_H = 6 -local CELL_MARGIN_V = 3 - ------------------------------------------------------------------------------- --- Public library API ------------------------------------------------------------------------------- ---- Create or retrieve the tooltip with the given key. --- If additional arguments are passed, they are passed to :SetColumnLayout for the acquired tooltip. --- @name LibQTip:Acquire(key[, numColumns, column1Justification, column2justification, ...]) --- @param key string or table - the tooltip key. Any value that can be used as a table key is accepted though you should try to provide unique keys to avoid conflicts. --- Numbers and booleans should be avoided and strings should be carefully chosen to avoid namespace clashes - no "MyTooltip" - you have been warned! --- @return tooltip Frame object - the acquired tooltip. --- @usage Acquire a tooltip with at least 5 columns, justification : left, center, left, left, left --- <pre>local tip = LibStub('LibQTip-1.0'):Acquire('MyFooBarTooltip', 5, "LEFT", "CENTER")</pre> -function lib:Acquire(key, ...) - if key == nil then - error("attempt to use a nil key", 2) - end - - local tooltip = activeTooltips[key] - - if not tooltip then - tooltip = AcquireTooltip() - InitializeTooltip(tooltip, key) - activeTooltips[key] = tooltip - end - - if select("#", ...) > 0 then - -- Here we catch any error to properly report it for the calling code - local ok, msg = pcall(tooltip.SetColumnLayout, tooltip, ...) - - if not ok then - error(msg, 2) - end - end - - return tooltip -end - -function lib:Release(tooltip) - local key = tooltip and tooltip.key - - if not key or activeTooltips[key] ~= tooltip then - return - end - - ReleaseTooltip(tooltip) - activeTooltips[key] = nil -end - -function lib:IsAcquired(key) - if key == nil then - error("attempt to use a nil key", 2) - end - - return not (not activeTooltips[key]) -end - -function lib:IterateTooltips() - return pairs(activeTooltips) -end - ------------------------------------------------------------------------------- --- Frame cache (for lines and columns) ------------------------------------------------------------------------------- -local frameHeap = lib.frameHeap - -local function AcquireFrame(parent) - local frame = tremove(frameHeap) or CreateFrame("Frame", nil, nil, BackdropTemplateMixin and "BackdropTemplate") - frame:SetParent(parent) - --[==[@debug@ - usedFrames = usedFrames + 1 - --@end-debug@]==] - return frame -end - -local function ReleaseFrame(frame) - frame:Hide() - frame:SetParent(nil) - frame:ClearAllPoints() - frame:SetBackdrop(nil) - - ClearFrameScripts(frame) - - tinsert(frameHeap, frame) - --[==[@debug@ - usedFrames = usedFrames - 1 - --@end-debug@]==] -end - ------------------------------------------------------------------------------- --- Timer cache ------------------------------------------------------------------------------- -local timerHeap = lib.timerHeap - -local function AcquireTimer(parent) - local frame = tremove(timerHeap) or CreateFrame("Frame") - frame:SetParent(parent) - return frame -end - -local function ReleaseTimer(frame) - frame:Hide() - frame:SetParent(nil) - - ClearFrameScripts(frame) - - tinsert(timerHeap, frame) -end - ------------------------------------------------------------------------------- --- Dirty layout handler ------------------------------------------------------------------------------- -lib.layoutCleaner = lib.layoutCleaner or CreateFrame("Frame") - -local layoutCleaner = lib.layoutCleaner -layoutCleaner.registry = layoutCleaner.registry or {} - -function layoutCleaner:RegisterForCleanup(tooltip) - self.registry[tooltip] = true - self:Show() -end - -function layoutCleaner:CleanupLayouts() - self:Hide() - - for tooltip in pairs(self.registry) do - FixCellSizes(tooltip) - end - - wipe(self.registry) -end - -layoutCleaner:SetScript("OnUpdate", layoutCleaner.CleanupLayouts) - ------------------------------------------------------------------------------- --- CellProvider and Cell ------------------------------------------------------------------------------- -function providerPrototype:AcquireCell() - local cell = tremove(self.heap) - - if not cell then - cell = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate") - setmetatable(cell, self.cellMetatable) - - if type(cell.InitializeCell) == "function" then - cell:InitializeCell() - end - end - - self.cells[cell] = true - - return cell -end - -function providerPrototype:ReleaseCell(cell) - if not self.cells[cell] then - return - end - - if type(cell.ReleaseCell) == "function" then - cell:ReleaseCell() - end - - self.cells[cell] = nil - tinsert(self.heap, cell) -end - -function providerPrototype:GetCellPrototype() - return self.cellPrototype, self.cellMetatable -end - -function providerPrototype:IterateCells() - return pairs(self.cells) -end - -function lib:CreateCellProvider(baseProvider) - local cellBaseMetatable, cellBasePrototype - - if baseProvider and baseProvider.GetCellPrototype then - cellBasePrototype, cellBaseMetatable = baseProvider:GetCellPrototype() - else - cellBaseMetatable = cellMetatable - end - - local newCellPrototype = setmetatable({}, cellBaseMetatable) - local newCellProvider = setmetatable({}, providerMetatable) - - newCellProvider.heap = {} - newCellProvider.cells = {} - newCellProvider.cellPrototype = newCellPrototype - newCellProvider.cellMetatable = {__index = newCellPrototype} - - return newCellProvider, newCellPrototype, cellBasePrototype -end - ------------------------------------------------------------------------------- --- Basic label provider ------------------------------------------------------------------------------- -if not lib.LabelProvider then - lib.LabelProvider, lib.LabelPrototype = lib:CreateCellProvider() -end - -local labelProvider = lib.LabelProvider -local labelPrototype = lib.LabelPrototype - -function labelPrototype:InitializeCell() - self.fontString = self:CreateFontString() - self.fontString:SetFontObject(_G.GameTooltipText) -end - -function labelPrototype:SetupCell(tooltip, value, justification, font, leftPadding, rightPadding, maxWidth, minWidth, ...) - local fontString = self.fontString - local line = tooltip.lines[self._line] - - -- detatch fs from cell for size calculations - fontString:ClearAllPoints() - fontString:SetFontObject(font or (line.is_header and tooltip:GetHeaderFont() or tooltip:GetFont())) - fontString:SetJustifyH(justification) - fontString:SetText(tostring(value)) - - leftPadding = leftPadding or 0 - rightPadding = rightPadding or 0 - - local width = fontString:GetStringWidth() + leftPadding + rightPadding - - if maxWidth and minWidth and (maxWidth < minWidth) then - error("maximum width cannot be lower than minimum width: " .. tostring(maxWidth) .. " < " .. tostring(minWidth), 2) - end - - if maxWidth and (maxWidth < (leftPadding + rightPadding)) then - error("maximum width cannot be lower than the sum of paddings: " .. tostring(maxWidth) .. " < " .. tostring(leftPadding) .. " + " .. tostring(rightPadding), 2) - end - - if minWidth and width < minWidth then - width = minWidth - end - - if maxWidth and maxWidth < width then - width = maxWidth - end - - fontString:SetWidth(width - (leftPadding + rightPadding)) - -- Use GetHeight() instead of GetStringHeight() so lines which are longer than width will wrap. - local height = fontString:GetHeight() - - -- reanchor fs to cell - fontString:SetWidth(0) - fontString:SetPoint("TOPLEFT", self, "TOPLEFT", leftPadding, 0) - fontString:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -rightPadding, 0) - --~ fs:SetPoint("TOPRIGHT", self, "TOPRIGHT", -r_pad, 0) - - self._paddingL = leftPadding - self._paddingR = rightPadding - - return width, height -end - -function labelPrototype:getContentHeight() - local fontString = self.fontString - fontString:SetWidth(self:GetWidth() - (self._paddingL + self._paddingR)) - - local height = self.fontString:GetHeight() - fontString:SetWidth(0) - - return height -end - -function labelPrototype:GetPosition() - return self._line, self._column -end - ------------------------------------------------------------------------------- --- Tooltip cache ------------------------------------------------------------------------------- -local tooltipHeap = lib.tooltipHeap - --- Returns a tooltip -function AcquireTooltip() - local tooltip = tremove(tooltipHeap) - - if not tooltip then - local template = (TooltipBackdropTemplateMixin and "TooltipBackdropTemplate") or (BackdropTemplateMixin and "BackdropTemplate") - tooltip = CreateFrame("Frame", nil, UIParent, template) - - local scrollFrame = CreateFrame("ScrollFrame", nil, tooltip) - scrollFrame:SetPoint("TOP", tooltip, "TOP", 0, -TOOLTIP_PADDING) - scrollFrame:SetPoint("BOTTOM", tooltip, "BOTTOM", 0, TOOLTIP_PADDING) - scrollFrame:SetPoint("LEFT", tooltip, "LEFT", TOOLTIP_PADDING, 0) - scrollFrame:SetPoint("RIGHT", tooltip, "RIGHT", -TOOLTIP_PADDING, 0) - tooltip.scrollFrame = scrollFrame - - local scrollChild = CreateFrame("Frame", nil, tooltip.scrollFrame) - scrollFrame:SetScrollChild(scrollChild) - tooltip.scrollChild = scrollChild - - setmetatable(tooltip, tipMetatable) - end - - --[==[@debug@ - usedTooltips = usedTooltips + 1 - --@end-debug@]==] - return tooltip -end - --- Cleans the tooltip and stores it in the cache -function ReleaseTooltip(tooltip) - if tooltip.releasing then - return - end - - tooltip.releasing = true - tooltip:Hide() - - local releaseHandler = lib.onReleaseHandlers[tooltip] - - if releaseHandler then - lib.onReleaseHandlers[tooltip] = nil - - local success, errorMessage = pcall(releaseHandler, tooltip) - - if not success then - geterrorhandler()(errorMessage) - end - elseif tooltip.OnRelease then - local success, errorMessage = pcall(tooltip.OnRelease, tooltip) - if not success then - geterrorhandler()(errorMessage) - end - - tooltip.OnRelease = nil - end - - tooltip.releasing = nil - tooltip.key = nil - tooltip.step = nil - - ClearTooltipScripts(tooltip) - - tooltip:SetAutoHideDelay(nil) - tooltip:ClearAllPoints() - tooltip:Clear() - - if tooltip.slider then - tooltip.slider:SetValue(0) - tooltip.slider:Hide() - tooltip.scrollFrame:SetPoint("RIGHT", tooltip, "RIGHT", -TOOLTIP_PADDING, 0) - tooltip:EnableMouseWheel(false) - end - - for i, column in ipairs(tooltip.columns) do - tooltip.columns[i] = ReleaseFrame(column) - end - - tooltip.columns = ReleaseTable(tooltip.columns) - tooltip.lines = ReleaseTable(tooltip.lines) - tooltip.colspans = ReleaseTable(tooltip.colspans) - - layoutCleaner.registry[tooltip] = nil - - if TooltipBackdropTemplateMixin and not tooltip.NineSlice then - -- don't recycle outdated tooltips into heap - tooltip = nil - end - - if tooltip then - tinsert(tooltipHeap, tooltip) - end - - highlightTexture:SetTexture(DEFAULT_HIGHLIGHT_TEXTURE_PATH) - highlightTexture:SetTexCoord(0, 1, 0, 1) - - --[==[@debug@ - usedTooltips = usedTooltips - 1 - --@end-debug@]==] -end - ------------------------------------------------------------------------------- --- Cell 'cache' (just a wrapper to the provider's cache) ------------------------------------------------------------------------------- --- Returns a cell for the given tooltip from the given provider -function AcquireCell(tooltip, provider) - local cell = provider:AcquireCell(tooltip) - - cell:SetParent(tooltip.scrollChild) - cell:SetFrameLevel(tooltip.scrollChild:GetFrameLevel() + 3) - cell._provider = provider - - return cell -end - --- Cleans the cell hands it to its provider for storing -function ReleaseCell(cell) - if cell.fontString and cell.r then - cell.fontString:SetTextColor(cell.r, cell.g, cell.b, cell.a) - end - - cell._font = nil - cell._justification = nil - cell._colSpan = nil - cell._line = nil - cell._column = nil - - cell:Hide() - cell:ClearAllPoints() - cell:SetParent(nil) - cell:SetBackdrop(nil) - - ClearFrameScripts(cell) - - cell._provider:ReleaseCell(cell) - cell._provider = nil -end - ------------------------------------------------------------------------------- --- Table cache ------------------------------------------------------------------------------- -local tableHeap = lib.tableHeap - --- Returns a table -function AcquireTable() - local tbl = tremove(tableHeap) or {} - --[==[@debug@ - usedTables = usedTables + 1 - --@end-debug@]==] - return tbl -end - --- Cleans the table and stores it in the cache -function ReleaseTable(tableInstance) - wipe(tableInstance) - tinsert(tableHeap, tableInstance) - --[==[@debug@ - usedTables = usedTables - 1 - --@end-debug@]==] -end - ------------------------------------------------------------------------------- --- Tooltip prototype ------------------------------------------------------------------------------- -function InitializeTooltip(tooltip, key) - ---------------------------------------------------------------------- - -- (Re)set frame settings - ---------------------------------------------------------------------- - if TooltipBackdropTemplateMixin then - tooltip.layoutType = GameTooltip.layoutType - NineSlicePanelMixin.OnLoad(tooltip.NineSlice) - if GameTooltip.layoutType then - tooltip.NineSlice:SetCenterColor(GameTooltip.NineSlice:GetCenterColor()) - tooltip.NineSlice:SetBorderColor(GameTooltip.NineSlice:GetBorderColor()) - end - else - local backdrop = GameTooltip:GetBackdrop() - - tooltip:SetBackdrop(backdrop) - - if backdrop then - tooltip:SetBackdropColor(GameTooltip:GetBackdropColor()) - tooltip:SetBackdropBorderColor(GameTooltip:GetBackdropBorderColor()) - end - end - - tooltip:SetScale(GameTooltip:GetScale()) - tooltip:SetAlpha(1) - tooltip:SetFrameStrata("TOOLTIP") - tooltip:SetClampedToScreen(false) - - ---------------------------------------------------------------------- - -- Internal data. Since it's possible to Acquire twice without calling - -- release, check for pre-existence. - ---------------------------------------------------------------------- - tooltip.key = key - tooltip.columns = tooltip.columns or AcquireTable() - tooltip.lines = tooltip.lines or AcquireTable() - tooltip.colspans = tooltip.colspans or AcquireTable() - tooltip.regularFont = _G.GameTooltipText - tooltip.headerFont = _G.GameTooltipHeaderText - tooltip.labelProvider = labelProvider - tooltip.cell_margin_h = tooltip.cell_margin_h or CELL_MARGIN_H - tooltip.cell_margin_v = tooltip.cell_margin_v or CELL_MARGIN_V - - ---------------------------------------------------------------------- - -- Finishing procedures - ---------------------------------------------------------------------- - tooltip:SetAutoHideDelay(nil) - tooltip:Hide() - ResetTooltipSize(tooltip) -end - -function tipPrototype:SetDefaultProvider(myProvider) - if not myProvider then - return - end - - self.labelProvider = myProvider -end - -function tipPrototype:GetDefaultProvider() - return self.labelProvider -end - -local function checkJustification(justification, level, silent) - if justification ~= "LEFT" and justification ~= "CENTER" and justification ~= "RIGHT" then - if silent then - return false - end - error("invalid justification, must one of LEFT, CENTER or RIGHT, not: " .. tostring(justification), level + 1) - end - - return true -end - -function tipPrototype:SetColumnLayout(numColumns, ...) - if type(numColumns) ~= "number" or numColumns < 1 then - error("number of columns must be a positive number, not: " .. tostring(numColumns), 2) - end - - for i = 1, numColumns do - local justification = select(i, ...) or "LEFT" - - checkJustification(justification, 2) - - if self.columns[i] then - self.columns[i].justification = justification - else - self:AddColumn(justification) - end - end -end - -function tipPrototype:AddColumn(justification) - justification = justification or "LEFT" - checkJustification(justification, 2) - - local colNum = #self.columns + 1 - local column = self.columns[colNum] or AcquireFrame(self.scrollChild) - - column:SetFrameLevel(self.scrollChild:GetFrameLevel() + 1) - column.justification = justification - column.width = 0 - column:SetWidth(1) - column:SetPoint("TOP", self.scrollChild) - column:SetPoint("BOTTOM", self.scrollChild) - - if colNum > 1 then - local h_margin = self.cell_margin_h or CELL_MARGIN_H - - column:SetPoint("LEFT", self.columns[colNum - 1], "RIGHT", h_margin, 0) - SetTooltipSize(self, self.width + h_margin, self.height) - else - column:SetPoint("LEFT", self.scrollChild) - end - - column:Show() - self.columns[colNum] = column - - return colNum -end - ------------------------------------------------------------------------------- --- Convenient methods ------------------------------------------------------------------------------- -function tipPrototype:Release() - lib:Release(self) -end - -function tipPrototype:IsAcquiredBy(key) - return key ~= nil and self.key == key -end - ------------------------------------------------------------------------------- --- Script hooks ------------------------------------------------------------------------------- -local RawSetScript = lib.frameMetatable.__index.SetScript - -function ClearTooltipScripts(tooltip) - if tooltip.scripts then - for scriptType in pairs(tooltip.scripts) do - RawSetScript(tooltip, scriptType, nil) - end - - tooltip.scripts = ReleaseTable(tooltip.scripts) - end -end - -function tipPrototype:SetScript(scriptType, handler) - RawSetScript(self, scriptType, handler) - - if handler then - if not self.scripts then - self.scripts = AcquireTable() - end - - self.scripts[scriptType] = true - elseif self.scripts then - self.scripts[scriptType] = nil - end -end - --- That might break some addons ; those addons were breaking other --- addons' tooltip though. -function tipPrototype:HookScript() - geterrorhandler()(":HookScript is not allowed on LibQTip tooltips") -end - ------------------------------------------------------------------------------- --- Scrollbar data and functions ------------------------------------------------------------------------------- -local BACKDROP_SLIDER_8_8 = BACKDROP_SLIDER_8_8 or { - bgFile = "Interface\\Buttons\\UI-SliderBar-Background", - edgeFile = "Interface\\Buttons\\UI-SliderBar-Border", - tile = true, - tileEdge = true, - tileSize = 8, - edgeSize = 8, - insets = { left = 3, right = 3, top = 6, bottom = 6 }, -}; - -local function slider_OnValueChanged(self) - self.scrollFrame:SetVerticalScroll(self:GetValue()) -end - -local function tooltip_OnMouseWheel(self, delta) - local slider = self.slider - local currentValue = slider:GetValue() - local minValue, maxValue = slider:GetMinMaxValues() - local stepValue = self.step or 10 - - if delta < 0 and currentValue < maxValue then - slider:SetValue(min(maxValue, currentValue + stepValue)) - elseif delta > 0 and currentValue > minValue then - slider:SetValue(max(minValue, currentValue - stepValue)) - end -end - --- Set the step size for the scroll bar -function tipPrototype:SetScrollStep(step) - self.step = step -end - --- will resize the tooltip to fit the screen and show a scrollbar if needed -function tipPrototype:UpdateScrolling(maxheight) - self:SetClampedToScreen(false) - - -- all data is in the tooltip; fix colspan width and prevent the layout cleaner from messing up the tooltip later - FixCellSizes(self) - layoutCleaner.registry[self] = nil - - local scale = self:GetScale() - local topside = self:GetTop() - local bottomside = self:GetBottom() - local screensize = UIParent:GetHeight() / scale - local tipsize = (topside - bottomside) - - -- if the tooltip would be too high, limit its height and show the slider - if bottomside < 0 or topside > screensize or (maxheight and tipsize > maxheight) then - local shrink = (bottomside < 0 and (5 - bottomside) or 0) + (topside > screensize and (topside - screensize + 5) or 0) - - if maxheight and tipsize - shrink > maxheight then - shrink = tipsize - maxheight - end - - self:SetHeight(2 * TOOLTIP_PADDING + self.height - shrink) - self:SetWidth(2 * TOOLTIP_PADDING + self.width + 20) - self.scrollFrame:SetPoint("RIGHT", self, "RIGHT", -(TOOLTIP_PADDING + 20), 0) - - if not self.slider then - local slider = CreateFrame("Slider", nil, self, BackdropTemplateMixin and "BackdropTemplate") - slider.scrollFrame = self.scrollFrame - - slider:SetOrientation("VERTICAL") - slider:SetPoint("TOPRIGHT", self, "TOPRIGHT", -TOOLTIP_PADDING, -TOOLTIP_PADDING) - slider:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -TOOLTIP_PADDING, TOOLTIP_PADDING) - slider:SetBackdrop(BACKDROP_SLIDER_8_8) - slider:SetThumbTexture([[Interface\Buttons\UI-SliderBar-Button-Vertical]]) - slider:SetMinMaxValues(0, 1) - slider:SetValueStep(1) - slider:SetWidth(12) - slider:SetScript("OnValueChanged", slider_OnValueChanged) - slider:SetValue(0) - - self.slider = slider - end - - self.slider:SetMinMaxValues(0, shrink) - self.slider:Show() - - self:EnableMouseWheel(true) - self:SetScript("OnMouseWheel", tooltip_OnMouseWheel) - else - self:SetHeight(2 * TOOLTIP_PADDING + self.height) - self:SetWidth(2 * TOOLTIP_PADDING + self.width) - - self.scrollFrame:SetPoint("RIGHT", self, "RIGHT", -TOOLTIP_PADDING, 0) - - if self.slider then - self.slider:SetValue(0) - self.slider:Hide() - - self:EnableMouseWheel(false) - self:SetScript("OnMouseWheel", nil) - end - end -end - ------------------------------------------------------------------------------- --- Tooltip methods for changing its contents. ------------------------------------------------------------------------------- -function tipPrototype:Clear() - for i, line in ipairs(self.lines) do - for _, cell in pairs(line.cells) do - if cell then - ReleaseCell(cell) - end - end - - ReleaseTable(line.cells) - - line.cells = nil - line.is_header = nil - - ReleaseFrame(line) - - self.lines[i] = nil - end - - for _, column in ipairs(self.columns) do - column.width = 0 - column:SetWidth(1) - end - - wipe(self.colspans) - - self.cell_margin_h = nil - self.cell_margin_v = nil - - ResetTooltipSize(self) -end - -function tipPrototype:SetCellMarginH(size) - if #self.lines > 0 then - error("Unable to set horizontal margin while the tooltip has lines.", 2) - end - - if not size or type(size) ~= "number" or size < 0 then - error("Margin size must be a positive number or zero.", 2) - end - - self.cell_margin_h = size -end - -function tipPrototype:SetCellMarginV(size) - if #self.lines > 0 then - error("Unable to set vertical margin while the tooltip has lines.", 2) - end - - if not size or type(size) ~= "number" or size < 0 then - error("Margin size must be a positive number or zero.", 2) - end - - self.cell_margin_v = size -end - -function SetTooltipSize(tooltip, width, height) - tooltip.height = height - tooltip.width = width - - tooltip:SetHeight(2 * TOOLTIP_PADDING + height) - tooltip:SetWidth(2 * TOOLTIP_PADDING + width) - - tooltip.scrollChild:SetHeight(height) - tooltip.scrollChild:SetWidth(width) -end - --- Add 2 pixels to height so dangling letters (g, y, p, j, etc) are not clipped. -function ResetTooltipSize(tooltip) - local h_margin = tooltip.cell_margin_h or CELL_MARGIN_H - - SetTooltipSize(tooltip, max(0, (h_margin * (#tooltip.columns - 1)) + (h_margin / 2)), 2) -end - -local function EnlargeColumn(tooltip, column, width) - if width > column.width then - SetTooltipSize(tooltip, tooltip.width + width - column.width, tooltip.height) - - column.width = width - column:SetWidth(width) - end -end - -local function ResizeLine(tooltip, line, height) - SetTooltipSize(tooltip, tooltip.width, tooltip.height + height - line.height) - - line.height = height - line:SetHeight(height) -end - -function FixCellSizes(tooltip) - local columns = tooltip.columns - local colspans = tooltip.colspans - local lines = tooltip.lines - local h_margin = tooltip.cell_margin_h or CELL_MARGIN_H - - -- resize columns to make room for the colspans - while next(colspans) do - local maxNeedCols - local maxNeedWidthPerCol = 0 - - -- calculate the colspan with the highest additional width need per column - for colRange, width in pairs(colspans) do - local left, right = colRange:match("^(%d+)%-(%d+)$") - - left, right = tonumber(left), tonumber(right) - - for col = left, right - 1 do - width = width - columns[col].width - h_margin - end - - width = width - columns[right].width - - if width <= 0 then - colspans[colRange] = nil - else - width = width / (right - left + 1) - - if width > maxNeedWidthPerCol then - maxNeedCols = colRange - maxNeedWidthPerCol = width - end - end - end - - -- resize all columns for that colspan - if maxNeedCols then - local left, right = maxNeedCols:match("^(%d+)%-(%d+)$") - - for col = left, right do - EnlargeColumn(tooltip, columns[col], columns[col].width + maxNeedWidthPerCol) - end - - colspans[maxNeedCols] = nil - end - end - - --now that the cell width is set, recalculate the rows' height - for _, line in ipairs(lines) do - if #(line.cells) > 0 then - local lineheight = 0 - - for _, cell in pairs(line.cells) do - if cell then - lineheight = max(lineheight, cell:getContentHeight()) - end - end - - if lineheight > 0 then - ResizeLine(tooltip, line, lineheight) - end - end - end -end - -local function _SetCell(tooltip, lineNum, colNum, value, font, justification, colSpan, provider, ...) - local line = tooltip.lines[lineNum] - local cells = line.cells - - -- Unset: be quick - if value == nil then - local cell = cells[colNum] - - if cell then - for i = colNum, colNum + cell._colSpan - 1 do - cells[i] = nil - end - - ReleaseCell(cell) - end - - return lineNum, colNum - end - - font = font or (line.is_header and tooltip.headerFont or tooltip.regularFont) - - -- Check previous cell - local cell - local prevCell = cells[colNum] - - if prevCell then - -- There is a cell here - justification = justification or prevCell._justification - colSpan = colSpan or prevCell._colSpan - - -- Clear the currently marked colspan - for i = colNum + 1, colNum + prevCell._colSpan - 1 do - cells[i] = nil - end - - if provider == nil or prevCell._provider == provider then - -- Reuse existing cell - cell = prevCell - provider = cell._provider - else - -- A new cell is required - cells[colNum] = ReleaseCell(prevCell) - end - elseif prevCell == nil then - -- Creating a new cell, using meaningful defaults. - provider = provider or tooltip.labelProvider - justification = justification or tooltip.columns[colNum].justification or "LEFT" - colSpan = colSpan or 1 - else - error("overlapping cells at column " .. colNum, 3) - end - - local tooltipWidth = #tooltip.columns - local rightColNum - - if colSpan > 0 then - rightColNum = colNum + colSpan - 1 - - if rightColNum > tooltipWidth then - error("ColSpan too big, cell extends beyond right-most column", 3) - end - else - -- Zero or negative: count back from right-most columns - rightColNum = max(colNum, tooltipWidth + colSpan) - -- Update colspan to its effective value - colSpan = 1 + rightColNum - colNum - end - - -- Cleanup colspans - for i = colNum + 1, rightColNum do - local columnCell = cells[i] - - if columnCell then - ReleaseCell(columnCell) - elseif columnCell == false then - error("overlapping cells at column " .. i, 3) - end - - cells[i] = false - end - - -- Create the cell - if not cell then - cell = AcquireCell(tooltip, provider) - cells[colNum] = cell - end - - -- Anchor the cell - cell:SetPoint("LEFT", tooltip.columns[colNum]) - cell:SetPoint("RIGHT", tooltip.columns[rightColNum]) - cell:SetPoint("TOP", line) - cell:SetPoint("BOTTOM", line) - - -- Store the cell settings directly into the cell - -- That's a bit risky but is really cheap compared to other ways to do it - cell._font, cell._justification, cell._colSpan, cell._line, cell._column = font, justification, colSpan, lineNum, colNum - - -- Setup the cell content - local width, height = cell:SetupCell(tooltip, value, justification, font, ...) - cell:Show() - - if colSpan > 1 then - -- Postpone width changes until the tooltip is shown - local colRange = colNum .. "-" .. rightColNum - - tooltip.colspans[colRange] = max(tooltip.colspans[colRange] or 0, width) - layoutCleaner:RegisterForCleanup(tooltip) - else - -- Enlarge the column and tooltip if need be - EnlargeColumn(tooltip, tooltip.columns[colNum], width) - end - - -- Enlarge the line and tooltip if need be - if height > line.height then - SetTooltipSize(tooltip, tooltip.width, tooltip.height + height - line.height) - - line.height = height - line:SetHeight(height) - end - - if rightColNum < tooltipWidth then - return lineNum, rightColNum + 1 - else - return lineNum, nil - end -end - -do - local function CreateLine(tooltip, font, ...) - if #tooltip.columns == 0 then - error("column layout should be defined before adding line", 3) - end - - local lineNum = #tooltip.lines + 1 - local line = tooltip.lines[lineNum] or AcquireFrame(tooltip.scrollChild) - - line:SetFrameLevel(tooltip.scrollChild:GetFrameLevel() + 2) - line:SetPoint("LEFT", tooltip.scrollChild) - line:SetPoint("RIGHT", tooltip.scrollChild) - - if lineNum > 1 then - local v_margin = tooltip.cell_margin_v or CELL_MARGIN_V - - line:SetPoint("TOP", tooltip.lines[lineNum - 1], "BOTTOM", 0, -v_margin) - SetTooltipSize(tooltip, tooltip.width, tooltip.height + v_margin) - else - line:SetPoint("TOP", tooltip.scrollChild) - end - - tooltip.lines[lineNum] = line - - line.cells = line.cells or AcquireTable() - line.height = 0 - line:SetHeight(1) - line:Show() - - local colNum = 1 - - for i = 1, #tooltip.columns do - local value = select(i, ...) - - if value ~= nil then - lineNum, colNum = _SetCell(tooltip, lineNum, i, value, font, nil, 1, tooltip.labelProvider) - end - end - - return lineNum, colNum - end - - function tipPrototype:AddLine(...) - return CreateLine(self, self.regularFont, ...) - end - - function tipPrototype:AddHeader(...) - local line, col = CreateLine(self, self.headerFont, ...) - - self.lines[line].is_header = true - - return line, col - end -end -- do-block - -local GenericBackdrop = { - bgFile = "Interface\\Tooltips\\UI-Tooltip-Background" -} - -function tipPrototype:AddSeparator(height, r, g, b, a) - local lineNum, colNum = self:AddLine() - local line = self.lines[lineNum] - local color = _G.NORMAL_FONT_COLOR - - height = height or 1 - - SetTooltipSize(self, self.width, self.height + height) - - line.height = height - line:SetHeight(height) - line:SetBackdrop(GenericBackdrop) - line:SetBackdropColor(r or color.r, g or color.g, b or color.b, a or 1) - - return lineNum, colNum -end - -function tipPrototype:SetCellColor(lineNum, colNum, r, g, b, a) - local cell = self.lines[lineNum].cells[colNum] - - if cell then - local sr, sg, sb, sa = self:GetBackdropColor() - - cell:SetBackdrop(GenericBackdrop) - cell:SetBackdropColor(r or sr, g or sg, b or sb, a or sa) - end -end - -function tipPrototype:SetColumnColor(colNum, r, g, b, a) - local column = self.columns[colNum] - - if column then - local sr, sg, sb, sa = self:GetBackdropColor() - column:SetBackdrop(GenericBackdrop) - column:SetBackdropColor(r or sr, g or sg, b or sb, a or sa) - end -end - -function tipPrototype:SetLineColor(lineNum, r, g, b, a) - local line = self.lines[lineNum] - - if line then - local sr, sg, sb, sa = self:GetBackdropColor() - - line:SetBackdrop(GenericBackdrop) - line:SetBackdropColor(r or sr, g or sg, b or sb, a or sa) - end -end - -function tipPrototype:SetCellTextColor(lineNum, colNum, r, g, b, a) - local line = self.lines[lineNum] - local column = self.columns[colNum] - - if not line or not column then - return - end - - local cell = self.lines[lineNum].cells[colNum] - - if cell then - if not cell.fontString then - error("cell's label provider did not assign a fontString field", 2) - end - - if not cell.r then - cell.r, cell.g, cell.b, cell.a = cell.fontString:GetTextColor() - end - - cell.fontString:SetTextColor(r or cell.r, g or cell.g, b or cell.b, a or cell.a) - end -end - -function tipPrototype:SetColumnTextColor(colNum, r, g, b, a) - if not self.columns[colNum] then - return - end - - for lineIndex = 1, #self.lines do - self:SetCellTextColor(lineIndex, colNum, r, g, b, a) - end -end - -function tipPrototype:SetLineTextColor(lineNum, r, g, b, a) - local line = self.lines[lineNum] - - if not line then - return - end - - for cellIndex = 1, #line.cells do - self:SetCellTextColor(lineNum, line.cells[cellIndex]._column, r, g, b, a) - end -end - -function tipPrototype:SetHighlightTexture(...) - return highlightTexture:SetTexture(...) -end - -function tipPrototype:SetHighlightTexCoord(...) - highlightTexture:SetTexCoord(...) -end - -do - local function checkFont(font, level, silent) - local bad = false - - if not font then - bad = true - elseif type(font) == "string" then - local ref = _G[font] - - if not ref or type(ref) ~= "table" or type(ref.IsObjectType) ~= "function" or not ref:IsObjectType("Font") then - bad = true - end - elseif type(font) ~= "table" or type(font.IsObjectType) ~= "function" or not font:IsObjectType("Font") then - bad = true - end - - if bad then - if silent then - return false - end - - error("font must be a Font instance or a string matching the name of a global Font instance, not: " .. tostring(font), level + 1) - end - return true - end - - function tipPrototype:SetFont(font) - local is_string = type(font) == "string" - - checkFont(font, 2) - self.regularFont = is_string and _G[font] or font - end - - function tipPrototype:SetHeaderFont(font) - local is_string = type(font) == "string" - - checkFont(font, 2) - self.headerFont = is_string and _G[font] or font - end - - -- TODO: fixed argument positions / remove checks for performance? - function tipPrototype:SetCell(lineNum, colNum, value, ...) - -- Mandatory argument checking - if type(lineNum) ~= "number" then - error("line number must be a number, not: " .. tostring(lineNum), 2) - elseif lineNum < 1 or lineNum > #self.lines then - error("line number out of range: " .. tostring(lineNum), 2) - elseif type(colNum) ~= "number" then - error("column number must be a number, not: " .. tostring(colNum), 2) - elseif colNum < 1 or colNum > #self.columns then - error("column number out of range: " .. tostring(colNum), 2) - end - - -- Variable argument checking - local font, justification, colSpan, provider - local i, arg = 1, ... - - if arg == nil or checkFont(arg, 2, true) then - i, font, arg = 2, ... - end - - if arg == nil or checkJustification(arg, 2, true) then - i, justification, arg = i + 1, select(i, ...) - end - - if arg == nil or type(arg) == "number" then - i, colSpan, arg = i + 1, select(i, ...) - end - - if arg == nil or type(arg) == "table" and type(arg.AcquireCell) == "function" then - i, provider = i + 1, arg - end - - return _SetCell(self, lineNum, colNum, value, font, justification, colSpan, provider, select(i, ...)) - end -end -- do-block - -function tipPrototype:GetFont() - return self.regularFont -end - -function tipPrototype:GetHeaderFont() - return self.headerFont -end - -function tipPrototype:GetLineCount() - return #self.lines -end - -function tipPrototype:GetColumnCount() - return #self.columns -end - ------------------------------------------------------------------------------- --- Frame Scripts ------------------------------------------------------------------------------- -local scripts = { - OnEnter = function(frame, ...) - highlightFrame:SetParent(frame) - highlightFrame:SetAllPoints(frame) - highlightFrame:Show() - - if frame._OnEnter_func then - frame:_OnEnter_func(frame._OnEnter_arg, ...) - end - end, - OnLeave = function(frame, ...) - highlightFrame:Hide() - highlightFrame:ClearAllPoints() - highlightFrame:SetParent(nil) - - if frame._OnLeave_func then - frame:_OnLeave_func(frame._OnLeave_arg, ...) - end - end, - OnMouseDown = function(frame, ...) - frame:_OnMouseDown_func(frame._OnMouseDown_arg, ...) - end, - OnMouseUp = function(frame, ...) - frame:_OnMouseUp_func(frame._OnMouseUp_arg, ...) - end, - OnReceiveDrag = function(frame, ...) - frame:_OnReceiveDrag_func(frame._OnReceiveDrag_arg, ...) - end -} - -function SetFrameScript(frame, script, func, arg) - if not scripts[script] then - return - end - - frame["_" .. script .. "_func"] = func - frame["_" .. script .. "_arg"] = arg - - if script == "OnMouseDown" or script == "OnMouseUp" or script == "OnReceiveDrag" then - if func then - frame:SetScript(script, scripts[script]) - else - frame:SetScript(script, nil) - end - end - - -- if at least one script is set, set the OnEnter/OnLeave scripts for the highlight - if frame._OnEnter_func or frame._OnLeave_func or frame._OnMouseDown_func or frame._OnMouseUp_func or frame._OnReceiveDrag_func then - frame:EnableMouse(true) - frame:SetScript("OnEnter", scripts.OnEnter) - frame:SetScript("OnLeave", scripts.OnLeave) - else - frame:EnableMouse(false) - frame:SetScript("OnEnter", nil) - frame:SetScript("OnLeave", nil) - end -end - -function ClearFrameScripts(frame) - if frame._OnEnter_func or frame._OnLeave_func or frame._OnMouseDown_func or frame._OnMouseUp_func or frame._OnReceiveDrag_func then - frame:EnableMouse(false) - - frame:SetScript("OnEnter", nil) - frame._OnEnter_func = nil - frame._OnEnter_arg = nil - - frame:SetScript("OnLeave", nil) - frame._OnLeave_func = nil - frame._OnLeave_arg = nil - - frame:SetScript("OnReceiveDrag", nil) - frame._OnReceiveDrag_func = nil - frame._OnReceiveDrag_arg = nil - - frame:SetScript("OnMouseDown", nil) - frame._OnMouseDown_func = nil - frame._OnMouseDown_arg = nil - - frame:SetScript("OnMouseUp", nil) - frame._OnMouseUp_func = nil - frame._OnMouseUp_arg = nil - end -end - -function tipPrototype:SetLineScript(lineNum, script, func, arg) - SetFrameScript(self.lines[lineNum], script, func, arg) -end - -function tipPrototype:SetColumnScript(colNum, script, func, arg) - SetFrameScript(self.columns[colNum], script, func, arg) -end - -function tipPrototype:SetCellScript(lineNum, colNum, script, func, arg) - local cell = self.lines[lineNum].cells[colNum] - - if cell then - SetFrameScript(cell, script, func, arg) - end -end - ------------------------------------------------------------------------------- --- Auto-hiding feature ------------------------------------------------------------------------------- - --- Script of the auto-hiding child frame -local function AutoHideTimerFrame_OnUpdate(self, elapsed) - self.checkElapsed = self.checkElapsed + elapsed - - if self.checkElapsed > 0.1 then - if self.parent:IsMouseOver() or (self.alternateFrame and self.alternateFrame:IsMouseOver()) then - self.elapsed = 0 - else - self.elapsed = self.elapsed + self.checkElapsed - - if self.elapsed >= self.delay then - lib:Release(self.parent) - end - end - - self.checkElapsed = 0 - end -end - --- Usage: --- :SetAutoHideDelay(0.25) => hides after 0.25sec outside of the tooltip --- :SetAutoHideDelay(0.25, someFrame) => hides after 0.25sec outside of both the tooltip and someFrame --- :SetAutoHideDelay() => disable auto-hiding (default) -function tipPrototype:SetAutoHideDelay(delay, alternateFrame, releaseHandler) - local timerFrame = self.autoHideTimerFrame - delay = tonumber(delay) or 0 - - if releaseHandler then - if type(releaseHandler) ~= "function" then - error("releaseHandler must be a function", 2) - end - - lib.onReleaseHandlers[self] = releaseHandler - end - - if delay > 0 then - if not timerFrame then - timerFrame = AcquireTimer(self) - timerFrame:SetScript("OnUpdate", AutoHideTimerFrame_OnUpdate) - - self.autoHideTimerFrame = timerFrame - end - - timerFrame.parent = self - timerFrame.checkElapsed = 0 - timerFrame.elapsed = 0 - timerFrame.delay = delay - timerFrame.alternateFrame = alternateFrame - timerFrame:Show() - elseif timerFrame then - self.autoHideTimerFrame = nil - - timerFrame.alternateFrame = nil - timerFrame:SetScript("OnUpdate", nil) - - ReleaseTimer(timerFrame) - end -end - ------------------------------------------------------------------------------- --- "Smart" Anchoring ------------------------------------------------------------------------------- -local function GetTipAnchor(frame) - local x, y = frame:GetCenter() - - if not x or not y then - return "TOPLEFT", "BOTTOMLEFT" - end - - local hhalf = (x > UIParent:GetWidth() * 2 / 3) and "RIGHT" or (x < UIParent:GetWidth() / 3) and "LEFT" or "" - local vhalf = (y > UIParent:GetHeight() / 2) and "TOP" or "BOTTOM" - - return vhalf .. hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP") .. hhalf -end - -function tipPrototype:SmartAnchorTo(frame) - if not frame then - error("Invalid frame provided.", 2) - end - - self:ClearAllPoints() - self:SetClampedToScreen(true) - self:SetPoint(GetTipAnchor(frame)) -end - ------------------------------------------------------------------------------- --- Debug slashcmds ------------------------------------------------------------------------------- --- @debug @ -local print = print -local function PrintStats() - local tipCache = tostring(#tooltipHeap) - local frameCache = tostring(#frameHeap) - local tableCache = tostring(#tableHeap) - local header = false - - print("Tooltips used: " .. usedTooltips .. ", Cached: " .. tipCache .. ", Total: " .. tipCache + usedTooltips) - print("Frames used: " .. usedFrames .. ", Cached: " .. frameCache .. ", Total: " .. frameCache + usedFrames) - print("Tables used: " .. usedTables .. ", Cached: " .. tableCache .. ", Total: " .. tableCache + usedTables) - - for k in pairs(activeTooltips) do - if not header then - print("Active tooltips:") - header = true - end - print("- " .. k) - end -end - -SLASH_LibQTip1 = "/qtip" -_G.SlashCmdList["LibQTip"] = PrintStats ---@end-debug@]==] diff --git a/Titan/libs/Ace/LibQTip-1.0/LibQTip-1.0.toc b/Titan/libs/Ace/LibQTip-1.0/LibQTip-1.0.toc deleted file mode 100644 index d7d75e8..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/LibQTip-1.0.toc +++ /dev/null @@ -1,15 +0,0 @@ -## Interface: 100007 -## Title: Lib: QTip-1.0 -## Notes: Library providing multi-column tooltips. -## Author: Torhal, Adirelle, Elkano, Tristanian -## Version: 10.0.7.1 -## LoadOnDemand: 1 -## X-Credits: Kaelten (input on initial design) -## X-Category: Library, Tooltip -## X-Curse-Project-ID: 15487 -## X-Date: 2023-03-29T21:01:29Z -## X-License: Ace3 BSD-like license -## X-Website: http://www.wowace.com/addons/libqtip-1-0/ - -LibStub\LibStub.lua -lib.xml diff --git a/Titan/libs/Ace/LibQTip-1.0/LibStub/LibStub.lua b/Titan/libs/Ace/LibQTip-1.0/LibStub/LibStub.lua deleted file mode 100644 index 7e7b76d..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/LibStub/LibStub.lua +++ /dev/null @@ -1,51 +0,0 @@ --- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $ --- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/addons/libstub/ for more info --- LibStub is hereby placed in the Public Domain --- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke -local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! -local LibStub = _G[LIBSTUB_MAJOR] - --- Check to see is this version of the stub is obsolete -if not LibStub or LibStub.minor < LIBSTUB_MINOR then - LibStub = LibStub or {libs = {}, minors = {} } - _G[LIBSTUB_MAJOR] = LibStub - LibStub.minor = LIBSTUB_MINOR - - -- LibStub:NewLibrary(major, minor) - -- major (string) - the major version of the library - -- minor (string or number ) - the minor version of the library - -- - -- returns nil if a newer or same version of the lib is already present - -- returns empty library object or old library object if upgrade is needed - function LibStub:NewLibrary(major, minor) - assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") - minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") - - local oldminor = self.minors[major] - if oldminor and oldminor >= minor then return nil end - self.minors[major], self.libs[major] = minor, self.libs[major] or {} - return self.libs[major], oldminor - end - - -- LibStub:GetLibrary(major, [silent]) - -- major (string) - the major version of the library - -- silent (boolean) - if true, library is optional, silently return nil if its not found - -- - -- throws an error if the library can not be found (except silent is set) - -- returns the library object if found - function LibStub:GetLibrary(major, silent) - if not self.libs[major] and not silent then - error(("Cannot find a library instance of %q."):format(tostring(major)), 2) - end - return self.libs[major], self.minors[major] - end - - -- LibStub:IterateLibraries() - -- - -- Returns an iterator for the currently registered libraries - function LibStub:IterateLibraries() - return pairs(self.libs) - end - - setmetatable(LibStub, { __call = LibStub.GetLibrary }) -end diff --git a/Titan/libs/Ace/LibQTip-1.0/README.md b/Titan/libs/Ace/LibQTip-1.0/README.md deleted file mode 100644 index b61c509..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# LibQTip-1.0 -LibQTip is designed replace GameTooltip - but with added functionality, such as multiple columns - from a minimalist design perspective. - -## Features -- Ability to display and handle multiple tooltips at the same time, -- Unlimited number of columns and lines, -- Column default and per cell justification, -- Tooltip default and per cell font setting, -- Colspans, -- Possibility to add custom cells, -- Optional scrollbar, -- Optional scripts for lines, columns, or cells, -- Optional automatic hiding, -- Frames and tables recycling to reduce resource footprint. - -## Caveats -Look [here](https://www.wowace.com/projects/libqtip-1-0/pages/getting-started) for information on embedding the latest beta/release. - -**In order to achieve effective frame recycling, tooltips must be released.** - -Holding a tooltip leads to the creation of a full set of frames for every AddOn which does not follow this practice. Moreover, releasing a tooltip has a very little overhead compared to its benefits. - -## Known issues -Alignment may be altered when using :SetScale after filling the tooltip. - -## Documentation -- [Getting Started Guide](https://www.wowace.com/projects/libqtip-1-0/pages/getting-started) -- [How to Add Custom Cells](https://www.wowace.com/projects/libqtip-1-0/pages/how-to-add-custom-cells) -- [API Reference](https://www.wowace.com/projects/libqtip-1-0/pages/api-reference) -- [Standard CellProvider API](https://www.wowace.com/projects/libqtip-1-0/pages/standard-cell-provider-api) diff --git a/Titan/libs/Ace/LibQTip-1.0/lib.xml b/Titan/libs/Ace/LibQTip-1.0/lib.xml deleted file mode 100644 index f212246..0000000 --- a/Titan/libs/Ace/LibQTip-1.0/lib.xml +++ /dev/null @@ -1,4 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ -..\FrameXML\UI.xsd"> - <Script file="LibQTip-1.0.lua"/> -</Ui> \ No newline at end of file diff --git a/Titan/libs/Ace/changelog.txt b/Titan/libs/Ace/changelog.txt index db97361..0aff887 100644 --- a/Titan/libs/Ace/changelog.txt +++ b/Titan/libs/Ace/changelog.txt @@ -1,3 +1,10 @@ +Ace3 Release - Revision r1390 (February 3rd, 2026) +-------------------------------------------------- +- AceConfigDialog-3.0: The original category ID is now preserved in AddToBlizOptions in 12.0, making it mandatory for addons to store the second return value and forward it to Settings.OpenToCategory +- AceConfig-3.0: Widgets can now specify a relative size with width="relative" and relWidth="0.5" +- AceGUI-3.0: Keybinding: Add basic gamepad support +- AceGUI-3.0: TreeGroup: Consistently provide an alpha value for GameTooltip:SetText + Ace3 Release - Revision r1377 (October 28th, 2025) -------------------------------------------------- - AceComm-3.0: Updated ChatThrottleLib for WoW 12.0 diff --git a/Titan/libs/LibQTip-1.0/CHANGELOG.md b/Titan/libs/LibQTip-1.0/CHANGELOG.md new file mode 100644 index 0000000..442bb65 --- /dev/null +++ b/Titan/libs/LibQTip-1.0/CHANGELOG.md @@ -0,0 +1,10 @@ +# Lib: QTip-1.0 + +## [10.0.7.1](https://github.com/Torhal/LibQTip-1.0/tree/10.0.7.1) (2023-03-29) +[Full Changelog](https://github.com/Torhal/LibQTip-1.0/compare/9.0.1.2...10.0.7.1) [Previous Releases](https://github.com/Torhal/LibQTip-1.0/releases) + +- Create release.yml + Add release configuration for the BigWigs Packager. +- Update ToC Interface and add X-Curse-Project-ID to support the BigWigs Packager. +- Create README.md +- update for WoW 9.1.5's new TooltipBackdropTemplate diff --git a/Titan/libs/LibQTip-1.0/LICENSE.txt b/Titan/libs/LibQTip-1.0/LICENSE.txt new file mode 100644 index 0000000..9bc7b5c --- /dev/null +++ b/Titan/libs/LibQTip-1.0/LICENSE.txt @@ -0,0 +1,29 @@ +Copyright (c) 2008, LibQTip Development Team + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Redistribution of a stand alone version is strictly prohibited without + prior written authorization from the Lead of the LibQTip Development Team. + * Neither the name of the LibQTip Development Team nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Titan/libs/LibQTip-1.0/LibQTip-1.0.lua b/Titan/libs/LibQTip-1.0/LibQTip-1.0.lua new file mode 100644 index 0000000..bb38c75 --- /dev/null +++ b/Titan/libs/LibQTip-1.0/LibQTip-1.0.lua @@ -0,0 +1,1565 @@ +local MAJOR = "LibQTip-1.0" +local MINOR = 49 -- Should be manually increased +local LibStub = _G.LibStub + +assert(LibStub, MAJOR .. " requires LibStub") + +local lib, oldMinor = LibStub:NewLibrary(MAJOR, MINOR) + +if not lib then + return +end -- No upgrade needed + +------------------------------------------------------------------------------ +-- Upvalued globals +------------------------------------------------------------------------------ +local table = _G.table +local tinsert = table.insert +local tremove = table.remove +local wipe = table.wipe + +local error = error +local math = math +local min, max = math.min, math.max +local next = next +local pairs, ipairs = pairs, ipairs +local select = select +local setmetatable = setmetatable +local tonumber, tostring = tonumber, tostring +local type = type + +local CreateFrame = _G.CreateFrame +local GameTooltip = _G.GameTooltip +local UIParent = _G.UIParent + +local geterrorhandler = _G.geterrorhandler + +------------------------------------------------------------------------------ +-- Tables and locals +------------------------------------------------------------------------------ +lib.frameMetatable = lib.frameMetatable or {__index = CreateFrame("Frame")} + +lib.tipPrototype = lib.tipPrototype or setmetatable({}, lib.frameMetatable) +lib.tipMetatable = lib.tipMetatable or {__index = lib.tipPrototype} + +lib.providerPrototype = lib.providerPrototype or {} +lib.providerMetatable = lib.providerMetatable or {__index = lib.providerPrototype} + +lib.cellPrototype = lib.cellPrototype or setmetatable({}, lib.frameMetatable) +lib.cellMetatable = lib.cellMetatable or {__index = lib.cellPrototype} + +lib.activeTooltips = lib.activeTooltips or {} + +lib.tooltipHeap = lib.tooltipHeap or {} +lib.frameHeap = lib.frameHeap or {} +lib.timerHeap = lib.timerHeap or {} +lib.tableHeap = lib.tableHeap or {} + +lib.onReleaseHandlers = lib.onReleaseHandlers or {} + +local tipPrototype = lib.tipPrototype +local tipMetatable = lib.tipMetatable + +local providerPrototype = lib.providerPrototype +local providerMetatable = lib.providerMetatable + +local cellPrototype = lib.cellPrototype +local cellMetatable = lib.cellMetatable + +local activeTooltips = lib.activeTooltips + +local highlightFrame = CreateFrame("Frame", nil, UIParent) +highlightFrame:SetFrameStrata("TOOLTIP") +highlightFrame:Hide() + +local DEFAULT_HIGHLIGHT_TEXTURE_PATH = [[Interface\QuestFrame\UI-QuestTitleHighlight]] + +local highlightTexture = highlightFrame:CreateTexture(nil, "OVERLAY") +highlightTexture:SetTexture(DEFAULT_HIGHLIGHT_TEXTURE_PATH) +highlightTexture:SetBlendMode("ADD") +highlightTexture:SetAllPoints(highlightFrame) + +------------------------------------------------------------------------------ +-- Private methods for Caches and Tooltip +------------------------------------------------------------------------------ +local AcquireTooltip, ReleaseTooltip +local AcquireCell, ReleaseCell +local AcquireTable, ReleaseTable + +local InitializeTooltip, SetTooltipSize, ResetTooltipSize, FixCellSizes +local ClearTooltipScripts +local SetFrameScript, ClearFrameScripts + +------------------------------------------------------------------------------ +-- Cache debugging. +------------------------------------------------------------------------------ +-- @debug @ +local usedTables, usedFrames, usedTooltips = 0, 0, 0 +--@end-debug@]==] + +------------------------------------------------------------------------------ +-- Internal constants to tweak the layout +------------------------------------------------------------------------------ +local TOOLTIP_PADDING = 10 +local CELL_MARGIN_H = 6 +local CELL_MARGIN_V = 3 + +------------------------------------------------------------------------------ +-- Public library API +------------------------------------------------------------------------------ +--- Create or retrieve the tooltip with the given key. +-- If additional arguments are passed, they are passed to :SetColumnLayout for the acquired tooltip. +-- @name LibQTip:Acquire(key[, numColumns, column1Justification, column2justification, ...]) +-- @param key string or table - the tooltip key. Any value that can be used as a table key is accepted though you should try to provide unique keys to avoid conflicts. +-- Numbers and booleans should be avoided and strings should be carefully chosen to avoid namespace clashes - no "MyTooltip" - you have been warned! +-- @return tooltip Frame object - the acquired tooltip. +-- @usage Acquire a tooltip with at least 5 columns, justification : left, center, left, left, left +-- <pre>local tip = LibStub('LibQTip-1.0'):Acquire('MyFooBarTooltip', 5, "LEFT", "CENTER")</pre> +function lib:Acquire(key, ...) + if key == nil then + error("attempt to use a nil key", 2) + end + + local tooltip = activeTooltips[key] + + if not tooltip then + tooltip = AcquireTooltip() + InitializeTooltip(tooltip, key) + activeTooltips[key] = tooltip + end + + if select("#", ...) > 0 then + -- Here we catch any error to properly report it for the calling code + local ok, msg = pcall(tooltip.SetColumnLayout, tooltip, ...) + + if not ok then + error(msg, 2) + end + end + + return tooltip +end + +function lib:Release(tooltip) + local key = tooltip and tooltip.key + + if not key or activeTooltips[key] ~= tooltip then + return + end + + ReleaseTooltip(tooltip) + activeTooltips[key] = nil +end + +function lib:IsAcquired(key) + if key == nil then + error("attempt to use a nil key", 2) + end + + return not (not activeTooltips[key]) +end + +function lib:IterateTooltips() + return pairs(activeTooltips) +end + +------------------------------------------------------------------------------ +-- Frame cache (for lines and columns) +------------------------------------------------------------------------------ +local frameHeap = lib.frameHeap + +local function AcquireFrame(parent) + local frame = tremove(frameHeap) or CreateFrame("Frame", nil, nil, BackdropTemplateMixin and "BackdropTemplate") + frame:SetParent(parent) + --[==[@debug@ + usedFrames = usedFrames + 1 + --@end-debug@]==] + return frame +end + +local function ReleaseFrame(frame) + frame:Hide() + frame:SetParent(nil) + frame:ClearAllPoints() + frame:SetBackdrop(nil) + + ClearFrameScripts(frame) + + tinsert(frameHeap, frame) + --[==[@debug@ + usedFrames = usedFrames - 1 + --@end-debug@]==] +end + +------------------------------------------------------------------------------ +-- Timer cache +------------------------------------------------------------------------------ +local timerHeap = lib.timerHeap + +local function AcquireTimer(parent) + local frame = tremove(timerHeap) or CreateFrame("Frame") + frame:SetParent(parent) + return frame +end + +local function ReleaseTimer(frame) + frame:Hide() + frame:SetParent(nil) + + ClearFrameScripts(frame) + + tinsert(timerHeap, frame) +end + +------------------------------------------------------------------------------ +-- Dirty layout handler +------------------------------------------------------------------------------ +lib.layoutCleaner = lib.layoutCleaner or CreateFrame("Frame") + +local layoutCleaner = lib.layoutCleaner +layoutCleaner.registry = layoutCleaner.registry or {} + +function layoutCleaner:RegisterForCleanup(tooltip) + self.registry[tooltip] = true + self:Show() +end + +function layoutCleaner:CleanupLayouts() + self:Hide() + + for tooltip in pairs(self.registry) do + FixCellSizes(tooltip) + end + + wipe(self.registry) +end + +layoutCleaner:SetScript("OnUpdate", layoutCleaner.CleanupLayouts) + +------------------------------------------------------------------------------ +-- CellProvider and Cell +------------------------------------------------------------------------------ +function providerPrototype:AcquireCell() + local cell = tremove(self.heap) + + if not cell then + cell = CreateFrame("Frame", nil, UIParent, BackdropTemplateMixin and "BackdropTemplate") + setmetatable(cell, self.cellMetatable) + + if type(cell.InitializeCell) == "function" then + cell:InitializeCell() + end + end + + self.cells[cell] = true + + return cell +end + +function providerPrototype:ReleaseCell(cell) + if not self.cells[cell] then + return + end + + if type(cell.ReleaseCell) == "function" then + cell:ReleaseCell() + end + + self.cells[cell] = nil + tinsert(self.heap, cell) +end + +function providerPrototype:GetCellPrototype() + return self.cellPrototype, self.cellMetatable +end + +function providerPrototype:IterateCells() + return pairs(self.cells) +end + +function lib:CreateCellProvider(baseProvider) + local cellBaseMetatable, cellBasePrototype + + if baseProvider and baseProvider.GetCellPrototype then + cellBasePrototype, cellBaseMetatable = baseProvider:GetCellPrototype() + else + cellBaseMetatable = cellMetatable + end + + local newCellPrototype = setmetatable({}, cellBaseMetatable) + local newCellProvider = setmetatable({}, providerMetatable) + + newCellProvider.heap = {} + newCellProvider.cells = {} + newCellProvider.cellPrototype = newCellPrototype + newCellProvider.cellMetatable = {__index = newCellPrototype} + + return newCellProvider, newCellPrototype, cellBasePrototype +end + +------------------------------------------------------------------------------ +-- Basic label provider +------------------------------------------------------------------------------ +if not lib.LabelProvider then + lib.LabelProvider, lib.LabelPrototype = lib:CreateCellProvider() +end + +local labelProvider = lib.LabelProvider +local labelPrototype = lib.LabelPrototype + +function labelPrototype:InitializeCell() + self.fontString = self:CreateFontString() + self.fontString:SetFontObject(_G.GameTooltipText) +end + +function labelPrototype:SetupCell(tooltip, value, justification, font, leftPadding, rightPadding, maxWidth, minWidth, ...) + local fontString = self.fontString + local line = tooltip.lines[self._line] + + -- detatch fs from cell for size calculations + fontString:ClearAllPoints() + fontString:SetFontObject(font or (line.is_header and tooltip:GetHeaderFont() or tooltip:GetFont())) + fontString:SetJustifyH(justification) + fontString:SetText(tostring(value)) + + leftPadding = leftPadding or 0 + rightPadding = rightPadding or 0 + + local width = fontString:GetStringWidth() + leftPadding + rightPadding + + if maxWidth and minWidth and (maxWidth < minWidth) then + error("maximum width cannot be lower than minimum width: " .. tostring(maxWidth) .. " < " .. tostring(minWidth), 2) + end + + if maxWidth and (maxWidth < (leftPadding + rightPadding)) then + error("maximum width cannot be lower than the sum of paddings: " .. tostring(maxWidth) .. " < " .. tostring(leftPadding) .. " + " .. tostring(rightPadding), 2) + end + + if minWidth and width < minWidth then + width = minWidth + end + + if maxWidth and maxWidth < width then + width = maxWidth + end + + fontString:SetWidth(width - (leftPadding + rightPadding)) + -- Use GetHeight() instead of GetStringHeight() so lines which are longer than width will wrap. + local height = fontString:GetHeight() + + -- reanchor fs to cell + fontString:SetWidth(0) + fontString:SetPoint("TOPLEFT", self, "TOPLEFT", leftPadding, 0) + fontString:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -rightPadding, 0) + --~ fs:SetPoint("TOPRIGHT", self, "TOPRIGHT", -r_pad, 0) + + self._paddingL = leftPadding + self._paddingR = rightPadding + + return width, height +end + +function labelPrototype:getContentHeight() + local fontString = self.fontString + fontString:SetWidth(self:GetWidth() - (self._paddingL + self._paddingR)) + + local height = self.fontString:GetHeight() + fontString:SetWidth(0) + + return height +end + +function labelPrototype:GetPosition() + return self._line, self._column +end + +------------------------------------------------------------------------------ +-- Tooltip cache +------------------------------------------------------------------------------ +local tooltipHeap = lib.tooltipHeap + +-- Returns a tooltip +function AcquireTooltip() + local tooltip = tremove(tooltipHeap) + + if not tooltip then + local template = (TooltipBackdropTemplateMixin and "TooltipBackdropTemplate") or (BackdropTemplateMixin and "BackdropTemplate") + tooltip = CreateFrame("Frame", nil, UIParent, template) + + local scrollFrame = CreateFrame("ScrollFrame", nil, tooltip) + scrollFrame:SetPoint("TOP", tooltip, "TOP", 0, -TOOLTIP_PADDING) + scrollFrame:SetPoint("BOTTOM", tooltip, "BOTTOM", 0, TOOLTIP_PADDING) + scrollFrame:SetPoint("LEFT", tooltip, "LEFT", TOOLTIP_PADDING, 0) + scrollFrame:SetPoint("RIGHT", tooltip, "RIGHT", -TOOLTIP_PADDING, 0) + tooltip.scrollFrame = scrollFrame + + local scrollChild = CreateFrame("Frame", nil, tooltip.scrollFrame) + scrollFrame:SetScrollChild(scrollChild) + tooltip.scrollChild = scrollChild + + setmetatable(tooltip, tipMetatable) + end + + --[==[@debug@ + usedTooltips = usedTooltips + 1 + --@end-debug@]==] + return tooltip +end + +-- Cleans the tooltip and stores it in the cache +function ReleaseTooltip(tooltip) + if tooltip.releasing then + return + end + + tooltip.releasing = true + tooltip:Hide() + + local releaseHandler = lib.onReleaseHandlers[tooltip] + + if releaseHandler then + lib.onReleaseHandlers[tooltip] = nil + + local success, errorMessage = pcall(releaseHandler, tooltip) + + if not success then + geterrorhandler()(errorMessage) + end + elseif tooltip.OnRelease then + local success, errorMessage = pcall(tooltip.OnRelease, tooltip) + if not success then + geterrorhandler()(errorMessage) + end + + tooltip.OnRelease = nil + end + + tooltip.releasing = nil + tooltip.key = nil + tooltip.step = nil + + ClearTooltipScripts(tooltip) + + tooltip:SetAutoHideDelay(nil) + tooltip:ClearAllPoints() + tooltip:Clear() + + if tooltip.slider then + tooltip.slider:SetValue(0) + tooltip.slider:Hide() + tooltip.scrollFrame:SetPoint("RIGHT", tooltip, "RIGHT", -TOOLTIP_PADDING, 0) + tooltip:EnableMouseWheel(false) + end + + for i, column in ipairs(tooltip.columns) do + tooltip.columns[i] = ReleaseFrame(column) + end + + tooltip.columns = ReleaseTable(tooltip.columns) + tooltip.lines = ReleaseTable(tooltip.lines) + tooltip.colspans = ReleaseTable(tooltip.colspans) + + layoutCleaner.registry[tooltip] = nil + + if TooltipBackdropTemplateMixin and not tooltip.NineSlice then + -- don't recycle outdated tooltips into heap + tooltip = nil + end + + if tooltip then + tinsert(tooltipHeap, tooltip) + end + + highlightTexture:SetTexture(DEFAULT_HIGHLIGHT_TEXTURE_PATH) + highlightTexture:SetTexCoord(0, 1, 0, 1) + + --[==[@debug@ + usedTooltips = usedTooltips - 1 + --@end-debug@]==] +end + +------------------------------------------------------------------------------ +-- Cell 'cache' (just a wrapper to the provider's cache) +------------------------------------------------------------------------------ +-- Returns a cell for the given tooltip from the given provider +function AcquireCell(tooltip, provider) + local cell = provider:AcquireCell(tooltip) + + cell:SetParent(tooltip.scrollChild) + cell:SetFrameLevel(tooltip.scrollChild:GetFrameLevel() + 3) + cell._provider = provider + + return cell +end + +-- Cleans the cell hands it to its provider for storing +function ReleaseCell(cell) + if cell.fontString and cell.r then + cell.fontString:SetTextColor(cell.r, cell.g, cell.b, cell.a) + end + + cell._font = nil + cell._justification = nil + cell._colSpan = nil + cell._line = nil + cell._column = nil + + cell:Hide() + cell:ClearAllPoints() + cell:SetParent(nil) + cell:SetBackdrop(nil) + + ClearFrameScripts(cell) + + cell._provider:ReleaseCell(cell) + cell._provider = nil +end + +------------------------------------------------------------------------------ +-- Table cache +------------------------------------------------------------------------------ +local tableHeap = lib.tableHeap + +-- Returns a table +function AcquireTable() + local tbl = tremove(tableHeap) or {} + --[==[@debug@ + usedTables = usedTables + 1 + --@end-debug@]==] + return tbl +end + +-- Cleans the table and stores it in the cache +function ReleaseTable(tableInstance) + wipe(tableInstance) + tinsert(tableHeap, tableInstance) + --[==[@debug@ + usedTables = usedTables - 1 + --@end-debug@]==] +end + +------------------------------------------------------------------------------ +-- Tooltip prototype +------------------------------------------------------------------------------ +function InitializeTooltip(tooltip, key) + ---------------------------------------------------------------------- + -- (Re)set frame settings + ---------------------------------------------------------------------- + if TooltipBackdropTemplateMixin then + tooltip.layoutType = GameTooltip.layoutType + NineSlicePanelMixin.OnLoad(tooltip.NineSlice) + if GameTooltip.layoutType then + tooltip.NineSlice:SetCenterColor(GameTooltip.NineSlice:GetCenterColor()) + tooltip.NineSlice:SetBorderColor(GameTooltip.NineSlice:GetBorderColor()) + end + else + local backdrop = GameTooltip:GetBackdrop() + + tooltip:SetBackdrop(backdrop) + + if backdrop then + tooltip:SetBackdropColor(GameTooltip:GetBackdropColor()) + tooltip:SetBackdropBorderColor(GameTooltip:GetBackdropBorderColor()) + end + end + + tooltip:SetScale(GameTooltip:GetScale()) + tooltip:SetAlpha(1) + tooltip:SetFrameStrata("TOOLTIP") + tooltip:SetClampedToScreen(false) + + ---------------------------------------------------------------------- + -- Internal data. Since it's possible to Acquire twice without calling + -- release, check for pre-existence. + ---------------------------------------------------------------------- + tooltip.key = key + tooltip.columns = tooltip.columns or AcquireTable() + tooltip.lines = tooltip.lines or AcquireTable() + tooltip.colspans = tooltip.colspans or AcquireTable() + tooltip.regularFont = _G.GameTooltipText + tooltip.headerFont = _G.GameTooltipHeaderText + tooltip.labelProvider = labelProvider + tooltip.cell_margin_h = tooltip.cell_margin_h or CELL_MARGIN_H + tooltip.cell_margin_v = tooltip.cell_margin_v or CELL_MARGIN_V + + ---------------------------------------------------------------------- + -- Finishing procedures + ---------------------------------------------------------------------- + tooltip:SetAutoHideDelay(nil) + tooltip:Hide() + ResetTooltipSize(tooltip) +end + +function tipPrototype:SetDefaultProvider(myProvider) + if not myProvider then + return + end + + self.labelProvider = myProvider +end + +function tipPrototype:GetDefaultProvider() + return self.labelProvider +end + +local function checkJustification(justification, level, silent) + if justification ~= "LEFT" and justification ~= "CENTER" and justification ~= "RIGHT" then + if silent then + return false + end + error("invalid justification, must one of LEFT, CENTER or RIGHT, not: " .. tostring(justification), level + 1) + end + + return true +end + +function tipPrototype:SetColumnLayout(numColumns, ...) + if type(numColumns) ~= "number" or numColumns < 1 then + error("number of columns must be a positive number, not: " .. tostring(numColumns), 2) + end + + for i = 1, numColumns do + local justification = select(i, ...) or "LEFT" + + checkJustification(justification, 2) + + if self.columns[i] then + self.columns[i].justification = justification + else + self:AddColumn(justification) + end + end +end + +function tipPrototype:AddColumn(justification) + justification = justification or "LEFT" + checkJustification(justification, 2) + + local colNum = #self.columns + 1 + local column = self.columns[colNum] or AcquireFrame(self.scrollChild) + + column:SetFrameLevel(self.scrollChild:GetFrameLevel() + 1) + column.justification = justification + column.width = 0 + column:SetWidth(1) + column:SetPoint("TOP", self.scrollChild) + column:SetPoint("BOTTOM", self.scrollChild) + + if colNum > 1 then + local h_margin = self.cell_margin_h or CELL_MARGIN_H + + column:SetPoint("LEFT", self.columns[colNum - 1], "RIGHT", h_margin, 0) + SetTooltipSize(self, self.width + h_margin, self.height) + else + column:SetPoint("LEFT", self.scrollChild) + end + + column:Show() + self.columns[colNum] = column + + return colNum +end + +------------------------------------------------------------------------------ +-- Convenient methods +------------------------------------------------------------------------------ +function tipPrototype:Release() + lib:Release(self) +end + +function tipPrototype:IsAcquiredBy(key) + return key ~= nil and self.key == key +end + +------------------------------------------------------------------------------ +-- Script hooks +------------------------------------------------------------------------------ +local RawSetScript = lib.frameMetatable.__index.SetScript + +function ClearTooltipScripts(tooltip) + if tooltip.scripts then + for scriptType in pairs(tooltip.scripts) do + RawSetScript(tooltip, scriptType, nil) + end + + tooltip.scripts = ReleaseTable(tooltip.scripts) + end +end + +function tipPrototype:SetScript(scriptType, handler) + RawSetScript(self, scriptType, handler) + + if handler then + if not self.scripts then + self.scripts = AcquireTable() + end + + self.scripts[scriptType] = true + elseif self.scripts then + self.scripts[scriptType] = nil + end +end + +-- That might break some addons ; those addons were breaking other +-- addons' tooltip though. +function tipPrototype:HookScript() + geterrorhandler()(":HookScript is not allowed on LibQTip tooltips") +end + +------------------------------------------------------------------------------ +-- Scrollbar data and functions +------------------------------------------------------------------------------ +local BACKDROP_SLIDER_8_8 = BACKDROP_SLIDER_8_8 or { + bgFile = "Interface\\Buttons\\UI-SliderBar-Background", + edgeFile = "Interface\\Buttons\\UI-SliderBar-Border", + tile = true, + tileEdge = true, + tileSize = 8, + edgeSize = 8, + insets = { left = 3, right = 3, top = 6, bottom = 6 }, +}; + +local function slider_OnValueChanged(self) + self.scrollFrame:SetVerticalScroll(self:GetValue()) +end + +local function tooltip_OnMouseWheel(self, delta) + local slider = self.slider + local currentValue = slider:GetValue() + local minValue, maxValue = slider:GetMinMaxValues() + local stepValue = self.step or 10 + + if delta < 0 and currentValue < maxValue then + slider:SetValue(min(maxValue, currentValue + stepValue)) + elseif delta > 0 and currentValue > minValue then + slider:SetValue(max(minValue, currentValue - stepValue)) + end +end + +-- Set the step size for the scroll bar +function tipPrototype:SetScrollStep(step) + self.step = step +end + +-- will resize the tooltip to fit the screen and show a scrollbar if needed +function tipPrototype:UpdateScrolling(maxheight) + self:SetClampedToScreen(false) + + -- all data is in the tooltip; fix colspan width and prevent the layout cleaner from messing up the tooltip later + FixCellSizes(self) + layoutCleaner.registry[self] = nil + + local scale = self:GetScale() + local topside = self:GetTop() + local bottomside = self:GetBottom() + local screensize = UIParent:GetHeight() / scale + local tipsize = (topside - bottomside) + + -- if the tooltip would be too high, limit its height and show the slider + if bottomside < 0 or topside > screensize or (maxheight and tipsize > maxheight) then + local shrink = (bottomside < 0 and (5 - bottomside) or 0) + (topside > screensize and (topside - screensize + 5) or 0) + + if maxheight and tipsize - shrink > maxheight then + shrink = tipsize - maxheight + end + + self:SetHeight(2 * TOOLTIP_PADDING + self.height - shrink) + self:SetWidth(2 * TOOLTIP_PADDING + self.width + 20) + self.scrollFrame:SetPoint("RIGHT", self, "RIGHT", -(TOOLTIP_PADDING + 20), 0) + + if not self.slider then + local slider = CreateFrame("Slider", nil, self, BackdropTemplateMixin and "BackdropTemplate") + slider.scrollFrame = self.scrollFrame + + slider:SetOrientation("VERTICAL") + slider:SetPoint("TOPRIGHT", self, "TOPRIGHT", -TOOLTIP_PADDING, -TOOLTIP_PADDING) + slider:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -TOOLTIP_PADDING, TOOLTIP_PADDING) + slider:SetBackdrop(BACKDROP_SLIDER_8_8) + slider:SetThumbTexture([[Interface\Buttons\UI-SliderBar-Button-Vertical]]) + slider:SetMinMaxValues(0, 1) + slider:SetValueStep(1) + slider:SetWidth(12) + slider:SetScript("OnValueChanged", slider_OnValueChanged) + slider:SetValue(0) + + self.slider = slider + end + + self.slider:SetMinMaxValues(0, shrink) + self.slider:Show() + + self:EnableMouseWheel(true) + self:SetScript("OnMouseWheel", tooltip_OnMouseWheel) + else + self:SetHeight(2 * TOOLTIP_PADDING + self.height) + self:SetWidth(2 * TOOLTIP_PADDING + self.width) + + self.scrollFrame:SetPoint("RIGHT", self, "RIGHT", -TOOLTIP_PADDING, 0) + + if self.slider then + self.slider:SetValue(0) + self.slider:Hide() + + self:EnableMouseWheel(false) + self:SetScript("OnMouseWheel", nil) + end + end +end + +------------------------------------------------------------------------------ +-- Tooltip methods for changing its contents. +------------------------------------------------------------------------------ +function tipPrototype:Clear() + for i, line in ipairs(self.lines) do + for _, cell in pairs(line.cells) do + if cell then + ReleaseCell(cell) + end + end + + ReleaseTable(line.cells) + + line.cells = nil + line.is_header = nil + + ReleaseFrame(line) + + self.lines[i] = nil + end + + for _, column in ipairs(self.columns) do + column.width = 0 + column:SetWidth(1) + end + + wipe(self.colspans) + + self.cell_margin_h = nil + self.cell_margin_v = nil + + ResetTooltipSize(self) +end + +function tipPrototype:SetCellMarginH(size) + if #self.lines > 0 then + error("Unable to set horizontal margin while the tooltip has lines.", 2) + end + + if not size or type(size) ~= "number" or size < 0 then + error("Margin size must be a positive number or zero.", 2) + end + + self.cell_margin_h = size +end + +function tipPrototype:SetCellMarginV(size) + if #self.lines > 0 then + error("Unable to set vertical margin while the tooltip has lines.", 2) + end + + if not size or type(size) ~= "number" or size < 0 then + error("Margin size must be a positive number or zero.", 2) + end + + self.cell_margin_v = size +end + +function SetTooltipSize(tooltip, width, height) + tooltip.height = height + tooltip.width = width + + tooltip:SetHeight(2 * TOOLTIP_PADDING + height) + tooltip:SetWidth(2 * TOOLTIP_PADDING + width) + + tooltip.scrollChild:SetHeight(height) + tooltip.scrollChild:SetWidth(width) +end + +-- Add 2 pixels to height so dangling letters (g, y, p, j, etc) are not clipped. +function ResetTooltipSize(tooltip) + local h_margin = tooltip.cell_margin_h or CELL_MARGIN_H + + SetTooltipSize(tooltip, max(0, (h_margin * (#tooltip.columns - 1)) + (h_margin / 2)), 2) +end + +local function EnlargeColumn(tooltip, column, width) + if width > column.width then + SetTooltipSize(tooltip, tooltip.width + width - column.width, tooltip.height) + + column.width = width + column:SetWidth(width) + end +end + +local function ResizeLine(tooltip, line, height) + SetTooltipSize(tooltip, tooltip.width, tooltip.height + height - line.height) + + line.height = height + line:SetHeight(height) +end + +function FixCellSizes(tooltip) + local columns = tooltip.columns + local colspans = tooltip.colspans + local lines = tooltip.lines + local h_margin = tooltip.cell_margin_h or CELL_MARGIN_H + + -- resize columns to make room for the colspans + while next(colspans) do + local maxNeedCols + local maxNeedWidthPerCol = 0 + + -- calculate the colspan with the highest additional width need per column + for colRange, width in pairs(colspans) do + local left, right = colRange:match("^(%d+)%-(%d+)$") + + left, right = tonumber(left), tonumber(right) + + for col = left, right - 1 do + width = width - columns[col].width - h_margin + end + + width = width - columns[right].width + + if width <= 0 then + colspans[colRange] = nil + else + width = width / (right - left + 1) + + if width > maxNeedWidthPerCol then + maxNeedCols = colRange + maxNeedWidthPerCol = width + end + end + end + + -- resize all columns for that colspan + if maxNeedCols then + local left, right = maxNeedCols:match("^(%d+)%-(%d+)$") + + for col = left, right do + EnlargeColumn(tooltip, columns[col], columns[col].width + maxNeedWidthPerCol) + end + + colspans[maxNeedCols] = nil + end + end + + --now that the cell width is set, recalculate the rows' height + for _, line in ipairs(lines) do + if #(line.cells) > 0 then + local lineheight = 0 + + for _, cell in pairs(line.cells) do + if cell then + lineheight = max(lineheight, cell:getContentHeight()) + end + end + + if lineheight > 0 then + ResizeLine(tooltip, line, lineheight) + end + end + end +end + +local function _SetCell(tooltip, lineNum, colNum, value, font, justification, colSpan, provider, ...) + local line = tooltip.lines[lineNum] + local cells = line.cells + + -- Unset: be quick + if value == nil then + local cell = cells[colNum] + + if cell then + for i = colNum, colNum + cell._colSpan - 1 do + cells[i] = nil + end + + ReleaseCell(cell) + end + + return lineNum, colNum + end + + font = font or (line.is_header and tooltip.headerFont or tooltip.regularFont) + + -- Check previous cell + local cell + local prevCell = cells[colNum] + + if prevCell then + -- There is a cell here + justification = justification or prevCell._justification + colSpan = colSpan or prevCell._colSpan + + -- Clear the currently marked colspan + for i = colNum + 1, colNum + prevCell._colSpan - 1 do + cells[i] = nil + end + + if provider == nil or prevCell._provider == provider then + -- Reuse existing cell + cell = prevCell + provider = cell._provider + else + -- A new cell is required + cells[colNum] = ReleaseCell(prevCell) + end + elseif prevCell == nil then + -- Creating a new cell, using meaningful defaults. + provider = provider or tooltip.labelProvider + justification = justification or tooltip.columns[colNum].justification or "LEFT" + colSpan = colSpan or 1 + else + error("overlapping cells at column " .. colNum, 3) + end + + local tooltipWidth = #tooltip.columns + local rightColNum + + if colSpan > 0 then + rightColNum = colNum + colSpan - 1 + + if rightColNum > tooltipWidth then + error("ColSpan too big, cell extends beyond right-most column", 3) + end + else + -- Zero or negative: count back from right-most columns + rightColNum = max(colNum, tooltipWidth + colSpan) + -- Update colspan to its effective value + colSpan = 1 + rightColNum - colNum + end + + -- Cleanup colspans + for i = colNum + 1, rightColNum do + local columnCell = cells[i] + + if columnCell then + ReleaseCell(columnCell) + elseif columnCell == false then + error("overlapping cells at column " .. i, 3) + end + + cells[i] = false + end + + -- Create the cell + if not cell then + cell = AcquireCell(tooltip, provider) + cells[colNum] = cell + end + + -- Anchor the cell + cell:SetPoint("LEFT", tooltip.columns[colNum]) + cell:SetPoint("RIGHT", tooltip.columns[rightColNum]) + cell:SetPoint("TOP", line) + cell:SetPoint("BOTTOM", line) + + -- Store the cell settings directly into the cell + -- That's a bit risky but is really cheap compared to other ways to do it + cell._font, cell._justification, cell._colSpan, cell._line, cell._column = font, justification, colSpan, lineNum, colNum + + -- Setup the cell content + local width, height = cell:SetupCell(tooltip, value, justification, font, ...) + cell:Show() + + if colSpan > 1 then + -- Postpone width changes until the tooltip is shown + local colRange = colNum .. "-" .. rightColNum + + tooltip.colspans[colRange] = max(tooltip.colspans[colRange] or 0, width) + layoutCleaner:RegisterForCleanup(tooltip) + else + -- Enlarge the column and tooltip if need be + EnlargeColumn(tooltip, tooltip.columns[colNum], width) + end + + -- Enlarge the line and tooltip if need be + if height > line.height then + SetTooltipSize(tooltip, tooltip.width, tooltip.height + height - line.height) + + line.height = height + line:SetHeight(height) + end + + if rightColNum < tooltipWidth then + return lineNum, rightColNum + 1 + else + return lineNum, nil + end +end + +do + local function CreateLine(tooltip, font, ...) + if #tooltip.columns == 0 then + error("column layout should be defined before adding line", 3) + end + + local lineNum = #tooltip.lines + 1 + local line = tooltip.lines[lineNum] or AcquireFrame(tooltip.scrollChild) + + line:SetFrameLevel(tooltip.scrollChild:GetFrameLevel() + 2) + line:SetPoint("LEFT", tooltip.scrollChild) + line:SetPoint("RIGHT", tooltip.scrollChild) + + if lineNum > 1 then + local v_margin = tooltip.cell_margin_v or CELL_MARGIN_V + + line:SetPoint("TOP", tooltip.lines[lineNum - 1], "BOTTOM", 0, -v_margin) + SetTooltipSize(tooltip, tooltip.width, tooltip.height + v_margin) + else + line:SetPoint("TOP", tooltip.scrollChild) + end + + tooltip.lines[lineNum] = line + + line.cells = line.cells or AcquireTable() + line.height = 0 + line:SetHeight(1) + line:Show() + + local colNum = 1 + + for i = 1, #tooltip.columns do + local value = select(i, ...) + + if value ~= nil then + lineNum, colNum = _SetCell(tooltip, lineNum, i, value, font, nil, 1, tooltip.labelProvider) + end + end + + return lineNum, colNum + end + + function tipPrototype:AddLine(...) + return CreateLine(self, self.regularFont, ...) + end + + function tipPrototype:AddHeader(...) + local line, col = CreateLine(self, self.headerFont, ...) + + self.lines[line].is_header = true + + return line, col + end +end -- do-block + +local GenericBackdrop = { + bgFile = "Interface\\Tooltips\\UI-Tooltip-Background" +} + +function tipPrototype:AddSeparator(height, r, g, b, a) + local lineNum, colNum = self:AddLine() + local line = self.lines[lineNum] + local color = _G.NORMAL_FONT_COLOR + + height = height or 1 + + SetTooltipSize(self, self.width, self.height + height) + + line.height = height + line:SetHeight(height) + line:SetBackdrop(GenericBackdrop) + line:SetBackdropColor(r or color.r, g or color.g, b or color.b, a or 1) + + return lineNum, colNum +end + +function tipPrototype:SetCellColor(lineNum, colNum, r, g, b, a) + local cell = self.lines[lineNum].cells[colNum] + + if cell then + local sr, sg, sb, sa = self:GetBackdropColor() + + cell:SetBackdrop(GenericBackdrop) + cell:SetBackdropColor(r or sr, g or sg, b or sb, a or sa) + end +end + +function tipPrototype:SetColumnColor(colNum, r, g, b, a) + local column = self.columns[colNum] + + if column then + local sr, sg, sb, sa = self:GetBackdropColor() + column:SetBackdrop(GenericBackdrop) + column:SetBackdropColor(r or sr, g or sg, b or sb, a or sa) + end +end + +function tipPrototype:SetLineColor(lineNum, r, g, b, a) + local line = self.lines[lineNum] + + if line then + local sr, sg, sb, sa = self:GetBackdropColor() + + line:SetBackdrop(GenericBackdrop) + line:SetBackdropColor(r or sr, g or sg, b or sb, a or sa) + end +end + +function tipPrototype:SetCellTextColor(lineNum, colNum, r, g, b, a) + local line = self.lines[lineNum] + local column = self.columns[colNum] + + if not line or not column then + return + end + + local cell = self.lines[lineNum].cells[colNum] + + if cell then + if not cell.fontString then + error("cell's label provider did not assign a fontString field", 2) + end + + if not cell.r then + cell.r, cell.g, cell.b, cell.a = cell.fontString:GetTextColor() + end + + cell.fontString:SetTextColor(r or cell.r, g or cell.g, b or cell.b, a or cell.a) + end +end + +function tipPrototype:SetColumnTextColor(colNum, r, g, b, a) + if not self.columns[colNum] then + return + end + + for lineIndex = 1, #self.lines do + self:SetCellTextColor(lineIndex, colNum, r, g, b, a) + end +end + +function tipPrototype:SetLineTextColor(lineNum, r, g, b, a) + local line = self.lines[lineNum] + + if not line then + return + end + + for cellIndex = 1, #line.cells do + self:SetCellTextColor(lineNum, line.cells[cellIndex]._column, r, g, b, a) + end +end + +function tipPrototype:SetHighlightTexture(...) + return highlightTexture:SetTexture(...) +end + +function tipPrototype:SetHighlightTexCoord(...) + highlightTexture:SetTexCoord(...) +end + +do + local function checkFont(font, level, silent) + local bad = false + + if not font then + bad = true + elseif type(font) == "string" then + local ref = _G[font] + + if not ref or type(ref) ~= "table" or type(ref.IsObjectType) ~= "function" or not ref:IsObjectType("Font") then + bad = true + end + elseif type(font) ~= "table" or type(font.IsObjectType) ~= "function" or not font:IsObjectType("Font") then + bad = true + end + + if bad then + if silent then + return false + end + + error("font must be a Font instance or a string matching the name of a global Font instance, not: " .. tostring(font), level + 1) + end + return true + end + + function tipPrototype:SetFont(font) + local is_string = type(font) == "string" + + checkFont(font, 2) + self.regularFont = is_string and _G[font] or font + end + + function tipPrototype:SetHeaderFont(font) + local is_string = type(font) == "string" + + checkFont(font, 2) + self.headerFont = is_string and _G[font] or font + end + + -- TODO: fixed argument positions / remove checks for performance? + function tipPrototype:SetCell(lineNum, colNum, value, ...) + -- Mandatory argument checking + if type(lineNum) ~= "number" then + error("line number must be a number, not: " .. tostring(lineNum), 2) + elseif lineNum < 1 or lineNum > #self.lines then + error("line number out of range: " .. tostring(lineNum), 2) + elseif type(colNum) ~= "number" then + error("column number must be a number, not: " .. tostring(colNum), 2) + elseif colNum < 1 or colNum > #self.columns then + error("column number out of range: " .. tostring(colNum), 2) + end + + -- Variable argument checking + local font, justification, colSpan, provider + local i, arg = 1, ... + + if arg == nil or checkFont(arg, 2, true) then + i, font, arg = 2, ... + end + + if arg == nil or checkJustification(arg, 2, true) then + i, justification, arg = i + 1, select(i, ...) + end + + if arg == nil or type(arg) == "number" then + i, colSpan, arg = i + 1, select(i, ...) + end + + if arg == nil or type(arg) == "table" and type(arg.AcquireCell) == "function" then + i, provider = i + 1, arg + end + + return _SetCell(self, lineNum, colNum, value, font, justification, colSpan, provider, select(i, ...)) + end +end -- do-block + +function tipPrototype:GetFont() + return self.regularFont +end + +function tipPrototype:GetHeaderFont() + return self.headerFont +end + +function tipPrototype:GetLineCount() + return #self.lines +end + +function tipPrototype:GetColumnCount() + return #self.columns +end + +------------------------------------------------------------------------------ +-- Frame Scripts +------------------------------------------------------------------------------ +local scripts = { + OnEnter = function(frame, ...) + highlightFrame:SetParent(frame) + highlightFrame:SetAllPoints(frame) + highlightFrame:Show() + + if frame._OnEnter_func then + frame:_OnEnter_func(frame._OnEnter_arg, ...) + end + end, + OnLeave = function(frame, ...) + highlightFrame:Hide() + highlightFrame:ClearAllPoints() + highlightFrame:SetParent(nil) + + if frame._OnLeave_func then + frame:_OnLeave_func(frame._OnLeave_arg, ...) + end + end, + OnMouseDown = function(frame, ...) + frame:_OnMouseDown_func(frame._OnMouseDown_arg, ...) + end, + OnMouseUp = function(frame, ...) + frame:_OnMouseUp_func(frame._OnMouseUp_arg, ...) + end, + OnReceiveDrag = function(frame, ...) + frame:_OnReceiveDrag_func(frame._OnReceiveDrag_arg, ...) + end +} + +function SetFrameScript(frame, script, func, arg) + if not scripts[script] then + return + end + + frame["_" .. script .. "_func"] = func + frame["_" .. script .. "_arg"] = arg + + if script == "OnMouseDown" or script == "OnMouseUp" or script == "OnReceiveDrag" then + if func then + frame:SetScript(script, scripts[script]) + else + frame:SetScript(script, nil) + end + end + + -- if at least one script is set, set the OnEnter/OnLeave scripts for the highlight + if frame._OnEnter_func or frame._OnLeave_func or frame._OnMouseDown_func or frame._OnMouseUp_func or frame._OnReceiveDrag_func then + frame:EnableMouse(true) + frame:SetScript("OnEnter", scripts.OnEnter) + frame:SetScript("OnLeave", scripts.OnLeave) + else + frame:EnableMouse(false) + frame:SetScript("OnEnter", nil) + frame:SetScript("OnLeave", nil) + end +end + +function ClearFrameScripts(frame) + if frame._OnEnter_func or frame._OnLeave_func or frame._OnMouseDown_func or frame._OnMouseUp_func or frame._OnReceiveDrag_func then + frame:EnableMouse(false) + + frame:SetScript("OnEnter", nil) + frame._OnEnter_func = nil + frame._OnEnter_arg = nil + + frame:SetScript("OnLeave", nil) + frame._OnLeave_func = nil + frame._OnLeave_arg = nil + + frame:SetScript("OnReceiveDrag", nil) + frame._OnReceiveDrag_func = nil + frame._OnReceiveDrag_arg = nil + + frame:SetScript("OnMouseDown", nil) + frame._OnMouseDown_func = nil + frame._OnMouseDown_arg = nil + + frame:SetScript("OnMouseUp", nil) + frame._OnMouseUp_func = nil + frame._OnMouseUp_arg = nil + end +end + +function tipPrototype:SetLineScript(lineNum, script, func, arg) + SetFrameScript(self.lines[lineNum], script, func, arg) +end + +function tipPrototype:SetColumnScript(colNum, script, func, arg) + SetFrameScript(self.columns[colNum], script, func, arg) +end + +function tipPrototype:SetCellScript(lineNum, colNum, script, func, arg) + local cell = self.lines[lineNum].cells[colNum] + + if cell then + SetFrameScript(cell, script, func, arg) + end +end + +------------------------------------------------------------------------------ +-- Auto-hiding feature +------------------------------------------------------------------------------ + +-- Script of the auto-hiding child frame +local function AutoHideTimerFrame_OnUpdate(self, elapsed) + self.checkElapsed = self.checkElapsed + elapsed + + if self.checkElapsed > 0.1 then + if self.parent:IsMouseOver() or (self.alternateFrame and self.alternateFrame:IsMouseOver()) then + self.elapsed = 0 + else + self.elapsed = self.elapsed + self.checkElapsed + + if self.elapsed >= self.delay then + lib:Release(self.parent) + end + end + + self.checkElapsed = 0 + end +end + +-- Usage: +-- :SetAutoHideDelay(0.25) => hides after 0.25sec outside of the tooltip +-- :SetAutoHideDelay(0.25, someFrame) => hides after 0.25sec outside of both the tooltip and someFrame +-- :SetAutoHideDelay() => disable auto-hiding (default) +function tipPrototype:SetAutoHideDelay(delay, alternateFrame, releaseHandler) + local timerFrame = self.autoHideTimerFrame + delay = tonumber(delay) or 0 + + if releaseHandler then + if type(releaseHandler) ~= "function" then + error("releaseHandler must be a function", 2) + end + + lib.onReleaseHandlers[self] = releaseHandler + end + + if delay > 0 then + if not timerFrame then + timerFrame = AcquireTimer(self) + timerFrame:SetScript("OnUpdate", AutoHideTimerFrame_OnUpdate) + + self.autoHideTimerFrame = timerFrame + end + + timerFrame.parent = self + timerFrame.checkElapsed = 0 + timerFrame.elapsed = 0 + timerFrame.delay = delay + timerFrame.alternateFrame = alternateFrame + timerFrame:Show() + elseif timerFrame then + self.autoHideTimerFrame = nil + + timerFrame.alternateFrame = nil + timerFrame:SetScript("OnUpdate", nil) + + ReleaseTimer(timerFrame) + end +end + +------------------------------------------------------------------------------ +-- "Smart" Anchoring +------------------------------------------------------------------------------ +local function GetTipAnchor(frame) + local x, y = frame:GetCenter() + + if not x or not y then + return "TOPLEFT", "BOTTOMLEFT" + end + + local hhalf = (x > UIParent:GetWidth() * 2 / 3) and "RIGHT" or (x < UIParent:GetWidth() / 3) and "LEFT" or "" + local vhalf = (y > UIParent:GetHeight() / 2) and "TOP" or "BOTTOM" + + return vhalf .. hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP") .. hhalf +end + +function tipPrototype:SmartAnchorTo(frame) + if not frame then + error("Invalid frame provided.", 2) + end + + self:ClearAllPoints() + self:SetClampedToScreen(true) + self:SetPoint(GetTipAnchor(frame)) +end + +------------------------------------------------------------------------------ +-- Debug slashcmds +------------------------------------------------------------------------------ +-- @debug @ +local print = print +local function PrintStats() + local tipCache = tostring(#tooltipHeap) + local frameCache = tostring(#frameHeap) + local tableCache = tostring(#tableHeap) + local header = false + + print("Tooltips used: " .. usedTooltips .. ", Cached: " .. tipCache .. ", Total: " .. tipCache + usedTooltips) + print("Frames used: " .. usedFrames .. ", Cached: " .. frameCache .. ", Total: " .. frameCache + usedFrames) + print("Tables used: " .. usedTables .. ", Cached: " .. tableCache .. ", Total: " .. tableCache + usedTables) + + for k in pairs(activeTooltips) do + if not header then + print("Active tooltips:") + header = true + end + print("- " .. k) + end +end + +SLASH_LibQTip1 = "/qtip" +_G.SlashCmdList["LibQTip"] = PrintStats +--@end-debug@]==] diff --git a/Titan/libs/LibQTip-1.0/LibQTip-1.0.toc b/Titan/libs/LibQTip-1.0/LibQTip-1.0.toc new file mode 100644 index 0000000..d7d75e8 --- /dev/null +++ b/Titan/libs/LibQTip-1.0/LibQTip-1.0.toc @@ -0,0 +1,15 @@ +## Interface: 100007 +## Title: Lib: QTip-1.0 +## Notes: Library providing multi-column tooltips. +## Author: Torhal, Adirelle, Elkano, Tristanian +## Version: 10.0.7.1 +## LoadOnDemand: 1 +## X-Credits: Kaelten (input on initial design) +## X-Category: Library, Tooltip +## X-Curse-Project-ID: 15487 +## X-Date: 2023-03-29T21:01:29Z +## X-License: Ace3 BSD-like license +## X-Website: http://www.wowace.com/addons/libqtip-1-0/ + +LibStub\LibStub.lua +lib.xml diff --git a/Titan/libs/LibQTip-1.0/LibStub/LibStub.lua b/Titan/libs/LibQTip-1.0/LibStub/LibStub.lua new file mode 100644 index 0000000..7e7b76d --- /dev/null +++ b/Titan/libs/LibQTip-1.0/LibStub/LibStub.lua @@ -0,0 +1,51 @@ +-- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $ +-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/addons/libstub/ for more info +-- LibStub is hereby placed in the Public Domain +-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke +local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! +local LibStub = _G[LIBSTUB_MAJOR] + +-- Check to see is this version of the stub is obsolete +if not LibStub or LibStub.minor < LIBSTUB_MINOR then + LibStub = LibStub or {libs = {}, minors = {} } + _G[LIBSTUB_MAJOR] = LibStub + LibStub.minor = LIBSTUB_MINOR + + -- LibStub:NewLibrary(major, minor) + -- major (string) - the major version of the library + -- minor (string or number ) - the minor version of the library + -- + -- returns nil if a newer or same version of the lib is already present + -- returns empty library object or old library object if upgrade is needed + function LibStub:NewLibrary(major, minor) + assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") + minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") + + local oldminor = self.minors[major] + if oldminor and oldminor >= minor then return nil end + self.minors[major], self.libs[major] = minor, self.libs[major] or {} + return self.libs[major], oldminor + end + + -- LibStub:GetLibrary(major, [silent]) + -- major (string) - the major version of the library + -- silent (boolean) - if true, library is optional, silently return nil if its not found + -- + -- throws an error if the library can not be found (except silent is set) + -- returns the library object if found + function LibStub:GetLibrary(major, silent) + if not self.libs[major] and not silent then + error(("Cannot find a library instance of %q."):format(tostring(major)), 2) + end + return self.libs[major], self.minors[major] + end + + -- LibStub:IterateLibraries() + -- + -- Returns an iterator for the currently registered libraries + function LibStub:IterateLibraries() + return pairs(self.libs) + end + + setmetatable(LibStub, { __call = LibStub.GetLibrary }) +end diff --git a/Titan/libs/LibQTip-1.0/README.md b/Titan/libs/LibQTip-1.0/README.md new file mode 100644 index 0000000..b61c509 --- /dev/null +++ b/Titan/libs/LibQTip-1.0/README.md @@ -0,0 +1,30 @@ +# LibQTip-1.0 +LibQTip is designed replace GameTooltip - but with added functionality, such as multiple columns - from a minimalist design perspective. + +## Features +- Ability to display and handle multiple tooltips at the same time, +- Unlimited number of columns and lines, +- Column default and per cell justification, +- Tooltip default and per cell font setting, +- Colspans, +- Possibility to add custom cells, +- Optional scrollbar, +- Optional scripts for lines, columns, or cells, +- Optional automatic hiding, +- Frames and tables recycling to reduce resource footprint. + +## Caveats +Look [here](https://www.wowace.com/projects/libqtip-1-0/pages/getting-started) for information on embedding the latest beta/release. + +**In order to achieve effective frame recycling, tooltips must be released.** + +Holding a tooltip leads to the creation of a full set of frames for every AddOn which does not follow this practice. Moreover, releasing a tooltip has a very little overhead compared to its benefits. + +## Known issues +Alignment may be altered when using :SetScale after filling the tooltip. + +## Documentation +- [Getting Started Guide](https://www.wowace.com/projects/libqtip-1-0/pages/getting-started) +- [How to Add Custom Cells](https://www.wowace.com/projects/libqtip-1-0/pages/how-to-add-custom-cells) +- [API Reference](https://www.wowace.com/projects/libqtip-1-0/pages/api-reference) +- [Standard CellProvider API](https://www.wowace.com/projects/libqtip-1-0/pages/standard-cell-provider-api) diff --git a/Titan/libs/LibQTip-1.0/lib.xml b/Titan/libs/LibQTip-1.0/lib.xml new file mode 100644 index 0000000..f212246 --- /dev/null +++ b/Titan/libs/LibQTip-1.0/lib.xml @@ -0,0 +1,4 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + <Script file="LibQTip-1.0.lua"/> +</Ui> \ No newline at end of file diff --git a/TitanPost/TitanPost.lua b/TitanPost/TitanPost.lua index 293919c..8917dcb 100644 --- a/TitanPost/TitanPost.lua +++ b/TitanPost/TitanPost.lua @@ -551,7 +551,7 @@ local function GeneratorFunction(owner, rootDescription) function() TitanUpdateConfig("init") -- Open the profile config as distinct frame - AceConfigDialog:Open("Titan Panel Addon Chars") + AceConfigDialog:Open("Titan Panel Addon Profiles") end ) diff --git a/TitanUI/Tools.lua b/TitanUI/Tools.lua index 8788acf..ece9031 100755 --- a/TitanUI/Tools.lua +++ b/TitanUI/Tools.lua @@ -70,7 +70,7 @@ local function GeneratorFunction(owner, rootDescription) GenCommand(root, id, config .. L["TITAN_PANEL_MENU_PROFILES"], function() TitanUpdateConfig("init") - AceConfigDialog:Open("Titan Panel Addon Chars") + AceConfigDialog:Open("Titan Panel Addon Profiles") end) elementDescription = root:CreateDivider()