From 79873b0523a583b918ef3589965f97cb171887ce Mon Sep 17 00:00:00 2001 From: Lothar Buchholz Date: Sun, 1 Nov 2026 00:00:24 +0100 Subject: [PATCH] - updated all libraries --- Libs/AceConfig-3.0/AceConfig-3.0.lua | 2 +- .../AceConfigDialog-3.0.lua | 85 +-- .../AceConfigRegistry-3.0.lua | 3 +- Libs/AceDB-3.0/AceDB-3.0.lua | 136 ++++- Libs/AceDBOptions-3.0/AceDBOptions-3.0.lua | 71 ++- .../widgets/AceGUIContainer-TreeGroup.lua | 12 +- .../widgets/AceGUIWidget-CheckBox.lua | 14 +- .../widgets/AceGUIWidget-ColorPicker.lua | 86 ++- .../widgets/AceGUIWidget-EditBox.lua | 18 +- .../widgets/AceGUIWidget-Heading.lua | 13 +- Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua | 7 +- .../widgets/AceGUIWidget-Keybinding.lua | 8 +- .../AceGUI-3.0/widgets/AceGUIWidget-Label.lua | 9 +- .../widgets/AceGUIWidget-MultiLineEditBox.lua | 18 +- .../widgets/AceGUIWidget-Slider.lua | 3 +- .../CallbackHandler-1.0.lua | 2 +- Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua | 515 +++++++++++++----- 17 files changed, 736 insertions(+), 266 deletions(-) diff --git a/Libs/AceConfig-3.0/AceConfig-3.0.lua b/Libs/AceConfig-3.0/AceConfig-3.0.lua index 2233c4c..1c9454a 100644 --- a/Libs/AceConfig-3.0/AceConfig-3.0.lua +++ b/Libs/AceConfig-3.0/AceConfig-3.0.lua @@ -27,7 +27,7 @@ if not AceConfig then return end local pcall, error, type, pairs = pcall, error, type, pairs -- ------------------------------------------------------------------- --- :RegisterOptionsTable(appName, options, slashcmd, persist) +-- :RegisterOptionsTable(appName, options, slashcmd) -- -- - appName - (string) application name -- - options - table or function ref, see AceConfigRegistry diff --git a/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua b/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua index 4446f4c..c7a3b18 100644 --- a/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua +++ b/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua @@ -7,7 +7,7 @@ local LibStub = LibStub local gui = LibStub("AceGUI-3.0") local reg = LibStub("AceConfigRegistry-3.0") -local MAJOR, MINOR = "AceConfigDialog-3.0", 86 +local MAJOR, MINOR = "AceConfigDialog-3.0", 93 local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not AceConfigDialog then return end @@ -517,7 +517,7 @@ local function OptionOnMouseOver(widget, event) if descStyle and descStyle ~= "tooltip" then return end - tooltip:SetText(name, 1, .82, 0, true) + tooltip:SetText(name, 1, .82, 0, 1, true) if opt.type == "multiselect" then tooltip:AddLine(user.text, 0.5, 0.5, 0.8, true) @@ -526,7 +526,7 @@ local function OptionOnMouseOver(widget, event) tooltip:AddLine(desc, 1, 1, 1, true) end if type(usage) == "string" then - tooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true) + tooltip:AddLine(usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true) end tooltip:Show() @@ -544,25 +544,28 @@ local function GetFuncName(option) end end do + local InCombatLockdown = InCombatLockdown local frame = AceConfigDialog.popup - if not frame or oldminor < 81 then + if not frame or oldminor < 93 then frame = CreateFrame("Frame", nil, UIParent) AceConfigDialog.popup = frame frame:Hide() frame:SetPoint("CENTER", UIParent, "CENTER") - frame:SetSize(320, 72) + frame:SetSize(400, 72) frame:EnableMouse(true) -- Do not allow click-through on the frame frame:SetFrameStrata("TOOLTIP") frame:SetFrameLevel(100) -- Lots of room to draw under it frame:SetScript("OnKeyDown", function(self, key) if key == "ESCAPE" then - self:SetPropagateKeyboardInput(false) + if not InCombatLockdown() then + self:SetPropagateKeyboardInput(false) + end if self.cancel:IsShown() then self.cancel:Click() else -- Showing a validation error self:Hide() end - else + elseif not InCombatLockdown() then self:SetPropagateKeyboardInput(true) end end) @@ -573,7 +576,7 @@ do frame:SetFixedFrameLevel(true) local text = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlight") - text:SetSize(290, 0) + text:SetSize(370, 0) text:SetPoint("TOP", 0, -16) frame.text = text @@ -605,11 +608,7 @@ local function confirmPopup(appName, rootframe, basepath, info, message, func, . local frame = AceConfigDialog.popup frame:Show() frame.text:SetText(message) - -- From StaticPopup.lua - -- local height = 32 + text:GetHeight() + 2; - -- height = height + 6 + accept:GetHeight() - -- We add 32 + 2 + 6 + 21 (button height) == 61 - local height = 61 + frame.text:GetHeight() + local height = 70 + frame.text:GetHeight() frame:SetHeight(height) frame.accept:ClearAllPoints() @@ -1080,6 +1079,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) @@ -1433,12 +1437,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 @@ -1503,7 +1510,7 @@ local function TreeOnButtonEnter(widget, event, uniquevalue, button) tooltip:SetPoint("LEFT",button,"RIGHT") end - tooltip:SetText(name, 1, .82, 0, true) + tooltip:SetText(name, 1, .82, 0, 1, true) if type(desc) == "string" then tooltip:AddLine(desc, 1, 1, 1, true) @@ -1942,6 +1949,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)) @@ -1963,16 +1972,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 @@ -1998,29 +2008,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/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua b/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua index 7d0d108..72e9c60 100644 --- a/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua +++ b/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua @@ -11,7 +11,7 @@ -- @release $Id$ 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/Libs/AceDB-3.0/AceDB-3.0.lua b/Libs/AceDB-3.0/AceDB-3.0.lua index 43c64c4..7325ac7 100644 --- a/Libs/AceDB-3.0/AceDB-3.0.lua +++ b/Libs/AceDB-3.0/AceDB-3.0.lua @@ -41,7 +41,7 @@ -- @class file -- @name AceDB-3.0.lua -- @release $Id$ -local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 27 +local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 40 local AceDB = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR) if not AceDB then return end -- No upgrade needed @@ -49,6 +49,7 @@ if not AceDB then return end -- No upgrade needed -- Lua APIs local type, pairs, next, error = type, pairs, next, error local setmetatable, rawset, rawget = setmetatable, rawset, rawget +local strlenutf8 = strlenutf8 -- WoW APIs local _G = _G @@ -251,17 +252,43 @@ local preserve_keys = { ["children"] = true, } -local realmKey = GetRealmName() -local charKey = UnitName("player") .. " - " .. realmKey -local _, classKey = UnitClass("player") -local _, raceKey = UnitRace("player") local factionKey = UnitFactionGroup("player") -local factionrealmKey = factionKey .. " - " .. realmKey local localeKey = GetLocale():lower() +local charKey, realmKey, classKey, raceKey, factionrealmKey, factionrealmregionKey +do + local _ + _, classKey = UnitClass("player") + _, raceKey = UnitRace("player") -local regionTable = { "US", "KR", "EU", "TW", "CN" } -local regionKey = regionTable[GetCurrentRegion()] -local factionrealmregionKey = factionrealmKey .. " - " .. regionKey + if RegionalUniqueNamesEnabled and RegionalUniqueNamesEnabled() then + local isRP = C_GameRules.IsGameRuleActive(Enum.GameRule.RPRuleset) + local isPVP = C_GameRules.IsGameRuleActive(Enum.GameRule.PvPRuleset) + if C_GameRules.IsGameRuleActive(Enum.GameRule.HardcoreRuleset) then + realmKey = "Hardcore" + elseif isRP and isPVP then + realmKey = "RP-PvP" + elseif isRP then + realmKey = "RP" + elseif isPVP then + realmKey = "PvP" + else + realmKey = "PvE" + end + local name, surname = UnitNameUnmodified("player") + charKey = name .. " " .. surname + else + realmKey = GetRealmName() + charKey = UnitNameUnmodified("player") .. " - " .. realmKey + end + + local regionTable = { "US", "KR", "EU", "TW", "CN" } + local regionName = GetCurrentRegionName() + if regionName and regionName == "" then regionName = nil end -- PTR/Beta tends to be "" + local regionKey = regionTable[GetCurrentRegion()] or regionName or "TR" + + factionrealmKey = factionKey .. " - " .. realmKey + factionrealmregionKey = factionrealmKey .. " - " .. regionKey +end -- Actual database initialization function local function initdb(sv, defaults, defaultProfile, olddb, parent) @@ -275,6 +302,18 @@ local function initdb(sv, defaults, defaultProfile, olddb, parent) -- Make a container for profile keys if not sv.profileKeys then sv.profileKeys = {} end + -- Validate any existing profile name + if sv.profileKeys[charKey] then + if type(sv.profileKeys[charKey]) ~= "string" then + sv.profileKeys[charKey] = defaultProfile or charKey + else + local profileNameLength = strlenutf8(sv.profileKeys[charKey]) + if profileNameLength == 0 or profileNameLength > 50 or sv.profileKeys[charKey]:find("^ +$") then + sv.profileKeys[charKey] = defaultProfile or charKey + end + end + end + -- Try to get the profile selected from the char db profileKey = sv.profileKeys[charKey] or defaultProfile or charKey @@ -360,7 +399,7 @@ local function logoutHandler(frame, event) -- cleanup sections that are empty without defaults local sv = rawget(db, "sv") - for section in pairs(db.keys) do + for section in pairs(rawget(db, "keys")) do if rawget(sv, section) then -- global is special, all other sections have sub-entrys -- also don't delete empty profiles on main dbs, only on namespaces @@ -377,6 +416,26 @@ local function logoutHandler(frame, event) end end end + + -- second pass after everything else is cleaned up to remove empty namespaces + -- can't be run in-loop above since there is no guaranteed order + for db in pairs(AceDB.db_registry) do + local sv = rawget(db, "sv") + local namespaces = rawget(sv, "namespaces") + if namespaces then + for name in pairs(namespaces) do + -- cleanout empty profiles table, if still present + if namespaces[name].profiles and not next(namespaces[name].profiles) then + namespaces[name].profiles = nil + end + + -- remove entire namespace, if needed + if not next(namespaces[name]) then + namespaces[name] = nil + end + end + end + end end end @@ -426,6 +485,11 @@ end function DBObjectLib:SetProfile(name) if type(name) ~= "string" then error(("Usage: AceDBObject:SetProfile(name): 'name' - string expected, got %q."):format(type(name)), 2) + else + local profileNameLength = strlenutf8(name) + if profileNameLength == 0 or profileNameLength > 50 or name:find("^ +$") then + error("Usage: AceDBObject:SetProfile(name): 'name' - string length must be between 1 and 50 characters.", 2) + end end -- changing to the same profile, dont do anything @@ -525,6 +589,17 @@ function DBObjectLib:DeleteProfile(name, silent) end end + -- remove from unloaded namespaces + if self.sv.namespaces then + for nsname, data in pairs(self.sv.namespaces) do + if self.children and self.children[nsname] then + -- already a mapped namespace + elseif data.profiles then + data.profiles[name] = nil + end + end + end + -- switch all characters that use this profile back to the default if self.sv.profileKeys then for key, profile in pairs(self.sv.profileKeys) do @@ -570,6 +645,20 @@ function DBObjectLib:CopyProfile(name, silent) end end + -- copy unloaded namespaces + if self.sv.namespaces then + for nsname, data in pairs(self.sv.namespaces) do + if self.children and self.children[nsname] then + -- already a mapped namespace + elseif data.profiles then + -- reset the current profile + data.profiles[self.keys.profile] = {} + -- copy data + copyTable(data.profiles[name], data.profiles[self.keys.profile]) + end + end + end + -- Callback: OnProfileCopied, database, sourceProfileKey self.callbacks:Fire("OnProfileCopied", self, name) end @@ -596,6 +685,18 @@ function DBObjectLib:ResetProfile(noChildren, noCallbacks) end end + -- reset unloaded namespaces + if self.sv.namespaces and not noChildren then + for nsname, data in pairs(self.sv.namespaces) do + if self.children and self.children[nsname] then + -- already a mapped namespace + elseif data.profiles then + -- reset the current profile + data.profiles[self.keys.profile] = nil + end + end + end + -- Callback: OnProfileReset, database if not noCallbacks then self.callbacks:Fire("OnProfileReset", self) @@ -606,8 +707,8 @@ end -- profile. -- @param defaultProfile The profile name to use as the default function DBObjectLib:ResetDB(defaultProfile) - if defaultProfile and type(defaultProfile) ~= "string" then - error(("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected, got %q."):format(type(defaultProfile)), 2) + if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then + error(("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or true expected, got %q."):format(type(defaultProfile)), 2) end local sv = self.sv @@ -720,8 +821,15 @@ function AceDB:New(tbl, defaults, defaultProfile) error(("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected, got %q."):format(type(defaults)), 2) end - if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then - error(("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected, got %q."):format(type(defaultProfile)), 2) + if defaultProfile then + if type(defaultProfile) == "string" then + local profileNameLength = strlenutf8(defaultProfile) + if profileNameLength == 0 or profileNameLength > 50 or defaultProfile:find("^ +$") then + error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string length must be between 1 and 50 characters.", 2) + end + elseif defaultProfile ~= true then + error(("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected, got %q."):format(type(defaultProfile)), 2) + end end return initdb(tbl, defaults, defaultProfile) diff --git a/Libs/AceDBOptions-3.0/AceDBOptions-3.0.lua b/Libs/AceDBOptions-3.0/AceDBOptions-3.0.lua index 236cf7b..dc60770 100644 --- a/Libs/AceDBOptions-3.0/AceDBOptions-3.0.lua +++ b/Libs/AceDBOptions-3.0/AceDBOptions-3.0.lua @@ -2,7 +2,7 @@ -- @class file -- @name AceDBOptions-3.0 -- @release $Id$ -local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 15 +local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 17 local AceDBOptions = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR) if not AceDBOptions then return end -- No upgrade needed @@ -33,6 +33,7 @@ local L = { delete_desc = "Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.", delete_sub = "Deletes a profile from the database.", intro = "You can change the active database profile, so you can have different settings for every character.", + name_too_long = "Profile names cannot be longer than 50 characters.", new = "New", new_sub = "Create a new empty profile.", profiles = "Profiles", @@ -56,6 +57,7 @@ if LOCALE == "deDE" then L["delete_desc"] = "Lösche vorhandene oder unbenutzte Profile aus der Datenbank, um Platz zu sparen und die SavedVariables-Datei 'sauber' zu halten." L["delete_sub"] = "Löscht ein Profil aus der Datenbank." L["intro"] = "Hier kannst du das aktive Datenbankprofil ändern, damit du verschiedene Einstellungen für jeden Charakter erstellen kannst, wodurch eine sehr flexible Konfiguration möglich wird." + L["name_too_long"] = "Profilnamen können nicht länger als 50 Zeichen sein." L["new"] = "Neu" L["new_sub"] = "Ein neues Profil erstellen." L["profiles"] = "Profile" @@ -76,6 +78,7 @@ elseif LOCALE == "frFR" then L["delete_desc"] = "Supprime les profils existants inutilisés de la base de données afin de gagner de la place et de nettoyer le fichier SavedVariables." L["delete_sub"] = "Supprime un profil de la base de données." L["intro"] = "Vous pouvez changer le profil actuel afin d'avoir des paramètres différents pour chaque personnage, permettant ainsi d'avoir une configuration très flexible." + L["name_too_long"] = "Les noms de profil ne peuvent pas dépasser 50 caractères." L["new"] = "Nouveau" L["new_sub"] = "Créée un nouveau profil vierge." L["profiles"] = "Profils" @@ -84,25 +87,26 @@ elseif LOCALE == "frFR" then L["reset_desc"] = "Réinitialise le profil actuel au cas où votre configuration est corrompue ou si vous voulez tout simplement faire table rase." L["reset_sub"] = "Réinitialise le profil actuel avec les paramètres par défaut." elseif LOCALE == "koKR" then - L["choose"] = "저장 중인 프로필" - L["choose_desc"] = "입력창에 새로운 이름을 입력하거나 저장 중인 프로필 중 하나를 선택하여 새로운 프로필을 만들 수 있습니다." + L["choose"] = "기존 프로필" + L["choose_desc"] = "편집 상자에 이름을 입력하여 새로운 프로필을 만들거나 이미 존재하는 프로필 중 하나를 선택할 수 있습니다." L["choose_sub"] = "현재 이용할 수 있는 프로필 중 하나를 선택합니다." - L["copy"] = "복사해오기" - L["copy_desc"] = "현재 사용 중인 프로필에 선택한 프로필의 설정을 복사합니다." + L["copy"] = "복사해 올 프로필" + L["copy_desc"] = "기존 프로필의 설정을 현재 활성화된 프로필로 복사합니다." L["current"] = "현재 프로필:" L["default"] = "기본값" L["delete"] = "프로필 삭제" - L["delete_confirm"] = "정말로 선택한 프로필을 삭제할까요?" - L["delete_desc"] = "저장 공간 절약과 SavedVariables 파일의 정리를 위해 데이터베이스에서 사용하지 않는 프로필을 삭제하세요." - L["delete_sub"] = "데이터베이스의 프로필을 삭제합니다." - L["intro"] = "활성 데이터베이스 프로필을 변경할 수 있고, 각 캐릭터 별로 다른 설정을 할 수 있습니다." + L["delete_confirm"] = "선택한 프로필을 삭제하시겠습니까?" + L["delete_desc"] = "데이터베이스에서 기존 프로필과 사용하지 않는 프로필을 삭제하여 공간을 절약하고 SavedVariables 파일을 정리합니다." + L["delete_sub"] = "데이터베이스에서 프로필을 삭제합니다." + L["intro"] = "활성 데이터베이스 프로필을 변경할 수 있으며, 모든 캐릭터마다 서로 다른 설정을 지정할 수 있습니다." + L["name_too_long"] = "프로필 이름은 50자리를 초과할 수 없습니다." L["new"] = "새로운 프로필" - L["new_sub"] = "새로운 프로필을 만듭니다." + L["new_sub"] = "비어 있는 프로필을 새로 만듭니다." L["profiles"] = "프로필" L["profiles_sub"] = "프로필 관리" - L["reset"] = "프로필 초기화" - L["reset_desc"] = "설정이 깨졌거나 처음부터 다시 설정을 원하는 경우, 현재 프로필을 기본값으로 초기화하세요." - L["reset_sub"] = "현재 프로필을 기본값으로 초기화합니다" + L["reset"] = "프로필 재설정" + L["reset_desc"] = "구성이 손상되었거나 처음부터 다시 시작하고 싶은 경우 현재 프로필을 기본값으로 재설정하세요." + L["reset_sub"] = "현재 프로필을 기본값으로 재설정합니다" elseif LOCALE == "esES" or LOCALE == "esMX" then L["choose"] = "Perfiles existentes" L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes." @@ -116,6 +120,7 @@ elseif LOCALE == "esES" or LOCALE == "esMX" then L["delete_desc"] = "Borra los perfiles existentes y sin uso de la base de datos para ganar espacio y limpiar el archivo SavedVariables." L["delete_sub"] = "Borra un perfil de la base de datos." L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones." + L["name_too_long"] = "Los nombres de perfil no pueden exceder los 50 caracteres." L["new"] = "Nuevo" L["new_sub"] = "Crear un nuevo perfil vacio." L["profiles"] = "Perfiles" @@ -136,6 +141,7 @@ elseif LOCALE == "zhTW" then L["delete_desc"] = "從資料庫裡刪除不再使用的設定檔,以節省空間,並且清理 SavedVariables 檔案。" L["delete_sub"] = "從資料庫裡刪除一個設定檔。" L["intro"] = "您可以從資料庫中選擇一個設定檔來使用,如此就可以讓每個角色使用不同的設定。" + L["name_too_long"] = "設定檔名稱不能超過50個字元。" L["new"] = "新建" L["new_sub"] = "新建一個空的設定檔。" L["profiles"] = "設定檔" @@ -156,6 +162,7 @@ elseif LOCALE == "zhCN" then L["delete_desc"] = "从数据库里删除不再使用的配置文件,以节省空间,并且清理SavedVariables文件。" L["delete_sub"] = "从数据库里删除一个配置文件。" L["intro"] = "你可以选择一个活动的数据配置文件,这样你的每个角色就可以拥有不同的设置值,可以给你的插件配置带来极大的灵活性。" + L["name_too_long"] = "配置文件名称不能超过50个字符。" L["new"] = "新建" L["new_sub"] = "新建一个空的配置文件。" L["profiles"] = "配置文件" @@ -166,36 +173,38 @@ elseif LOCALE == "zhCN" then elseif LOCALE == "ruRU" then L["choose"] = "Существующие профили" L["choose_desc"] = "Вы можете создать новый профиль, введя название в поле ввода, или выбрать один из уже существующих профилей." - L["choose_sub"] = "Выбор одиного из уже доступных профилей" + L["choose_sub"] = "Выбор одного из уже доступных профилей." L["copy"] = "Скопировать из" - L["copy_desc"] = "Скопировать настройки из выбранного профиля в активный." + L["copy_desc"] = "Копирование настроек из выбранного профиля в активный." L["current"] = "Текущий профиль:" L["default"] = "По умолчанию" L["delete"] = "Удалить профиль" - L["delete_confirm"] = "Вы уверены, что вы хотите удалить выбранный профиль?" - L["delete_desc"] = "Удалить существующий и неиспользуемый профиль из БД для сохранения места, и очистить SavedVariables файл." - L["delete_sub"] = "Удаление профиля из БД" - L["intro"] = "Изменяя активный профиль, вы можете задать различные настройки модификаций для каждого персонажа." + L["delete_confirm"] = "Вы уверены, что хотите удалить выбранный профиль?" + L["delete_desc"] = "Удаление существующего и неиспользуемого профиля из базы данных для сохранения места, и очистка файла SavedVariables." + L["delete_sub"] = "Удаление профиля из базы данных." + L["intro"] = "Изменяя активный профиль, Вы можете задать разные настройки для каждого персонажа." + L["name_too_long"] = "Имена профилей не могут превышать 50 символов." L["new"] = "Новый" - L["new_sub"] = "Создать новый чистый профиль" + L["new_sub"] = "Создание нового чистого профиля." L["profiles"] = "Профили" L["profiles_sub"] = "Управление профилями" - L["reset"] = "Сброс профиля" - L["reset_desc"] = "Сбросить текущий профиль к стандартным настройкам, если ваша конфигурация испорчена или вы хотите настроить всё заново." + L["reset"] = "Сбросить профиль" + L["reset_desc"] = "Сброс текущего профиля к стандартным настройкам, если Ваша конфигурация испорчена или Вы хотите настроить все заново." L["reset_sub"] = "Сброс текущего профиля на стандартный" elseif LOCALE == "itIT" then L["choose"] = "Profili Esistenti" L["choose_desc"] = "Puoi creare un nuovo profilo digitando il nome della casella di testo, oppure scegliendone uno tra i profili già esistenti." L["choose_sub"] = "Seleziona uno dei profili attualmente disponibili." L["copy"] = "Copia Da" - L["copy_desc"] = "Copia le impostazioni da un profilo esistente, nel profilo attivo in questo momento." + L["copy_desc"] = "Copia le impostazioni da un profilo esistente nel profilo attivo in questo momento." L["current"] = "Profilo Attivo:" - L["default"] = "Standard" + L["default"] = "Predefinito" L["delete"] = "Cancella un Profilo" L["delete_confirm"] = "Sei sicuro di voler cancellare il profilo selezionato?" L["delete_desc"] = "Cancella i profili non utilizzati dal database per risparmiare spazio e mantenere puliti i file di configurazione SavedVariables." L["delete_sub"] = "Cancella un profilo dal Database." L["intro"] = "Puoi cambiare il profilo attivo, in modo da usare impostazioni diverse per ogni personaggio." + L["name_too_long"] = "Il nome del profilo non può superare i 50 caratteri." L["new"] = "Nuovo" L["new_sub"] = "Crea un nuovo profilo vuoto." L["profiles"] = "Profili" @@ -216,6 +225,7 @@ elseif LOCALE == "ptBR" then L["delete_desc"] = "Remove perfis existentes e inutilizados do banco de dados para economizar espaço, e limpar o arquivo SavedVariables." L["delete_sub"] = "Remove um perfil do banco de dados." L["intro"] = "Você pode alterar o perfil do banco de dados ativo, para que possa ter definições diferentes para cada personagem." + L["name_too_long"] = "O nome do perfil não pode exceder 50 caracteres." L["new"] = "Novo" L["new_sub"] = "Cria um novo perfil vazio." L["profiles"] = "Perfis" @@ -346,6 +356,7 @@ end --[[ the real options table ]] +local strlenutf8 = strlenutf8 local optionsTable = { desc = { order = 1, @@ -382,6 +393,15 @@ local optionsTable = { order = 30, get = false, set = "SetProfile", + usage = L["name_too_long"], + validate = function(_, text) + local length = strlenutf8(text) + if length > 50 or length == 0 or text:find("^ +$") then + return false + end + return true + end, + width = 2, }, choose = { name = L["choose"], @@ -392,6 +412,7 @@ local optionsTable = { set = "SetProfile", values = "ListProfiles", arg = "common", + width = 2, }, copydesc = { order = 50, @@ -408,6 +429,7 @@ local optionsTable = { values = "ListProfiles", disabled = "HasNoProfiles", arg = "nocurrent", + width = 2, }, deldesc = { order = 70, @@ -426,6 +448,7 @@ local optionsTable = { arg = "nocurrent", confirm = true, confirmText = L["delete_confirm"], + width = 2, }, } diff --git a/Libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua b/Libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua index 89f387a..fef4557 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua +++ b/Libs/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", 47 +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 @@ -387,10 +387,6 @@ local methods = { ["RefreshTree"] = function(self,scrollToSelection,fromOnUpdate) local buttons = self.buttons local lines = self.lines - - for i, v in ipairs(buttons) do - v:Hide() - end while lines[1] do local t = tremove(lines) for k in pairs(t) do @@ -499,6 +495,10 @@ local methods = { buttonnum = buttonnum + 1 end + -- We hide the remaining buttons after updating others to avoid a blizzard bug that keeps them interactable even if hidden when hidden before updating the buttons. + for i = buttonnum, #buttons do + buttons[i]:Hide() + end end, ["SetSelected"] = function(self, value) diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua index fe17e03..6fe454e 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Checkbox Widget -------------------------------------------------------------------------------]] -local Type, Version = "CheckBox", 26 +local Type, Version = "CheckBox", 27 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -97,7 +97,7 @@ local methods = { if disabled then self.frame:Disable() self.text:SetTextColor(0.5, 0.5, 0.5) - SetDesaturation(self.check, true) + self.check:SetDesaturated(true) if self.desc then self.desc:SetTextColor(0.5, 0.5, 0.5) end @@ -105,9 +105,9 @@ local methods = { self.frame:Enable() self.text:SetTextColor(1, 1, 1) if self.tristate and self.checked == nil then - SetDesaturation(self.check, true) + self.check:SetDesaturated(true) else - SetDesaturation(self.check, false) + self.check:SetDesaturated(false) end if self.desc then self.desc:SetTextColor(1, 1, 1) @@ -119,15 +119,15 @@ local methods = { local check = self.check self.checked = value if value then - SetDesaturation(check, false) + self.check:SetDesaturated(false) check:Show() else --Nil is the unknown tristate value if self.tristate and value == nil then - SetDesaturation(check, true) + self.check:SetDesaturated(true) check:Show() else - SetDesaturation(check, false) + self.check:SetDesaturated(false) check:Hide() end end diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua index d57b008..4c40c50 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- ColorPicker Widget -------------------------------------------------------------------------------]] -local Type, Version = "ColorPicker", 25 +local Type, Version = "ColorPicker", 29 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -11,13 +11,24 @@ local pairs = pairs -- WoW APIs local CreateFrame, UIParent = CreateFrame, UIParent +-- Unfortunately we have no way to realistically detect if a client uses inverted alpha +-- as no API will tell you. Wrath uses the old colorpicker, era uses the new one, both are inverted +local INVERTED_ALPHA = (WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE and WOW_PROJECT_ID ~= WOW_PROJECT_CAMELOT) + --[[----------------------------------------------------------------------------- Support functions -------------------------------------------------------------------------------]] local function ColorCallback(self, r, g, b, a, isAlpha) + if INVERTED_ALPHA and a then + a = 1 - a + end if not self.HasAlpha then a = 1 end + -- no change, skip update + if r == self.r and g == self.g and b == self.b and a == self.a then + return + end self:SetColor(r, g, b, a) if ColorPickerFrame:IsVisible() then --colorpicker is still open @@ -50,30 +61,63 @@ local function ColorSwatch_OnClick(frame) ColorPickerFrame:SetFrameLevel(frame:GetFrameLevel() + 10) ColorPickerFrame:SetClampedToScreen(true) - ColorPickerFrame.func = function() - local r, g, b = ColorPickerFrame:GetColorRGB() - local a = 1 - OpacitySliderFrame:GetValue() - ColorCallback(self, r, g, b, a) - end + if ColorPickerFrame.SetupColorPickerAndShow then -- 10.2.5 color picker overhaul + local r2, g2, b2, a2 = self.r, self.g, self.b, (self.a or 1) + if INVERTED_ALPHA then + a2 = 1 - a2 + end - ColorPickerFrame.hasOpacity = self.HasAlpha - ColorPickerFrame.opacityFunc = function() - local r, g, b = ColorPickerFrame:GetColorRGB() - local a = 1 - OpacitySliderFrame:GetValue() - ColorCallback(self, r, g, b, a, true) - end + local info = { + swatchFunc = function() + local r, g, b = ColorPickerFrame:GetColorRGB() + local a = ColorPickerFrame:GetColorAlpha() + ColorCallback(self, r, g, b, a) + end, - local r, g, b, a = self.r, self.g, self.b, self.a - if self.HasAlpha then - ColorPickerFrame.opacity = 1 - (a or 0) - end - ColorPickerFrame:SetColorRGB(r, g, b) + hasOpacity = self.HasAlpha, + opacityFunc = function() + local r, g, b = ColorPickerFrame:GetColorRGB() + local a = ColorPickerFrame:GetColorAlpha() + ColorCallback(self, r, g, b, a, true) + end, + opacity = a2, - ColorPickerFrame.cancelFunc = function() - ColorCallback(self, r, g, b, a, true) - end + cancelFunc = function() + ColorCallback(self, r2, g2, b2, a2, true) + end, - ColorPickerFrame:Show() + r = r2, + g = g2, + b = b2, + } + + ColorPickerFrame:SetupColorPickerAndShow(info) + else + ColorPickerFrame.func = function() + local r, g, b = ColorPickerFrame:GetColorRGB() + local a = OpacitySliderFrame:GetValue() + ColorCallback(self, r, g, b, a) + end + + ColorPickerFrame.hasOpacity = self.HasAlpha + ColorPickerFrame.opacityFunc = function() + local r, g, b = ColorPickerFrame:GetColorRGB() + local a = OpacitySliderFrame:GetValue() + ColorCallback(self, r, g, b, a, true) + end + + local r, g, b, a = self.r, self.g, self.b, 1 - (self.a or 1) + if self.HasAlpha then + ColorPickerFrame.opacity = a + end + ColorPickerFrame:SetColorRGB(r, g, b) + + ColorPickerFrame.cancelFunc = function() + ColorCallback(self, r, g, b, a, true) + end + + ColorPickerFrame:Show() + end end AceGUI:ClearFocus() end diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua index bb1e4fd..ae1e969 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- EditBox Widget -------------------------------------------------------------------------------]] -local Type, Version = "EditBox", 28 +local Type, Version = "EditBox", 29 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -10,7 +10,7 @@ local tostring, pairs = tostring, pairs -- WoW APIs local PlaySound = PlaySound -local GetCursorInfo, ClearCursor, GetSpellInfo = GetCursorInfo, ClearCursor, GetSpellInfo +local GetCursorInfo, ClearCursor = GetCursorInfo, ClearCursor local CreateFrame, UIParent = CreateFrame, UIParent local _G = _G @@ -19,7 +19,11 @@ Support functions -------------------------------------------------------------------------------]] if not AceGUIEditBoxInsertLink then -- upgradeable hook - hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end) + if ChatFrameUtil and ChatFrameUtil.InsertLink then + hooksecurefunc(ChatFrameUtil, "InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end) + elseif ChatEdit_InsertLink then + hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end) + end end function _G.AceGUIEditBoxInsertLink(text) @@ -76,12 +80,16 @@ end local function EditBox_OnReceiveDrag(frame) local self = frame.obj - local type, id, info = GetCursorInfo() + local type, id, info, extra = GetCursorInfo() local name if type == "item" then name = info elseif type == "spell" then - name = GetSpellInfo(id, info) + if C_Spell and C_Spell.GetSpellName then + name = C_Spell.GetSpellName(extra) + else + name = GetSpellInfo(id, info) + end elseif type == "macro" then name = GetMacroInfo(id) end diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua index 862ae88..2c271cc 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Heading Widget -------------------------------------------------------------------------------]] -local Type, Version = "Heading", 20 +local Type, Version = "Heading", 21 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -9,7 +9,7 @@ if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end local pairs = pairs -- WoW APIs -local CreateFrame, UIParent = CreateFrame, UIParent +local CreateFrame, UIParent, issecretvalue = CreateFrame, UIParent, issecretvalue --[[----------------------------------------------------------------------------- Methods @@ -21,11 +21,16 @@ local methods = { self:SetHeight(18) end, - -- ["OnRelease"] = nil, + ["OnRelease"] = function(self) + self.label:ClearText() + self.label:ClearAllPoints() + self.label:SetPoint("TOP") + self.label:SetPoint("BOTTOM") + end, ["SetText"] = function(self, text) self.label:SetText(text or "") - if text and text ~= "" then + if issecretvalue(text) or (text and text ~= "") then self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0) self.right:Show() else diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua index 378e813..6bc1a9b 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua @@ -1,7 +1,7 @@ --[[----------------------------------------------------------------------------- Icon Widget -------------------------------------------------------------------------------]] -local Type, Version = "Icon", 21 +local Type, Version = "Icon", 22 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -67,6 +67,11 @@ local methods = { end end, + ["SetImageByAtlas"] = function(self, atlasString) + local image = self.image + image:SetAtlas(atlasString) + end, + ["SetImageSize"] = function(self, width, height) self.image:SetWidth(width) self.image:SetHeight(height) diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua index 0c779dc..ee5a83b 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua +++ b/Libs/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/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua index d0841ef..41b165b 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua @@ -2,7 +2,7 @@ Label Widget Displays text and optionally an icon. -------------------------------------------------------------------------------]] -local Type, Version = "Label", 28 +local Type, Version = "Label", 29 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -124,6 +124,13 @@ local methods = { UpdateImageAnchor(self) end, + ["SetImageByAtlas"] = function(self, atlasString) + self.imageshown = true + local image = self.image + image:SetAtlas(atlasString) + UpdateImageAnchor(self) + end, + ["SetFont"] = function(self, font, height, flags) if not self.fontObject then self.fontObject = CreateFont("AceGUI30LabelFont" .. AceGUI:GetNextWidgetNum(Type)) diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua index bacb2be..3dcbaca 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua @@ -1,4 +1,4 @@ -local Type, Version = "MultiLineEditBox", 32 +local Type, Version = "MultiLineEditBox", 33 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -6,7 +6,7 @@ if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end local pairs = pairs -- WoW APIs -local GetCursorInfo, GetSpellInfo, ClearCursor = GetCursorInfo, GetSpellInfo, ClearCursor +local GetCursorInfo, ClearCursor = GetCursorInfo, ClearCursor local CreateFrame, UIParent = CreateFrame, UIParent local _G = _G @@ -16,7 +16,11 @@ Support functions if not AceGUIMultiLineEditBoxInsertLink then -- upgradeable hook - hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIMultiLineEditBoxInsertLink(...) end) + if ChatFrameUtil and ChatFrameUtil.InsertLink then + hooksecurefunc(ChatFrameUtil, "InsertLink", function(...) return _G.AceGUIMultiLineEditBoxInsertLink(...) end) + elseif ChatEdit_InsertLink then + hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIMultiLineEditBoxInsertLink(...) end) + end end function _G.AceGUIMultiLineEditBoxInsertLink(text) @@ -100,9 +104,13 @@ local function OnMouseUp(self) end local function OnReceiveDrag(self) -- EditBox / ScrollFrame - local type, id, info = GetCursorInfo() + local type, id, info, extra = GetCursorInfo() if type == "spell" then - info = GetSpellInfo(id, info) + if C_Spell and C_Spell.GetSpellName then + info = C_Spell.GetSpellName(extra) + else + info = GetSpellInfo(id, info) + end elseif type ~= "item" then return end diff --git a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua index 483d400..85b2ddb 100644 --- a/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua +++ b/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua @@ -2,7 +2,7 @@ Slider Widget Graphical Slider, like, for Range values. -------------------------------------------------------------------------------]] -local Type, Version = "Slider", 23 +local Type, Version = "Slider", 24 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end @@ -273,6 +273,7 @@ local function Constructor() widget[method] = func end slider.obj, editbox.obj = widget, widget + C_Timer.After(0.3, function() editbox:SetText(" ") UpdateText(widget) end) -- Workaround for font loading issue, making the editboxes blank until the text is changed return AceGUI:RegisterAsWidget(widget) end diff --git a/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua index 6a31c8a..05fb9d2 100644 --- a/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua +++ b/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua @@ -1,4 +1,4 @@ ---[[ $Id$ ]] +--[[ $Id: CallbackHandler-1.0.lua 25 2022-12-12 15:02:36Z nevcairiel $ ]] local MAJOR, MINOR = "CallbackHandler-1.0", 8 local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) diff --git a/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua b/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua index 94dc315..2f04bf0 100644 --- a/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua +++ b/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua @@ -1,4 +1,4 @@ - +--@curseforge-project-slug: libdbicon-1-0@ ----------------------------------------------------------------------- -- LibDBIcon-1.0 -- @@ -6,7 +6,7 @@ -- local DBICON10 = "LibDBIcon-1.0" -local DBICON10_MINOR = 44 -- Bump on changes +local DBICON10_MINOR = 57 -- Bump on changes if not LibStub then error(DBICON10 .. " requires LibStub.") end local ldb = LibStub("LibDataBroker-1.1", true) if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end @@ -16,9 +16,8 @@ if not lib then return end lib.objects = lib.objects or {} lib.callbackRegistered = lib.callbackRegistered or nil lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) -lib.notCreated = lib.notCreated or {} lib.radius = lib.radius or 5 -local next, Minimap, CreateFrame = next, Minimap, CreateFrame +local next, Minimap, CreateFrame, AddonCompartmentFrame = next, Minimap, CreateFrame, AddonCompartmentFrame lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate") local isDraggingButton = false @@ -26,6 +25,15 @@ function lib:IconCallback(event, name, key, value) if lib.objects[name] then if key == "icon" then lib.objects[name].icon:SetTexture(value) + if lib:IsButtonInCompartment(name) and lib:IsButtonCompartmentAvailable() then + local addonList = AddonCompartmentFrame.registeredAddons + for i =1, #addonList do + if addonList[i].text == name then + addonList[i].icon = value + return + end + end + end elseif key == "iconCoords" then lib.objects[name].icon:UpdateCoord() elseif key == "iconR" then @@ -95,6 +103,33 @@ local function onLeave(self) end end +local function onEnterCompartment(self, menu) + local buttonName = menu.text + local object = lib.objects[buttonName] + if object and object.dataObject then + if object.dataObject.OnTooltipShow then + lib.tooltip:SetOwner(self, "ANCHOR_NONE") + lib.tooltip:SetPoint(getAnchors(self)) + object.dataObject.OnTooltipShow(lib.tooltip) + lib.tooltip:Show() + elseif object.dataObject.OnEnter then + object.dataObject.OnEnter(self) + end + end +end + +local function onLeaveCompartment(self, menu) + lib.tooltip:Hide() + + local buttonName = menu.text + local object = lib.objects[buttonName] + if object and object.dataObject then + if object.dataObject.OnLeave then + object.dataObject.OnLeave(self) + end + end +end + -------------------------------------------------------------------------------- local onDragStart, updatePosition @@ -213,43 +248,39 @@ local function updateCoord(self) self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY) end -local function createButton(name, object, db) +local function createButton(name, object, db, customCompartmentIcon) local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap) button.dataObject = object button.db = db + lib.objects[name] = button + button:SetFrameStrata("MEDIUM") - if button.SetFixedFrameStrata then -- Classic support - button:SetFixedFrameStrata(true) - end + button:SetFixedFrameStrata(true) button:SetFrameLevel(8) - if button.SetFixedFrameLevel then -- Classic support - button:SetFixedFrameLevel(true) - end - button:SetSize(31, 31) + button:SetFixedFrameLevel(true) button:RegisterForClicks("anyUp") button:RegisterForDrag("LeftButton") - button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight" - local overlay = button:CreateTexture(nil, "OVERLAY") - overlay:SetSize(53, 53) - overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder" - overlay:SetPoint("TOPLEFT") - local background = button:CreateTexture(nil, "BACKGROUND") - background:SetSize(20, 20) - background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background" - background:SetPoint("TOPLEFT", 7, -5) - local icon = button:CreateTexture(nil, "ARTWORK") - icon:SetSize(17, 17) - icon:SetTexture(object.icon) - icon:SetPoint("TOPLEFT", 7, -6) - button.icon = icon - button.isMouseDown = false + lib:ResetButtonHighlightTexture(name) + lib:ResetButtonSize(name) + local border = button:CreateTexture(nil, "OVERLAY") + button.border = border + lib:ResetButtonBorder(name) + + local background = button:CreateTexture(nil, "BACKGROUND") + button.background = background + lib:ResetButtonBackground(name) + + local icon = button:CreateTexture(nil, "ARTWORK") + icon:SetTexture(object.icon) local r, g, b = icon:GetVertexColor() icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b) - icon.UpdateCoord = updateCoord icon:UpdateCoord() + button.icon = icon + lib:ResetButtonIcon(name) + button.isMouseDown = false button:SetScript("OnEnter", onEnter) button:SetScript("OnLeave", onLeave) button:SetScript("OnClick", onClick) @@ -269,8 +300,6 @@ local function createButton(name, object, db) animOut:SetStartDelay(1) button.fadeOut:SetToFinalAlpha(true) - lib.objects[name] = button - if lib.loggedIn then updatePosition(button, db and db.minimapPos) if not db or not db.hide then @@ -279,23 +308,18 @@ local function createButton(name, object, db) button:Hide() end end - lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback -end --- We could use a metatable.__index on lib.objects, but then we'd create --- the icons when checking things like :IsRegistered, which is not necessary. -local function check(name) - if lib.notCreated[name] then - createButton(name, lib.notCreated[name][1], lib.notCreated[name][2]) - lib.notCreated[name] = nil + if db and db.showInCompartment then + lib:AddButtonToCompartment(name, customCompartmentIcon) end + lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback end -- Wait a bit with the initial positioning to let any GetMinimapShape addons -- load up. if not lib.loggedIn then - local f = CreateFrame("Frame") - f:SetScript("OnEvent", function(f) + local frame = CreateFrame("Frame") + frame:SetScript("OnEvent", function(self) for _, button in next, lib.objects do updatePosition(button, button.db and button.db.minimapPos) if not button.db or not button.db.hide then @@ -305,90 +329,9 @@ if not lib.loggedIn then end end lib.loggedIn = true - f:SetScript("OnEvent", nil) + self:SetScript("OnEvent", nil) end) - f:RegisterEvent("PLAYER_LOGIN") -end - -local function getDatabase(name) - return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db -end - -function lib:Register(name, object, db) - if not object.icon then error("Can't register LDB objects without icons set!") end - if lib.objects[name] or lib.notCreated[name] then error(DBICON10.. ": Object '".. name .."' is already registered.") end - if not db or not db.hide then - createButton(name, object, db) - else - lib.notCreated[name] = {object, db} - end -end - -function lib:Lock(name) - if not lib:IsRegistered(name) then return end - if lib.objects[name] then - lib.objects[name]:SetScript("OnDragStart", nil) - lib.objects[name]:SetScript("OnDragStop", nil) - end - local db = getDatabase(name) - if db then - db.lock = true - end -end - -function lib:Unlock(name) - if not lib:IsRegistered(name) then return end - if lib.objects[name] then - lib.objects[name]:SetScript("OnDragStart", onDragStart) - lib.objects[name]:SetScript("OnDragStop", onDragStop) - end - local db = getDatabase(name) - if db then - db.lock = nil - end -end - -function lib:Hide(name) - if not lib.objects[name] then return end - lib.objects[name]:Hide() -end - -function lib:Show(name) - check(name) - local button = lib.objects[name] - if button then - button:Show() - updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) - end -end - -function lib:IsRegistered(name) - return (lib.objects[name] or lib.notCreated[name]) and true or false -end - -function lib:Refresh(name, db) - check(name) - local button = lib.objects[name] - if db then - button.db = db - end - updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) - if not button.db or not button.db.hide then - button:Show() - else - button:Hide() - end - if not button.db or not button.db.lock then - button:SetScript("OnDragStart", onDragStart) - button:SetScript("OnDragStop", onDragStop) - else - button:SetScript("OnDragStart", nil) - button:SetScript("OnDragStop", nil) - end -end - -function lib:GetMinimapButton(name) - return lib.objects[name] + frame:RegisterEvent("PLAYER_LOGIN") end do @@ -411,23 +354,100 @@ do end Minimap:HookScript("OnEnter", OnMinimapEnter) Minimap:HookScript("OnLeave", OnMinimapLeave) +end - function lib:ShowOnEnter(name, value) - local button = lib.objects[name] - if button then - if value then - button.showOnMouseover = true - button.fadeOut:Stop() - button:SetAlpha(0) - else - button.showOnMouseover = false - button.fadeOut:Stop() - button:SetAlpha(1) - end +-------------------------------------------------------------------------------- +-- Button API +-- + +function lib:Register(name, object, db, customCompartmentIcon) + if not object.icon then error("Can't register LDB objects without icons set!") end + if lib:GetMinimapButton(name) then error(DBICON10.. ": Object '".. name .."' is already registered.") end + createButton(name, object, db, customCompartmentIcon) +end + +function lib:Lock(name) + local button = lib:GetMinimapButton(name) + if button then + button:SetScript("OnDragStart", nil) + button:SetScript("OnDragStop", nil) + if button.db then + button.db.lock = true end end end +function lib:Unlock(name) + local button = lib:GetMinimapButton(name) + if button then + button:SetScript("OnDragStart", onDragStart) + button:SetScript("OnDragStop", onDragStop) + if button.db then + button.db.lock = nil + end + end +end + +function lib:Hide(name) + local button = lib:GetMinimapButton(name) + if button then + button:Hide() + end +end + +function lib:Show(name) + local button = lib:GetMinimapButton(name) + if button then + button:Show() + updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) + end +end + +function lib:IsRegistered(name) + return lib.objects[name] and true or false +end + +function lib:Refresh(name, db) + local button = lib:GetMinimapButton(name) + if button then + if db then + button.db = db + end + updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) + if not button.db or not button.db.hide then + button:Show() + else + button:Hide() + end + if not button.db or not button.db.lock then + button:SetScript("OnDragStart", onDragStart) + button:SetScript("OnDragStop", onDragStop) + else + button:SetScript("OnDragStart", nil) + button:SetScript("OnDragStop", nil) + end + end +end + +function lib:ShowOnEnter(name, value) + local button = lib:GetMinimapButton(name) + if button then + if value then + button.showOnMouseover = true + button.fadeOut:Stop() + button:SetAlpha(0) + else + button.showOnMouseover = false + button.fadeOut:Stop() + button:SetAlpha(1) + end + end +end + +function lib:GetMinimapButton(name) + return lib.objects[name] +end + function lib:GetButtonList() local t = {} for name in next, lib.objects do @@ -449,9 +469,224 @@ function lib:SetButtonToPosition(button, position) updatePosition(lib.objects[button] or button, position) end --- Upgrade! +-- Button Configuration +function lib:SetButtonSize(name, size) + local button = lib:GetMinimapButton(name) + if button and type(size) == "number" then + button:SetSize(size, size) + end +end + +function lib:ResetButtonSize(name) + local button = lib:GetMinimapButton(name) + if button then + button:SetSize(31, 31) + end +end + +function lib:SetButtonHighlightTexture(name, highlightTexture) + local button = lib:GetMinimapButton(name) + if button and (type(highlightTexture) == "number" or type(highlightTexture) == "string") then + button:SetHighlightTexture(highlightTexture) + end +end + +function lib:ResetButtonHighlightTexture(name) + local button = lib:GetMinimapButton(name) + if button then + button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight" + end +end + +-- Border configuration +function lib:RemoveButtonBorder(name) + local button = lib:GetMinimapButton(name) + if button.border then + button.border:Hide() + end +end + +function lib:SetButtonBorder(name, borderTexture, size, framePoint, offsetX, offsetY) + local button = lib:GetMinimapButton(name) + if button.border then + lib:ResetButtonBorder(name) + if type(borderTexture) == "number" or type(borderTexture) == "string" then + button.border:SetTexture(borderTexture) + end + if type(size) == "number" then + button.border:SetSize(size, size) + end + if type(framePoint) == "string" then + button.border:ClearAllPoints() + button.border:SetPoint(framePoint, type(offsetX) == "number" and offsetX or 0, type(offsetY) == "number" and offsetY or 0) + end + end +end + +function lib:ResetButtonBorder(name) + local button = lib:GetMinimapButton(name) + if button.border then + button.border:Show() + button.border:ClearAllPoints() + button.border:SetPoint("TOPLEFT", 0, 0) + button.border:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder" + if lib:IsButtonCompartmentAvailable() then + button.border:SetSize(50, 50) + else + button.border:SetSize(53, 53) + end + end +end + +-- Background configuration +function lib:RemoveButtonBackground(name) + local button = lib:GetMinimapButton(name) + if button.background then + button.background:Hide() + end +end + +function lib:SetButtonBackground(name, backgroundTexture, size, framePoint, offsetX, offsetY) + local button = lib:GetMinimapButton(name) + if button.background then + lib:ResetButtonBackground(name) + if type(backgroundTexture) == "number" or type(backgroundTexture) == "string" then + button.background:SetTexture(backgroundTexture) + end + if type(size) == "number" then + button.background:SetSize(size, size) + end + if type(framePoint) == "string" then + button.background:ClearAllPoints() + button.background:SetPoint(framePoint, type(offsetX) == "number" and offsetX or 0, type(offsetY) == "number" and offsetY or 0) + end + end +end + +function lib:ResetButtonBackground(name) + local button = lib:GetMinimapButton(name) + if button.background then + button.background:Show() + button.background:ClearAllPoints() + button.background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background" + if lib:IsButtonCompartmentAvailable() then + button.background:SetSize(24, 24) + button.background:SetPoint("CENTER", 0, 0) + else + button.background:SetSize(20, 20) + button.background:SetPoint("TOPLEFT", 7, -5) + end + end +end + +-- Icon Configuration +function lib:SetButtonIcon(name, iconTexture, size, framePoint, offsetX, offsetY) + local button = lib:GetMinimapButton(name) + if button.icon then + lib:ResetButtonIcon(name) + if type(iconTexture) == "number" or type(iconTexture) == "string" then + button.icon:SetTexture(iconTexture) + end + if type(size) == "number" then + button.icon:SetSize(size, size) + end + if type(framePoint) == "string" then + button.icon:ClearAllPoints() + button.icon:SetPoint(framePoint, type(offsetX) == "number" and offsetX or 0, type(offsetY) == "number" and offsetY or 0) + end + end +end + +function lib:ResetButtonIcon(name) + local button = lib:GetMinimapButton(name) + if button.icon then + button.icon:SetTexture(button.dataObject.icon) + button.icon:UpdateCoord() + local r, g, b = button.icon:GetVertexColor() + button.icon:SetVertexColor(button.dataObject.iconR or r, button.dataObject.iconG or g, button.dataObject.iconB or b) + if lib:IsButtonCompartmentAvailable() then + button.icon:SetSize(18, 18) + button.icon:ClearAllPoints() + button.icon:SetPoint("CENTER") + else + button.icon:SetSize(17, 17) + button.icon:ClearAllPoints() + button.icon:SetPoint("TOPLEFT", 7, -6) + end + end +end + +-------------------------------------------------------------------------------- +-- Addon Compartment API +-- + +if AddonCompartmentFrame then + function lib:IsButtonCompartmentAvailable() + return true + end +else + function lib:IsButtonCompartmentAvailable() + return false + end +end + +function lib:IsButtonInCompartment(buttonName) + local object = lib.objects[buttonName] + if object and object.db and object.db.showInCompartment then + return true + end + return false +end + +function lib:AddButtonToCompartment(buttonName, customIcon) + if lib:IsButtonCompartmentAvailable() then + local object = lib.objects[buttonName] + if object and not object.compartmentData then + if object.db then + object.db.showInCompartment = true + end + object.compartmentData = { + text = buttonName, + icon = customIcon or object.dataObject.icon, + notCheckable = true, + registerForAnyClick = true, + func = function(_, menuInputData, menu) + object.dataObject.OnClick(menu, menuInputData.buttonName) + end, + funcOnEnter = onEnterCompartment, + funcOnLeave = onLeaveCompartment, + } + AddonCompartmentFrame:RegisterAddon(object.compartmentData) + end + end +end + +function lib:RemoveButtonFromCompartment(buttonName) + if lib:IsButtonCompartmentAvailable() then + local object = lib.objects[buttonName] + if object and object.compartmentData then + for i = 1, #AddonCompartmentFrame.registeredAddons do + local entry = AddonCompartmentFrame.registeredAddons[i] + if entry == object.compartmentData then + object.compartmentData = nil + if object.db then + object.db.showInCompartment = nil + end + table.remove(AddonCompartmentFrame.registeredAddons, i) + AddonCompartmentFrame:UpdateDisplay() + return + end + end + end + end +end + +-------------------------------------------------------------------------------- +-- Upgrades +-- + for name, button in next, lib.objects do - local db = getDatabase(name) + local db = button.db if not db or not db.lock then button:SetScript("OnDragStart", onDragStart) button:SetScript("OnDragStop", onDragStop) @@ -474,3 +709,9 @@ for name, button in next, lib.objects do end end lib:SetButtonRadius(lib.radius) -- Upgrade to 40 +if lib.notCreated then -- Upgrade to 50 + for name in next, lib.notCreated do + createButton(name, lib.notCreated[name][1], lib.notCreated[name][2]) + end + lib.notCreated = nil +end