diff --git a/AchievementInfo.txt b/AchievementInfo.txt index 81cd2f7..5824986 100644 --- a/AchievementInfo.txt +++ b/AchievementInfo.txt @@ -1,10 +1,11 @@ ## Title: AchievementInfo ## Description: Displays progress updates for achievements in the chat. You can display update-details like 'Slay 25/100 Monsters' if interested. |cFF0000Important:|r The messages appear only when an achievement is updated. This is no permanent tracking tool. -## Version: 2.16 +## AddOnVersion 220 +## Version: 2.20 ## Author: |c87B7CCAsto|r, @Astarax ## Contact: mail@coded-with-heart.com -## APIVersion: 100022 +## APIVersion: 100025 ## SavedVariables: ACHIEVEMENT_INFO_DB ## OptionalDependsOn: LibAddonMenu-2.0, LibStub diff --git a/AchievementInfoCommon.lua b/AchievementInfoCommon.lua index 4e7e5fa..ff0247f 100644 --- a/AchievementInfoCommon.lua +++ b/AchievementInfoCommon.lua @@ -8,7 +8,7 @@ AchievementInfo = {} AchievementInfo.name = "AchievementInfo" AchievementInfo.author = "Asto, @Astarax" -AchievementInfo.version = 2.16 +AchievementInfo.version = 2.20 AchievementInfo.savedVars = nil AchievementInfo.LangStore = {} diff --git a/AchievementInfoSettings.lua b/AchievementInfoSettings.lua index 7c594e9..7b67307 100644 --- a/AchievementInfoSettings.lua +++ b/AchievementInfoSettings.lua @@ -24,6 +24,18 @@ function AchievementInfo.loadSavedVars() cat8 = true, cat9 = true, cat10 = true, + cat11 = true, + cat12 = true, + cat13 = true, + cat14 = true, + cat15 = true, + cat16 = true, + cat17 = true, + cat18 = true, + cat19 = true, + cat20 = true, + cat21 = true, + cat22 = true, devDebug = false } diff --git a/Libs/LibAddonMenu-2.0.txt b/Libs/LibAddonMenu-2.0.txt index c6c4796..a2f6285 100644 --- a/Libs/LibAddonMenu-2.0.txt +++ b/Libs/LibAddonMenu-2.0.txt @@ -1,10 +1,16 @@ -## APIVersion: 100011 +## APIVersion: 100022 100023 ## Title: LibAddonMenu-2.0 -## Version: 2.0 r18 +## Version: 2.0 r26 +## AddOnVersion: 26 ## Author: Seerah, sirinsidiator, et al. -## Contributors: votan, merlight, Garkin +## Contributors: votan, merlight, Garkin, Randactyl, KuroiLight, silvereyes333, Baertram, kyoma ## Description: A library to aid in the creation of option panels. - +## +## This Add-on is not created by, affiliated with or sponsored by ZeniMax Media Inc. or its affiliates. +## The Elder Scrolls® and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the United States and/or other countries. +## All rights reserved +## +## You can read the full terms at https://account.elderscrollsonline.com/add-on-terms LibStub\LibStub.lua @@ -23,3 +29,4 @@ LibAddonMenu-2.0\controls\header.lua LibAddonMenu-2.0\controls\slider.lua LibAddonMenu-2.0\controls\texture.lua LibAddonMenu-2.0\controls\iconpicker.lua +LibAddonMenu-2.0\controls\divider.lua diff --git a/Libs/LibAddonMenu-2.0/LICENSE b/Libs/LibAddonMenu-2.0/LICENSE index b862858..755f075 100644 --- a/Libs/LibAddonMenu-2.0/LICENSE +++ b/Libs/LibAddonMenu-2.0/LICENSE @@ -1,6 +1,6 @@ The Artistic License 2.0 - Copyright (c) 2015 Ryan Lakanen (Seerah) + Copyright (c) 2016 Ryan Lakanen (Seerah) Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/Libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua b/Libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua index ef3def9..1638383 100644 --- a/Libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua +++ b/Libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua @@ -1,33 +1,33 @@ --- LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah) -- --- Distributed under The Artistic License 2.0 (see LICENSE) -- +-- LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah) -- +-- Distributed under The Artistic License 2.0 (see LICENSE) -- ------------------------------------------------------------------ --Register LAM with LibStub -local MAJOR, MINOR = "LibAddonMenu-2.0", 18 +local MAJOR, MINOR = "LibAddonMenu-2.0", 26 local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR) -if not lam then return end --the same or newer version of this lib is already loaded into memory +if not lam then return end --the same or newer version of this lib is already loaded into memory local messages = {} local MESSAGE_PREFIX = "[LAM2] " local function PrintLater(msg) - if CHAT_SYSTEM.primaryContainer then - d(MESSAGE_PREFIX .. msg) - else - messages[#messages + 1] = msg - end + if CHAT_SYSTEM.primaryContainer then + d(MESSAGE_PREFIX .. msg) + else + messages[#messages + 1] = msg + end end local function FlushMessages() - for i = 1, #messages do - d(MESSAGE_PREFIX .. messages[i]) - end - messages = {} + for i = 1, #messages do + d(MESSAGE_PREFIX .. messages[i]) + end + messages = {} end if LAMSettingsPanelCreated and not LAMCompatibilityWarning then - PrintLater("An old version of LibAddonMenu with compatibility issues was detected. For more information on how to proceed search for LibAddonMenu on esoui.com") - LAMCompatibilityWarning = true + PrintLater("An old version of LibAddonMenu with compatibility issues was detected. For more information on how to proceed search for LibAddonMenu on esoui.com") + LAMCompatibilityWarning = true end --UPVALUES-- @@ -38,72 +38,413 @@ local cm = CALLBACK_MANAGER local tconcat = table.concat local tinsert = table.insert +local MIN_HEIGHT = 26 +local HALF_WIDTH_LINE_SPACING = 2 +local OPTIONS_CREATION_RUNNING = 1 +local OPTIONS_CREATED = 2 +local LAM_CONFIRM_DIALOG = "LAM_CONFIRM_DIALOG" +local LAM_DEFAULTS_DIALOG = "LAM_DEFAULTS" +local LAM_RELOAD_DIALOG = "LAM_RELOAD_DIALOG" + local addonsForList = {} local addonToOptionsMap = {} -local optionsCreated = {} +local optionsState = {} lam.widgets = lam.widgets or {} local widgets = lam.widgets -lam.util = {} +lam.util = lam.util or {} local util = lam.util +lam.controlsForReload = lam.controlsForReload or {} +local controlsForReload = lam.controlsForReload -local function GetTooltipText(tooltip) - if type(tooltip) == "string" then - return tooltip - elseif type(tooltip) == "function" then - return tostring(tooltip()) - end - return nil +local function GetDefaultValue(default) + if type(default) == "function" then + return default() + end + return default +end + +local function GetStringFromValue(value) + if type(value) == "function" then + return value() + elseif type(value) == "number" then + return GetString(value) + end + return value end local function CreateBaseControl(parent, controlData, controlName) - local control = wm:CreateControl(controlName or controlData.reference, parent.scroll or parent, CT_CONTROL) - control.panel = parent.panel or parent -- if this is in a submenu, panel is the submenu's parent - control.data = controlData + local control = wm:CreateControl(controlName or controlData.reference, parent.scroll or parent, CT_CONTROL) + control.panel = parent.panel or parent -- if this is in a submenu, panel is the submenu's parent + control.data = controlData - control.isHalfWidth = controlData.width == "half" - control:SetWidth(control.panel:GetWidth() - 60) - return control + control.isHalfWidth = controlData.width == "half" + local width = 510 -- set default width in case a custom parent object is passed + if control.panel.GetWidth ~= nil then width = control.panel:GetWidth() - 60 end + control:SetWidth(width) + return control end -local MIN_HEIGHT = 26 -local HALF_WIDTH_LINE_SPACING = 2 local function CreateLabelAndContainerControl(parent, controlData, controlName) - local control = CreateBaseControl(parent, controlData, controlName) - local width = control:GetWidth() + local control = CreateBaseControl(parent, controlData, controlName) + local width = control:GetWidth() - local container = wm:CreateControl(nil, control, CT_CONTROL) - container:SetDimensions(width / 3, MIN_HEIGHT) - control.container = container + local container = wm:CreateControl(nil, control, CT_CONTROL) + container:SetDimensions(width / 3, MIN_HEIGHT) + control.container = container - local label = wm:CreateControl(nil, control, CT_LABEL) - label:SetFont("ZoFontWinH4") - label:SetHeight(MIN_HEIGHT) - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetText(controlData.name) - control.label = label + local label = wm:CreateControl(nil, control, CT_LABEL) + label:SetFont("ZoFontWinH4") + label:SetHeight(MIN_HEIGHT) + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetText(GetStringFromValue(controlData.name)) + control.label = label - if control.isHalfWidth then - control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING) - label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0) - label:SetAnchor(TOPRIGHT, control, TOPRIGHT, 0, 0) - container:SetAnchor(TOPRIGHT, control.label, BOTTOMRIGHT, 0, HALF_WIDTH_LINE_SPACING) - else - control:SetDimensions(width, MIN_HEIGHT) - container:SetAnchor(TOPRIGHT, control, TOPRIGHT, 0, 0) - label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0) - label:SetAnchor(TOPRIGHT, container, TOPLEFT, 5, 0) - end + if control.isHalfWidth then + control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING) + label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0) + label:SetAnchor(TOPRIGHT, control, TOPRIGHT, 0, 0) + container:SetAnchor(TOPRIGHT, control.label, BOTTOMRIGHT, 0, HALF_WIDTH_LINE_SPACING) + else + control:SetDimensions(width, MIN_HEIGHT) + container:SetAnchor(TOPRIGHT, control, TOPRIGHT, 0, 0) + label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0) + label:SetAnchor(TOPRIGHT, container, TOPLEFT, 5, 0) + end - control.data.tooltipText = GetTooltipText(control.data.tooltip) - control:SetMouseEnabled(true) - control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - return control + control.data.tooltipText = GetStringFromValue(control.data.tooltip) + control:SetMouseEnabled(true) + control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + return control end -util.GetTooltipText = GetTooltipText +local function GetTopPanel(panel) + while panel.panel and panel.panel ~= panel do + panel = panel.panel + end + return panel +end + +local function IsSame(objA, objB) + if #objA ~= #objB then return false end + for i = 1, #objA do + if objA[i] ~= objB[i] then return false end + end + return true +end + +local function RefreshReloadUIButton() + lam.requiresReload = false + + for i = 1, #controlsForReload do + local reloadControl = controlsForReload[i] + if not IsSame(reloadControl.startValue, {reloadControl.data.getFunc()}) then + lam.requiresReload = true + break + end + end + + lam.applyButton:SetHidden(not lam.requiresReload) +end + +local function RequestRefreshIfNeeded(control) + -- if our parent window wants to refresh controls, then fire the callback + local panel = GetTopPanel(control.panel) + local panelData = panel.data + if panelData.registerForRefresh then + cm:FireCallbacks("LAM-RefreshPanel", control) + end + RefreshReloadUIButton() +end + +local function RegisterForRefreshIfNeeded(control) + -- if our parent window wants to refresh controls, then add this to the list + local panel = GetTopPanel(control.panel) + local panelData = panel.data + if panelData.registerForRefresh or panelData.registerForDefaults then + tinsert(panel.controlsToRefresh or {}, control) -- prevent errors on custom panels + end +end + +local function RegisterForReloadIfNeeded(control) + if control.data.requiresReload then + tinsert(controlsForReload, control) + control.startValue = {control.data.getFunc()} + end +end + +local function GetConfirmDialog() + if(not ESO_Dialogs[LAM_CONFIRM_DIALOG]) then + ESO_Dialogs[LAM_CONFIRM_DIALOG] = { + canQueue = true, + title = { + text = "", + }, + mainText = { + text = "", + }, + buttons = { + [1] = { + text = SI_DIALOG_CONFIRM, + callback = function(dialog) end, + }, + [2] = { + text = SI_DIALOG_CANCEL, + } + } + } + end + return ESO_Dialogs[LAM_CONFIRM_DIALOG] +end + +local function ShowConfirmationDialog(title, body, callback) + local dialog = GetConfirmDialog() + dialog.title.text = title + dialog.mainText.text = body + dialog.buttons[1].callback = callback + ZO_Dialogs_ShowDialog(LAM_CONFIRM_DIALOG) +end + +local function GetDefaultsDialog() + if(not ESO_Dialogs[LAM_DEFAULTS_DIALOG]) then + ESO_Dialogs[LAM_DEFAULTS_DIALOG] = { + canQueue = true, + title = { + text = SI_INTERFACE_OPTIONS_RESET_TO_DEFAULT_TOOLTIP, + }, + mainText = { + text = SI_OPTIONS_RESET_PROMPT, + }, + buttons = { + [1] = { + text = SI_OPTIONS_RESET, + callback = function(dialog) end, + }, + [2] = { + text = SI_DIALOG_CANCEL, + } + } + } + end + return ESO_Dialogs[LAM_DEFAULTS_DIALOG] +end + +local function ShowDefaultsDialog(panel) + local dialog = GetDefaultsDialog() + dialog.buttons[1].callback = function() + panel:ForceDefaults() + RefreshReloadUIButton() + end + ZO_Dialogs_ShowDialog(LAM_DEFAULTS_DIALOG) +end + +local function DiscardChangesOnReloadControls() + for i = 1, #controlsForReload do + local reloadControl = controlsForReload[i] + if not IsSame(reloadControl.startValue, {reloadControl.data.getFunc()}) then + reloadControl:UpdateValue(false, unpack(reloadControl.startValue)) + end + end + lam.requiresReload = false + lam.applyButton:SetHidden(true) +end + +local function StorePanelForReopening() + local saveData = ZO_Ingame_SavedVariables["LAM"] or {} + saveData.reopenPanel = lam.currentAddonPanel:GetName() + ZO_Ingame_SavedVariables["LAM"] = saveData +end + +local function RetrievePanelForReopening() + local saveData = ZO_Ingame_SavedVariables["LAM"] + if(saveData) then + ZO_Ingame_SavedVariables["LAM"] = nil + return _G[saveData.reopenPanel] + end +end + +local function HandleReloadUIPressed() + StorePanelForReopening() + ReloadUI() +end + +local function HandleLoadDefaultsPressed() + ShowDefaultsDialog(lam.currentAddonPanel) +end + +local function GetReloadDialog() + if(not ESO_Dialogs[LAM_RELOAD_DIALOG]) then + ESO_Dialogs[LAM_RELOAD_DIALOG] = { + canQueue = true, + title = { + text = util.L["RELOAD_DIALOG_TITLE"], + }, + mainText = { + text = util.L["RELOAD_DIALOG_TEXT"], + }, + buttons = { + [1] = { + text = util.L["RELOAD_DIALOG_RELOAD_BUTTON"], + callback = function() ReloadUI() end, + }, + [2] = { + text = util.L["RELOAD_DIALOG_DISCARD_BUTTON"], + callback = DiscardChangesOnReloadControls, + } + }, + noChoiceCallback = DiscardChangesOnReloadControls, + } + end + return ESO_Dialogs[LAM_CONFIRM_DIALOG] +end + +local function ShowReloadDialogIfNeeded() + if lam.requiresReload then + local dialog = GetReloadDialog() + ZO_Dialogs_ShowDialog(LAM_RELOAD_DIALOG) + end +end + +local function UpdateWarning(control) + local warning + if control.data.warning ~= nil then + warning = util.GetStringFromValue(control.data.warning) + end + + if control.data.requiresReload then + if not warning then + warning = string.format("|cff0000%s", util.L["RELOAD_UI_WARNING"]) + else + warning = string.format("%s\n\n|cff0000%s", warning, util.L["RELOAD_UI_WARNING"]) + end + end + + if not warning then + control.warning:SetHidden(true) + else + control.warning.data = {tooltipText = warning} + control.warning:SetHidden(false) + end +end + +local localization = { + en = { + PANEL_NAME = "Addons", + AUTHOR = string.format("%s: <>", GetString(SI_ADDON_MANAGER_AUTHOR)), -- "Author: <>" + VERSION = "Version: <>", + WEBSITE = "Visit Website", + PANEL_INFO_FONT = "$(CHAT_FONT)|14|soft-shadow-thin", + RELOAD_UI_WARNING = "Changes to this setting require an UI reload in order to take effect.", + RELOAD_DIALOG_TITLE = "UI Reload required", + RELOAD_DIALOG_TEXT = "Some changes require an UI reload in order to take effect. Do you want to reload now or discard the changes?", + RELOAD_DIALOG_RELOAD_BUTTON = "Reload", + RELOAD_DIALOG_DISCARD_BUTTON = "Discard", + }, + it = { -- provided by JohnnyKing + PANEL_NAME = "Addon", + VERSION = "Versione: <>", + WEBSITE = "Visita il Sitoweb", + RELOAD_UI_WARNING = "Cambiare questa impostazione richiede un Ricarica UI al fine che faccia effetto.", + RELOAD_DIALOG_TITLE = "Ricarica UI richiesto", + RELOAD_DIALOG_TEXT = "Alcune modifiche richiedono un Ricarica UI al fine che facciano effetto. Sei sicuro di voler ricaricare ora o di voler annullare le modifiche?", + RELOAD_DIALOG_RELOAD_BUTTON = "Ricarica", + RELOAD_DIALOG_DISCARD_BUTTON = "Annulla", + }, + fr = { -- provided by Ayantir + PANEL_NAME = "Extensions", + WEBSITE = "Visiter le site Web", + RELOAD_UI_WARNING = "La modification de ce paramètre requiert un rechargement de l'UI pour qu'il soit pris en compte.", + RELOAD_DIALOG_TITLE = "Reload UI requis", + RELOAD_DIALOG_TEXT = "Certaines modifications requièrent un rechargement de l'UI pour qu'ils soient pris en compte. Souhaitez-vous recharger l'interface maintenant ou annuler les modifications ?", + RELOAD_DIALOG_RELOAD_BUTTON = "Recharger", + RELOAD_DIALOG_DISCARD_BUTTON = "Annuler", + }, + de = { -- provided by sirinsidiator + PANEL_NAME = "Erweiterungen", + WEBSITE = "Webseite besuchen", + RELOAD_UI_WARNING = "Änderungen an dieser Option werden erst übernommen nachdem die Benutzeroberfläche neu geladen wird.", + RELOAD_DIALOG_TITLE = "Neuladen benötigt", + RELOAD_DIALOG_TEXT = "Einige Änderungen werden erst übernommen nachdem die Benutzeroberfläche neu geladen wird. Wollt Ihr sie jetzt neu laden oder die Änderungen verwerfen?", + RELOAD_DIALOG_RELOAD_BUTTON = "Neu laden", + RELOAD_DIALOG_DISCARD_BUTTON = "Verwerfen", + }, + ru = { -- provided by TERAB1T + PANEL_NAME = "Дополнения", + VERSION = "Версия: <>", + WEBSITE = "Посетить сайт", + PANEL_INFO_FONT = "RuESO/fonts/Univers57.otf|14|soft-shadow-thin", + RELOAD_UI_WARNING = "Для применения этой настройки необходима перезагрузка интерфейса.", + RELOAD_DIALOG_TITLE = "Необходима перезагрузка интерфейса", + RELOAD_DIALOG_TEXT = "Для применения некоторых изменений необходима перезагрузка интерфейса. Перезагрузить интерфейс сейчас или отменить изменения?", + RELOAD_DIALOG_RELOAD_BUTTON = "Перезагрузить", + RELOAD_DIALOG_DISCARD_BUTTON = "Отменить изменения", + }, + es = { -- provided by Morganlefai, checked by Kwisatz + PANEL_NAME = "Configuración", + VERSION = "Versión: <>", + WEBSITE = "Visita la página web", + RELOAD_UI_WARNING = "Cambiar este ajuste recargará la interfaz del usuario.", + RELOAD_DIALOG_TITLE = "Requiere recargar la interfaz", + RELOAD_DIALOG_TEXT = "Algunos cambios requieren recargar la interfaz para poder aplicarse. Quieres aplicar los cambios y recargar la interfaz?", + RELOAD_DIALOG_RELOAD_BUTTON = "Recargar", + RELOAD_DIALOG_DISCARD_BUTTON = "Cancelar", + }, + jp = { -- provided by k0ta0uchi + PANEL_NAME = "アドオン設定", + WEBSITE = "ウェブサイトを見る", + }, + zh = { -- provided by bssthu + PANEL_NAME = "插件", + VERSION = "版本: <>", + WEBSITE = "访问网站", + PANEL_INFO_FONT = "EsoZh/fonts/univers57.otf|14|soft-shadow-thin", + }, + pl = { -- provided by EmiruTegryfon + PANEL_NAME = "Dodatki", + VERSION = "Wersja: <>", + WEBSITE = "Odwiedź stronę", + RELOAD_UI_WARNING = "Zmiany będą widoczne po ponownym załadowaniu UI.", + RELOAD_DIALOG_TITLE = "Wymagane przeładowanie UI", + RELOAD_DIALOG_TEXT = "Niektóre zmiany wymagają ponownego załadowania UI. Czy chcesz teraz ponownie załadować, czy porzucić zmiany?", + RELOAD_DIALOG_RELOAD_BUTTON = "Przeładuj", + RELOAD_DIALOG_DISCARD_BUTTON = "Porzuć", + }, + kr = { -- provided by p.walker + PANEL_NAME = "蝠盜蠨", + VERSION = "纄訄: <>", + WEBSITE = "裹芬襴钸 縩紸", + PANEL_INFO_FONT = "EsoKR/fonts/Univers57.otf|14|soft-shadow-thin", + RELOAD_UI_WARNING = "襴 茤訕襄 绀溽靘籴 風滼筼 訁袩靘瀰褄靴 UI 苈穜滠遨襴 靄袔革瓈瓤.", + RELOAD_DIALOG_TITLE = "UI 苈穜滠遨 靄袔", + RELOAD_DIALOG_TEXT = "绀溽瘜 茤訕 謑 UI 苈穜滠遨襄 靄袔穜靘璔 芬靭襴 覈蒵瓈瓤. 诀瀈 苈穜滠遨靘蓜溠蒵瓈灌? 蝄瓈籴 绀溽襄 迨莌靘蓜溠蒵瓈灌?", + RELOAD_DIALOG_RELOAD_BUTTON = "苈穜滠遨", + RELOAD_DIALOG_DISCARD_BUTTON = "绀溽迨莌", + }, + br = { -- provided by mlsevero + PANEL_NAME = "Addons", + AUTHOR = string.format("%s: <>", GetString(SI_ADDON_MANAGER_AUTHOR)), -- "Autor: <>" + VERSION = "Versão: <>", + WEBSITE = "Visite o Website", + RELOAD_UI_WARNING = "Mudanças nessa configuração requer a releitura da UI para ter efeito.", + RELOAD_DIALOG_TITLE = "Releitura da UI requerida", + RELOAD_DIALOG_TEXT = "Algumas mudanças requerem a releitura da UI para ter efeito. Você deseja reler agora ou descartar as mudanças?", + RELOAD_DIALOG_RELOAD_BUTTON = "Relê", + RELOAD_DIALOG_DISCARD_BUTTON = "Descarta", + }, +} + +util.L = ZO_ShallowTableCopy(localization[GetCVar("Language.2")] or {}, localization["en"]) +util.GetTooltipText = GetStringFromValue -- deprecated, use util.GetStringFromValue instead +util.GetStringFromValue = GetStringFromValue +util.GetDefaultValue = GetDefaultValue util.CreateBaseControl = CreateBaseControl util.CreateLabelAndContainerControl = CreateLabelAndContainerControl +util.RequestRefreshIfNeeded = RequestRefreshIfNeeded +util.RegisterForRefreshIfNeeded = RegisterForRefreshIfNeeded +util.RegisterForReloadIfNeeded = RegisterForReloadIfNeeded +util.GetTopPanel = GetTopPanel +util.ShowConfirmationDialog = ShowConfirmationDialog +util.UpdateWarning = UpdateWarning local ADDON_DATA_TYPE = 1 local RESELECTING_DURING_REBUILD = true @@ -112,98 +453,105 @@ local USER_REQUESTED_OPEN = true --INTERNAL FUNCTION --scrolls ZO_ScrollList `list` to move the row corresponding to `data` --- into view (does nothing if there is no such row in the list) +-- into view (does nothing if there is no such row in the list) --unlike ZO_ScrollList_ScrollDataIntoView, this function accounts for --- fading near the list's edges - it avoids the fading area by scrolling --- a little further than the ZO function +-- fading near the list's edges - it avoids the fading area by scrolling +-- a little further than the ZO function local function ScrollDataIntoView(list, data) - local targetIndex = data.sortIndex - if not targetIndex then return end + local targetIndex = data.sortIndex + if not targetIndex then return end - local scrollMin, scrollMax = list.scrollbar:GetMinMax() - local scrollTop = list.scrollbar:GetValue() - local controlHeight = list.controlHeight - local targetMin = controlHeight * (targetIndex - 1) - 64 - -- subtracting 64 ain't arbitrary, it's the maximum fading height - -- (libraries/zo_templates/scrolltemplates.lua/UpdateScrollFade) + local scrollMin, scrollMax = list.scrollbar:GetMinMax() + local scrollTop = list.scrollbar:GetValue() + local controlHeight = list.uniformControlHeight or list.controlHeight + local targetMin = controlHeight * (targetIndex - 1) - 64 + -- subtracting 64 ain't arbitrary, it's the maximum fading height + -- (libraries/zo_templates/scrolltemplates.lua/UpdateScrollFade) - if targetMin < scrollTop then - ZO_ScrollList_ScrollAbsolute(list, zo_max(targetMin, scrollMin)) - else - local listHeight = ZO_ScrollList_GetHeight(list) - local targetMax = controlHeight * targetIndex + 64 - listHeight + if targetMin < scrollTop then + ZO_ScrollList_ScrollAbsolute(list, zo_max(targetMin, scrollMin)) + else + local listHeight = ZO_ScrollList_GetHeight(list) + local targetMax = controlHeight * targetIndex + 64 - listHeight - if targetMax > scrollTop then - ZO_ScrollList_ScrollAbsolute(list, zo_min(targetMax, scrollMax)) - end - end + if targetMax > scrollTop then + ZO_ScrollList_ScrollAbsolute(list, zo_min(targetMax, scrollMax)) + end + end end --INTERNAL FUNCTION --constructs a string pattern from the text in `searchEdit` control --- * metacharacters are escaped, losing their special meaning --- * whitespace matches anything (including empty substring) +-- * metacharacters are escaped, losing their special meaning +-- * whitespace matches anything (including empty substring) --if there is nothing but whitespace, returns nil --otherwise returns a filter function, which takes a `data` table argument --- and returns true iff `data.filterText` matches the pattern +-- and returns true iff `data.filterText` matches the pattern local function GetSearchFilterFunc(searchEdit) - local text = searchEdit:GetText():lower() - local pattern = text:match("(%S+.-)%s*$") + local text = searchEdit:GetText():lower() + local pattern = text:match("(%S+.-)%s*$") - if not pattern then -- nothing but whitespace - return nil - end + if not pattern then -- nothing but whitespace + return nil + end - -- escape metacharacters, e.g. "ESO-Datenbank.de" => "ESO%-Datenbank%.de" - pattern = pattern:gsub("[-*+?^$().[%]%%]", "%%%0") + -- escape metacharacters, e.g. "ESO-Datenbank.de" => "ESO%-Datenbank%.de" + pattern = pattern:gsub("[-*+?^$().[%]%%]", "%%%0") - -- replace whitespace with "match shortest anything" - pattern = pattern:gsub("%s+", ".-") + -- replace whitespace with "match shortest anything" + pattern = pattern:gsub("%s+", ".-") - return function(data) - return data.filterText:lower():find(pattern) ~= nil - end + return function(data) + return data.filterText:lower():find(pattern) ~= nil + end end --INTERNAL FUNCTION --populates `addonList` with entries from `addonsForList` --- addonList = ZO_ScrollList control --- filter = [optional] function(data) +-- addonList = ZO_ScrollList control +-- filter = [optional] function(data) local function PopulateAddonList(addonList, filter) - local entryList = ZO_ScrollList_GetDataList(addonList) - local numEntries = 0 - local selectedData = nil + local entryList = ZO_ScrollList_GetDataList(addonList) + local numEntries = 0 + local selectedData = nil + local selectionIsFinal = false - ZO_ScrollList_Clear(addonList) + ZO_ScrollList_Clear(addonList) - for i, data in ipairs(addonsForList) do - if not filter or filter(data) then - local dataEntry = ZO_ScrollList_CreateDataEntry(ADDON_DATA_TYPE, data) - numEntries = numEntries + 1 - data.sortIndex = numEntries - entryList[numEntries] = dataEntry - -- select the first panel passing the filter, or the currently - -- shown panel, but only if it passes the filter as well - if selectedData == nil or data.panel == lam.currentAddonPanel then - selectedData = data - end - else - data.sortIndex = nil - end - end + for i, data in ipairs(addonsForList) do + if not filter or filter(data) then + local dataEntry = ZO_ScrollList_CreateDataEntry(ADDON_DATA_TYPE, data) + numEntries = numEntries + 1 + data.sortIndex = numEntries + entryList[numEntries] = dataEntry + -- select the first panel passing the filter, or the currently + -- shown panel, but only if it passes the filter as well + if selectedData == nil or data.panel == lam.pendingAddonPanel or data.panel == lam.currentAddonPanel then + if not selectionIsFinal then + selectedData = data + end + if data.panel == lam.pendingAddonPanel then + lam.pendingAddonPanel = nil + selectionIsFinal = true + end + end + else + data.sortIndex = nil + end + end - ZO_ScrollList_Commit(addonList) + ZO_ScrollList_Commit(addonList) - if selectedData then - if selectedData.panel == lam.currentAddonPanel then - ZO_ScrollList_SelectData(addonList, selectedData, nil, RESELECTING_DURING_REBUILD) - else - ZO_ScrollList_SelectData(addonList, selectedData, nil) - end - ScrollDataIntoView(addonList, selectedData) - end + if selectedData then + if selectedData.panel == lam.currentAddonPanel then + ZO_ScrollList_SelectData(addonList, selectedData, nil, RESELECTING_DURING_REBUILD) + else + ZO_ScrollList_SelectData(addonList, selectedData, nil) + end + ScrollDataIntoView(addonList, selectedData) + end end @@ -211,198 +559,277 @@ end --each widget has its version checked before loading, --so we only have the most recent one in memory --Usage: --- widgetType = "string"; the type of widget being registered --- widgetVersion = integer; the widget's version number +-- widgetType = "string"; the type of widget being registered +-- widgetVersion = integer; the widget's version number LAMCreateControl = LAMCreateControl or {} local lamcc = LAMCreateControl function lam:RegisterWidget(widgetType, widgetVersion) - if widgets[widgetType] and widgets[widgetType] >= widgetVersion then - return false - else - widgets[widgetType] = widgetVersion - return true - end + if widgets[widgetType] and widgets[widgetType] >= widgetVersion then + return false + else + widgets[widgetType] = widgetVersion + return true + end end +-- INTERNAL METHOD: hijacks the handlers for the actions in the OptionsWindow layer if not already done +local function InitKeybindActions() + if not lam.keybindsInitialized then + lam.keybindsInitialized = true + ZO_PreHook(KEYBOARD_OPTIONS, "ApplySettings", function() + if lam.currentPanelOpened then + if not lam.applyButton:IsHidden() then + HandleReloadUIPressed() + end + return true + end + end) + ZO_PreHook("ZO_Dialogs_ShowDialog", function(dialogName) + if lam.currentPanelOpened and dialogName == "OPTIONS_RESET_TO_DEFAULTS" then + if not lam.defaultButton:IsHidden() then + HandleLoadDefaultsPressed() + end + return true + end + end) + end +end + +-- INTERNAL METHOD: fires the LAM-PanelOpened callback if not already done +local function OpenCurrentPanel() + if lam.currentAddonPanel and not lam.currentPanelOpened then + lam.currentPanelOpened = true + lam.defaultButton:SetHidden(not lam.currentAddonPanel.data.registerForDefaults) + cm:FireCallbacks("LAM-PanelOpened", lam.currentAddonPanel) + end +end + +-- INTERNAL METHOD: fires the LAM-PanelClosed callback if not already done +local function CloseCurrentPanel() + if lam.currentAddonPanel and lam.currentPanelOpened then + lam.currentPanelOpened = false + cm:FireCallbacks("LAM-PanelClosed", lam.currentAddonPanel) + end +end --METHOD: OPEN TO ADDON PANEL-- --opens to a specific addon's option panel --Usage: --- panel = userdata; the panel returned by the :RegisterOptionsPanel method +-- panel = userdata; the panel returned by the :RegisterOptionsPanel method local locSettings = GetString(SI_GAME_MENU_SETTINGS) function lam:OpenToPanel(panel) - -- find and select the panel's row in addon list + -- find and select the panel's row in addon list - local addonList = lam.addonList - local selectedData = nil + local addonList = lam.addonList + local selectedData = nil - for _, addonData in ipairs(addonsForList) do - if addonData.panel == panel then - selectedData = addonData - ScrollDataIntoView(addonList, selectedData) - break - end - end + for _, addonData in ipairs(addonsForList) do + if addonData.panel == panel then + selectedData = addonData + ScrollDataIntoView(addonList, selectedData) + lam.pendingAddonPanel = addonData.panel + break + end + end - ZO_ScrollList_SelectData(addonList, selectedData) - ZO_ScrollList_RefreshVisible(addonList, selectedData) + ZO_ScrollList_SelectData(addonList, selectedData) + ZO_ScrollList_RefreshVisible(addonList, selectedData) - local srchEdit = LAMAddonSettingsWindow:GetNamedChild("SearchFilterEdit") - srchEdit:Clear() + local srchEdit = LAMAddonSettingsWindow:GetNamedChild("SearchFilterEdit") + srchEdit:Clear() - -- note that ZO_ScrollList doesn't require `selectedData` to be actually - -- present in the list, and that the list will only be populated once LAM - -- "Addon Settings" menu entry is selected for the first time + -- note that ZO_ScrollList doesn't require `selectedData` to be actually + -- present in the list, and that the list will only be populated once LAM + -- "Addon Settings" menu entry is selected for the first time - local function openAddonSettingsMenu() - local gameMenu = ZO_GameMenu_InGame.gameMenu - local settingsMenu = gameMenu.headerControls[locSettings] + local function openAddonSettingsMenu() + local gameMenu = ZO_GameMenu_InGame.gameMenu + local settingsMenu = gameMenu.headerControls[locSettings] - if settingsMenu then -- an instance of ZO_TreeNode - local children = settingsMenu:GetChildren() - for i = 1, (children and #children or 0) do - local childNode = children[i] - local data = childNode:GetData() - if data and data.id == lam.panelId then - -- found LAM "Addon Settings" node, yay! - childNode:GetTree():SelectNode(childNode) - break - end - end - end - end + if settingsMenu then -- an instance of ZO_TreeNode + local children = settingsMenu:GetChildren() + for i = 1, (children and #children or 0) do + local childNode = children[i] + local data = childNode:GetData() + if data and data.id == lam.panelId then + -- found LAM "Addon Settings" node, yay! + childNode:GetTree():SelectNode(childNode) + break + end + end + end + end - if sm:GetScene("gameMenuInGame"):GetState() == SCENE_SHOWN then - openAddonSettingsMenu() - else - sm:CallWhen("gameMenuInGame", SCENE_SHOWN, openAddonSettingsMenu) - sm:Show("gameMenuInGame") - end + if sm:GetScene("gameMenuInGame"):GetState() == SCENE_SHOWN then + openAddonSettingsMenu() + else + sm:CallWhen("gameMenuInGame", SCENE_SHOWN, openAddonSettingsMenu) + sm:Show("gameMenuInGame") + end end +local TwinOptionsContainer_Index = 0 +local function TwinOptionsContainer(parent, leftWidget, rightWidget) + TwinOptionsContainer_Index = TwinOptionsContainer_Index + 1 + local cParent = parent.scroll or parent + local panel = parent.panel or cParent + local container = wm:CreateControl("$(parent)TwinContainer" .. tostring(TwinOptionsContainer_Index), + cParent, CT_CONTROL) + container:SetResizeToFitDescendents(true) + container:SetAnchor(select(2, leftWidget:GetAnchor(0) )) + + leftWidget:ClearAnchors() + leftWidget:SetAnchor(TOPLEFT, container, TOPLEFT) + rightWidget:SetAnchor(TOPLEFT, leftWidget, TOPRIGHT, 5, 0) + + leftWidget:SetWidth( leftWidget:GetWidth() - 2.5 ) -- fixes bad alignment with 'full' controls + rightWidget:SetWidth( rightWidget:GetWidth() - 2.5 ) + + leftWidget:SetParent(container) + rightWidget:SetParent(container) + + container.data = {type = "container"} + container.panel = panel + return container +end --INTERNAL FUNCTION --creates controls when options panel is first shown --controls anchoring of these controls in the panel local function CreateOptionsControls(panel) - local addonID = panel:GetName() - local optionsTable = addonToOptionsMap[addonID] + local addonID = panel:GetName() + if(optionsState[addonID] == OPTIONS_CREATED) then + return false + elseif(optionsState[addonID] == OPTIONS_CREATION_RUNNING) then + return true + end + optionsState[addonID] = OPTIONS_CREATION_RUNNING - if optionsTable then - local function CreateAndAnchorWidget(parent, widgetData, offsetX, offsetY, anchorTarget, wasHalf) - local widget - local status, err = pcall(function() widget = LAMCreateControl[widgetData.type](parent, widgetData) end) - if not status then - return err or true, offsetY, anchorTarget, wasHalf - else - local isHalf = (widgetData.width == "half") - if not anchorTarget then -- the first widget in a panel is just placed in the top left corner - widget:SetAnchor(TOPLEFT) - anchorTarget = widget - elseif wasHalf and isHalf then -- when the previous widget was only half width and this one is too, we place it on the right side - widget:SetAnchor(TOPLEFT, anchorTarget, TOPRIGHT, 5 + (offsetX or 0), 0) - widget.lineControl = anchorTarget - offsetY = zo_max(0, widget:GetHeight() - anchorTarget:GetHeight()) -- we need to get the common height of both widgets to know where the next row starts - isHalf = false - else -- otherwise we just put it below the previous one normally - widget:SetAnchor(TOPLEFT, anchorTarget, BOTTOMLEFT, 0, 15 + offsetY) - offsetY = 0 - anchorTarget = widget - end - return false, offsetY, anchorTarget, isHalf - end - end + local function CreationFinished() + optionsState[addonID] = OPTIONS_CREATED + cm:FireCallbacks("LAM-PanelControlsCreated", panel) + OpenCurrentPanel() + end - local THROTTLE_TIMEOUT, THROTTLE_COUNT = 10, 20 - local fifo = {} - local anchorOffset, lastAddedControl, wasHalf - local CreateWidgetsInPanel, err + local optionsTable = addonToOptionsMap[addonID] + if optionsTable then + local function CreateAndAnchorWidget(parent, widgetData, offsetX, offsetY, anchorTarget, wasHalf) + local widget + local status, err = pcall(function() widget = LAMCreateControl[widgetData.type](parent, widgetData) end) + if not status then + return err or true, offsetY, anchorTarget, wasHalf + else + local isHalf = (widgetData.width == "half") + if not anchorTarget then -- the first widget in a panel is just placed in the top left corner + widget:SetAnchor(TOPLEFT) + anchorTarget = widget + elseif wasHalf and isHalf then -- when the previous widget was only half width and this one is too, we place it on the right side + widget.lineControl = anchorTarget + isHalf = false + offsetY = 0 + anchorTarget = TwinOptionsContainer(parent, anchorTarget, widget) + else -- otherwise we just put it below the previous one normally + widget:SetAnchor(TOPLEFT, anchorTarget, BOTTOMLEFT, 0, 15) + offsetY = 0 + anchorTarget = widget + end + return false, offsetY, anchorTarget, isHalf + end + end - local function PrepareForNextPanel() - anchorOffset, lastAddedControl, wasHalf = 0, nil, false - end + local THROTTLE_TIMEOUT, THROTTLE_COUNT = 10, 20 + local fifo = {} + local anchorOffset, lastAddedControl, wasHalf + local CreateWidgetsInPanel, err - local function SetupCreationCalls(parent, widgetDataTable) - fifo[#fifo + 1] = PrepareForNextPanel - local count = #widgetDataTable - for i = 1, count, THROTTLE_COUNT do - fifo[#fifo + 1] = function() - CreateWidgetsInPanel(parent, widgetDataTable, i, zo_min(i + THROTTLE_COUNT - 1, count)) - end - end - return count ~= NonContiguousCount(widgetDataTable) - end + local function PrepareForNextPanel() + anchorOffset, lastAddedControl, wasHalf = 0, nil, false + end - CreateWidgetsInPanel = function(parent, widgetDataTable, startIndex, endIndex) - for i=startIndex,endIndex do - local widgetData = widgetDataTable[i] - if not widgetData then - PrintLater("Skipped creation of missing entry in the settings menu of " .. addonID .. ".") - else - local widgetType = widgetData.type - local offsetX = 0 - local isSubmenu = (widgetType == "submenu") - if isSubmenu then - wasHalf = false - offsetX = 5 - end + local function SetupCreationCalls(parent, widgetDataTable) + fifo[#fifo + 1] = PrepareForNextPanel + local count = #widgetDataTable + for i = 1, count, THROTTLE_COUNT do + fifo[#fifo + 1] = function() + CreateWidgetsInPanel(parent, widgetDataTable, i, zo_min(i + THROTTLE_COUNT - 1, count)) + end + end + return count ~= NonContiguousCount(widgetDataTable) + end - err, anchorOffset, lastAddedControl, wasHalf = CreateAndAnchorWidget(parent, widgetData, offsetX, anchorOffset, lastAddedControl, wasHalf) - if err then - PrintLater(("Could not create %s '%s' of %s."):format(widgetData.type, widgetData.name or "unnamed", addonID)) - end + CreateWidgetsInPanel = function(parent, widgetDataTable, startIndex, endIndex) + for i=startIndex,endIndex do + local widgetData = widgetDataTable[i] + if not widgetData then + PrintLater("Skipped creation of missing entry in the settings menu of " .. addonID .. ".") + else + local widgetType = widgetData.type + local offsetX = 0 + local isSubmenu = (widgetType == "submenu") + if isSubmenu then + wasHalf = false + offsetX = 5 + end - if isSubmenu then - if SetupCreationCalls(lastAddedControl, widgetData.controls) then - PrintLater(("The sub menu '%s' of %s is missing some entries."):format(widgetData.name or "unnamed", addonID)) - end - end - end - end - end + err, anchorOffset, lastAddedControl, wasHalf = CreateAndAnchorWidget(parent, widgetData, offsetX, anchorOffset, lastAddedControl, wasHalf) + if err then + PrintLater(("Could not create %s '%s' of %s."):format(widgetData.type, GetStringFromValue(widgetData.name or "unnamed"), addonID)) + end - local function DoCreateSettings() - if #fifo > 0 then - local nextCall = table.remove(fifo, 1) - nextCall() - if(nextCall == PrepareForNextPanel) then - DoCreateSettings() - else - zo_callLater(DoCreateSettings, THROTTLE_TIMEOUT) - end - else - optionsCreated[addonID] = true - cm:FireCallbacks("LAM-PanelControlsCreated", panel) - end - end + if isSubmenu then + if SetupCreationCalls(lastAddedControl, widgetData.controls) then + PrintLater(("The sub menu '%s' of %s is missing some entries."):format(GetStringFromValue(widgetData.name or "unnamed"), addonID)) + end + end + end + end + end - if SetupCreationCalls(panel, optionsTable) then - PrintLater(("The settings menu of %s is missing some entries."):format(addonID)) - end - DoCreateSettings() - end + local function DoCreateSettings() + if #fifo > 0 then + local nextCall = table.remove(fifo, 1) + nextCall() + if(nextCall == PrepareForNextPanel) then + DoCreateSettings() + else + zo_callLater(DoCreateSettings, THROTTLE_TIMEOUT) + end + else + CreationFinished() + end + end + + if SetupCreationCalls(panel, optionsTable) then + PrintLater(("The settings menu of %s is missing some entries."):format(addonID)) + end + DoCreateSettings() + else + CreationFinished() + end + + return true end - --INTERNAL FUNCTION --handles switching between panels -local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel - local currentlySelected = lam.currentAddonPanel - if currentlySelected and currentlySelected ~= panel then - currentlySelected:SetHidden(true) - end - lam.currentAddonPanel = panel +local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel + local currentlySelected = lam.currentAddonPanel + if currentlySelected and currentlySelected ~= panel then + currentlySelected:SetHidden(true) + CloseCurrentPanel() + end + lam.currentAddonPanel = panel - -- refresh visible rows to reflect panel IsHidden status - ZO_ScrollList_RefreshVisible(lam.addonList) + -- refresh visible rows to reflect panel IsHidden status + ZO_ScrollList_RefreshVisible(lam.addonList) - if not optionsCreated[panel:GetName()] then --if this is the first time opening this panel, create these options - CreateOptionsControls(panel) - end + if not CreateOptionsControls(panel) then + OpenCurrentPanel() + end - cm:FireCallbacks("LAM-RefreshPanel", panel) + cm:FireCallbacks("LAM-RefreshPanel", panel) end local CheckSafetyAndInitialize @@ -410,40 +837,40 @@ local CheckSafetyAndInitialize --METHOD: REGISTER ADDON PANEL --registers your addon with LibAddonMenu and creates a panel --Usage: --- addonID = "string"; unique ID which will be the global name of your panel --- panelData = table; data object for your panel - see controls\panel.lua +-- addonID = "string"; unique ID which will be the global name of your panel +-- panelData = table; data object for your panel - see controls\panel.lua function lam:RegisterAddonPanel(addonID, panelData) - CheckSafetyAndInitialize(addonID) - local container = lam:GetAddonPanelContainer() - local panel = lamcc.panel(container, panelData, addonID) --addonID==global name of panel - panel:SetHidden(true) - panel:SetAnchorFill(container) - panel:SetHandler("OnShow", ToggleAddonPanels) + CheckSafetyAndInitialize(addonID) + local container = lam:GetAddonPanelContainer() + local panel = lamcc.panel(container, panelData, addonID) --addonID==global name of panel + panel:SetHidden(true) + panel:SetAnchorFill(container) + panel:SetHandler("OnShow", ToggleAddonPanels) - local function stripMarkup(str) - return str:gsub("|[Cc]%x%x%x%x%x%x", ""):gsub("|[Rr]", "") - end + local function stripMarkup(str) + return str:gsub("|[Cc]%x%x%x%x%x%x", ""):gsub("|[Rr]", "") + end - local filterParts = {panelData.name, nil, nil} - -- append keywords and author separately, the may be nil - filterParts[#filterParts + 1] = panelData.keywords - filterParts[#filterParts + 1] = panelData.author + local filterParts = {panelData.name, nil, nil} + -- append keywords and author separately, the may be nil + filterParts[#filterParts + 1] = panelData.keywords + filterParts[#filterParts + 1] = panelData.author - local addonData = { - panel = panel, - name = stripMarkup(panelData.name), - filterText = stripMarkup(tconcat(filterParts, "\t")):lower(), - } + local addonData = { + panel = panel, + name = stripMarkup(panelData.name), + filterText = stripMarkup(tconcat(filterParts, "\t")):lower(), + } - tinsert(addonsForList, addonData) + tinsert(addonsForList, addonData) - if panelData.slashCommand then - SLASH_COMMANDS[panelData.slashCommand] = function() - lam:OpenToPanel(panel) - end - end + if panelData.slashCommand then + SLASH_COMMANDS[panelData.slashCommand] = function() + lam:OpenToPanel(panel) + end + end - return panel --return for authors creating options manually + return panel --return for authors creating options manually end @@ -454,306 +881,305 @@ end --see exampleoptions.lua for an example --see controls\.lua for each widget type --Usage: --- addonID = "string"; the same string passed to :RegisterAddonPanel --- optionsTable = table; the table containing all of the options controls and their data -function lam:RegisterOptionControls(addonID, optionsTable) --optionsTable = {sliderData, buttonData, etc} - addonToOptionsMap[addonID] = optionsTable +-- addonID = "string"; the same string passed to :RegisterAddonPanel +-- optionsTable = table; the table containing all of the options controls and their data +function lam:RegisterOptionControls(addonID, optionsTable) --optionsTable = {sliderData, buttonData, etc} + addonToOptionsMap[addonID] = optionsTable end - --INTERNAL FUNCTION --creates LAM's Addon Settings entry in ZO_GameMenu local function CreateAddonSettingsMenuEntry() - --Russian for TERAB1T's RuESO addon, which creates an "ru" locale - --game font does not support Cyrillic, so they are using custom fonts + extended latin charset - --Spanish provided by Luisen75 for their translation project - local controlPanelNames = { - en = "Addon Settings", - fr = "Extensions", - de = "Erweiterungen", - ru = "Îacòpoéêè äoïoìîeîèé", - es = "Configura Addons", - } + local panelData = { + id = KEYBOARD_OPTIONS.currentPanelId, + name = util.L["PANEL_NAME"], + } - local panelData = { - id = KEYBOARD_OPTIONS.currentPanelId, - name = controlPanelNames[GetCVar("Language.2")] or controlPanelNames["en"], - } + KEYBOARD_OPTIONS.currentPanelId = panelData.id + 1 + KEYBOARD_OPTIONS.panelNames[panelData.id] = panelData.name - KEYBOARD_OPTIONS.currentPanelId = panelData.id + 1 - KEYBOARD_OPTIONS.panelNames[panelData.id] = panelData.name + lam.panelId = panelData.id - lam.panelId = panelData.id + local addonListSorted = false - local addonListSorted = false + function panelData.callback() + sm:AddFragment(lam:GetAddonSettingsFragment()) + KEYBOARD_OPTIONS:ChangePanels(lam.panelId) - function panelData.callback() - sm:AddFragment(lam:GetAddonSettingsFragment()) - KEYBOARD_OPTIONS:ChangePanels(lam.panelId) + local title = LAMAddonSettingsWindow:GetNamedChild("Title") + title:SetText(panelData.name) - local title = LAMAddonSettingsWindow:GetNamedChild("Title") - title:SetText(panelData.name) + if not addonListSorted and #addonsForList > 0 then + local searchEdit = LAMAddonSettingsWindow:GetNamedChild("SearchFilterEdit") + --we're about to show our list for the first time - let's sort it + table.sort(addonsForList, function(a, b) return a.name < b.name end) + PopulateAddonList(lam.addonList, GetSearchFilterFunc(searchEdit)) + addonListSorted = true + end + end - if not addonListSorted and #addonsForList > 0 then - local searchEdit = LAMAddonSettingsWindow:GetNamedChild("SearchFilterEdit") - --we're about to show our list for the first time - let's sort it - table.sort(addonsForList, function(a, b) return a.name < b.name end) - PopulateAddonList(lam.addonList, GetSearchFilterFunc(searchEdit)) - addonListSorted = true - end - end + function panelData.unselectedCallback() + sm:RemoveFragment(lam:GetAddonSettingsFragment()) + if SetCameraOptionsPreviewModeEnabled then -- available since API version 100011 + SetCameraOptionsPreviewModeEnabled(false) + end + end - function panelData.unselectedCallback() - sm:RemoveFragment(lam:GetAddonSettingsFragment()) - if SetCameraOptionsPreviewModeEnabled then -- available since API version 100011 - SetCameraOptionsPreviewModeEnabled(false) - end - end - - ZO_GameMenu_AddSettingPanel(panelData) + ZO_GameMenu_AddSettingPanel(panelData) end --INTERNAL FUNCTION --creates the left-hand menu in LAM's window local function CreateAddonList(name, parent) - local addonList = wm:CreateControlFromVirtual(name, parent, "ZO_ScrollList") + local addonList = wm:CreateControlFromVirtual(name, parent, "ZO_ScrollList") - local function addonListRow_OnMouseDown(control, button) - if button == 1 then - local data = ZO_ScrollList_GetData(control) - ZO_ScrollList_SelectData(addonList, data, control) - end - end + local function addonListRow_OnMouseDown(control, button) + if button == 1 then + local data = ZO_ScrollList_GetData(control) + ZO_ScrollList_SelectData(addonList, data, control) + end + end - local function addonListRow_OnMouseEnter(control) - ZO_ScrollList_MouseEnter(addonList, control) - end + local function addonListRow_OnMouseEnter(control) + ZO_ScrollList_MouseEnter(addonList, control) + end - local function addonListRow_OnMouseExit(control) - ZO_ScrollList_MouseExit(addonList, control) - end + local function addonListRow_OnMouseExit(control) + ZO_ScrollList_MouseExit(addonList, control) + end - local function addonListRow_Select(previouslySelectedData, selectedData, reselectingDuringRebuild) - if not reselectingDuringRebuild then - if previouslySelectedData then - previouslySelectedData.panel:SetHidden(true) - end - if selectedData then - selectedData.panel:SetHidden(false) - PlaySound(SOUNDS.MENU_SUBCATEGORY_SELECTION) - end - end - end + local function addonListRow_Select(previouslySelectedData, selectedData, reselectingDuringRebuild) + if not reselectingDuringRebuild then + if previouslySelectedData then + previouslySelectedData.panel:SetHidden(true) + end + if selectedData then + selectedData.panel:SetHidden(false) + PlaySound(SOUNDS.MENU_SUBCATEGORY_SELECTION) + end + end + end - local function addonListRow_Setup(control, data) - control:SetText(data.name) - control:SetSelected(not data.panel:IsHidden()) - end + local function addonListRow_Setup(control, data) + control:SetText(data.name) + control:SetSelected(not data.panel:IsHidden()) + end - ZO_ScrollList_AddDataType(addonList, ADDON_DATA_TYPE, "ZO_SelectableLabel", 28, addonListRow_Setup) - -- I don't know how to make highlights clear properly; they often - -- get stuck and after a while the list is full of highlighted rows - --ZO_ScrollList_EnableHighlight(addonList, "ZO_ThinListHighlight") - ZO_ScrollList_EnableSelection(addonList, "ZO_ThinListHighlight", addonListRow_Select) + ZO_ScrollList_AddDataType(addonList, ADDON_DATA_TYPE, "ZO_SelectableLabel", 28, addonListRow_Setup) + -- I don't know how to make highlights clear properly; they often + -- get stuck and after a while the list is full of highlighted rows + --ZO_ScrollList_EnableHighlight(addonList, "ZO_ThinListHighlight") + ZO_ScrollList_EnableSelection(addonList, "ZO_ThinListHighlight", addonListRow_Select) - local addonDataType = ZO_ScrollList_GetDataTypeTable(addonList, ADDON_DATA_TYPE) - local addonListRow_CreateRaw = addonDataType.pool.m_Factory + local addonDataType = ZO_ScrollList_GetDataTypeTable(addonList, ADDON_DATA_TYPE) + local addonListRow_CreateRaw = addonDataType.pool.m_Factory - local function addonListRow_Create(pool) - local control = addonListRow_CreateRaw(pool) - control:SetHandler("OnMouseDown", addonListRow_OnMouseDown) - --control:SetHandler("OnMouseEnter", addonListRow_OnMouseEnter) - --control:SetHandler("OnMouseExit", addonListRow_OnMouseExit) - control:SetHeight(28) - control:SetFont("ZoFontHeader") - control:SetHorizontalAlignment(TEXT_ALIGN_LEFT) - control:SetVerticalAlignment(TEXT_ALIGN_CENTER) - control:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - return control - end + local function addonListRow_Create(pool) + local control = addonListRow_CreateRaw(pool) + control:SetHandler("OnMouseDown", addonListRow_OnMouseDown) + --control:SetHandler("OnMouseEnter", addonListRow_OnMouseEnter) + --control:SetHandler("OnMouseExit", addonListRow_OnMouseExit) + control:SetHeight(28) + control:SetFont("ZoFontHeader") + control:SetHorizontalAlignment(TEXT_ALIGN_LEFT) + control:SetVerticalAlignment(TEXT_ALIGN_CENTER) + control:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + return control + end - addonDataType.pool.m_Factory = addonListRow_Create + addonDataType.pool.m_Factory = addonListRow_Create - return addonList + return addonList end --INTERNAL FUNCTION local function CreateSearchFilterBox(name, parent) - local boxControl = wm:CreateControl(name, parent, CT_CONTROL) + local boxControl = wm:CreateControl(name, parent, CT_CONTROL) - local srchButton = wm:CreateControl("$(parent)Button", boxControl, CT_BUTTON) - srchButton:SetDimensions(32, 32) - srchButton:SetAnchor(LEFT, nil, LEFT, 2, 0) - srchButton:SetNormalTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_up.dds") - srchButton:SetPressedTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_down.dds") - srchButton:SetMouseOverTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_over.dds") + local srchButton = wm:CreateControl("$(parent)Button", boxControl, CT_BUTTON) + srchButton:SetDimensions(32, 32) + srchButton:SetAnchor(LEFT, nil, LEFT, 2, 0) + srchButton:SetNormalTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_up.dds") + srchButton:SetPressedTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_down.dds") + srchButton:SetMouseOverTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_over.dds") - local srchEdit = wm:CreateControlFromVirtual("$(parent)Edit", boxControl, "ZO_DefaultEdit") - srchEdit:SetAnchor(LEFT, srchButton, RIGHT, 4, 1) - srchEdit:SetAnchor(RIGHT, nil, RIGHT, -4, 1) - srchEdit:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) + local srchEdit = wm:CreateControlFromVirtual("$(parent)Edit", boxControl, "ZO_DefaultEdit") + srchEdit:SetAnchor(LEFT, srchButton, RIGHT, 4, 1) + srchEdit:SetAnchor(RIGHT, nil, RIGHT, -4, 1) + srchEdit:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) - local srchBg = wm:CreateControl("$(parent)Bg", boxControl, CT_BACKDROP) - srchBg:SetAnchorFill() - srchBg:SetAlpha(0) - srchBg:SetCenterColor(0, 0, 0, 0.5) - srchBg:SetEdgeColor(ZO_DISABLED_TEXT:UnpackRGBA()) - srchBg:SetEdgeTexture("", 1, 1, 0, 0) + local srchBg = wm:CreateControl("$(parent)Bg", boxControl, CT_BACKDROP) + srchBg:SetAnchorFill() + srchBg:SetAlpha(0) + srchBg:SetCenterColor(0, 0, 0, 0.5) + srchBg:SetEdgeColor(ZO_DISABLED_TEXT:UnpackRGBA()) + srchBg:SetEdgeTexture("", 1, 1, 0, 0) - -- search backdrop should appear whenever you hover over either - -- the magnifying glass button or the edit field (which is only - -- visible when it contains some text), and also while the edit - -- field has keyboard focus + -- search backdrop should appear whenever you hover over either + -- the magnifying glass button or the edit field (which is only + -- visible when it contains some text), and also while the edit + -- field has keyboard focus - local srchActive = false - local srchHover = false + local srchActive = false + local srchHover = false - local function srchBgUpdateAlpha() - if srchActive or srchEdit:HasFocus() then - srchBg:SetAlpha(srchHover and 0.8 or 0.6) - else - srchBg:SetAlpha(srchHover and 0.6 or 0.0) - end - end + local function srchBgUpdateAlpha() + if srchActive or srchEdit:HasFocus() then + srchBg:SetAlpha(srchHover and 0.8 or 0.6) + else + srchBg:SetAlpha(srchHover and 0.6 or 0.0) + end + end - local function srchMouseEnter(control) - srchHover = true - srchBgUpdateAlpha() - end + local function srchMouseEnter(control) + srchHover = true + srchBgUpdateAlpha() + end - local function srchMouseExit(control) - srchHover = false - srchBgUpdateAlpha() - end + local function srchMouseExit(control) + srchHover = false + srchBgUpdateAlpha() + end - boxControl:SetMouseEnabled(true) - boxControl:SetHitInsets(1, 1, -1, -1) - boxControl:SetHandler("OnMouseEnter", srchMouseEnter) - boxControl:SetHandler("OnMouseExit", srchMouseExit) + boxControl:SetMouseEnabled(true) + boxControl:SetHitInsets(1, 1, -1, -1) + boxControl:SetHandler("OnMouseEnter", srchMouseEnter) + boxControl:SetHandler("OnMouseExit", srchMouseExit) - srchButton:SetHandler("OnMouseEnter", srchMouseEnter) - srchButton:SetHandler("OnMouseExit", srchMouseExit) + srchButton:SetHandler("OnMouseEnter", srchMouseEnter) + srchButton:SetHandler("OnMouseExit", srchMouseExit) - local focusLostTime = 0 + local focusLostTime = 0 - srchButton:SetHandler("OnClicked", function(self) - srchEdit:Clear() - if GetFrameTimeMilliseconds() - focusLostTime < 100 then - -- re-focus the edit box if it lost focus due to this - -- button click (note that this handler may run a few - -- frames later) - srchEdit:TakeFocus() - end - end) + srchButton:SetHandler("OnClicked", function(self) + srchEdit:Clear() + if GetFrameTimeMilliseconds() - focusLostTime < 100 then + -- re-focus the edit box if it lost focus due to this + -- button click (note that this handler may run a few + -- frames later) + srchEdit:TakeFocus() + end + end) - srchEdit:SetHandler("OnMouseEnter", srchMouseEnter) - srchEdit:SetHandler("OnMouseExit", srchMouseExit) - srchEdit:SetHandler("OnFocusGained", srchBgUpdateAlpha) + srchEdit:SetHandler("OnMouseEnter", srchMouseEnter) + srchEdit:SetHandler("OnMouseExit", srchMouseExit) + srchEdit:SetHandler("OnFocusGained", srchBgUpdateAlpha) - srchEdit:SetHandler("OnFocusLost", function() - focusLostTime = GetFrameTimeMilliseconds() - srchBgUpdateAlpha() - end) + srchEdit:SetHandler("OnFocusLost", function() + focusLostTime = GetFrameTimeMilliseconds() + srchBgUpdateAlpha() + end) - srchEdit:SetHandler("OnEscape", function(self) - self:Clear() - self:LoseFocus() - end) + srchEdit:SetHandler("OnEscape", function(self) + self:Clear() + self:LoseFocus() + end) - srchEdit:SetHandler("OnTextChanged", function(self) - local filterFunc = GetSearchFilterFunc(self) - if filterFunc then - srchActive = true - srchBg:SetEdgeColor(ZO_SECOND_CONTRAST_TEXT:UnpackRGBA()) - srchButton:SetState(BSTATE_PRESSED) - else - srchActive = false - srchBg:SetEdgeColor(ZO_DISABLED_TEXT:UnpackRGBA()) - srchButton:SetState(BSTATE_NORMAL) - end - srchBgUpdateAlpha() - PopulateAddonList(lam.addonList, filterFunc) - PlaySound(SOUNDS.SPINNER_DOWN) - end) + srchEdit:SetHandler("OnTextChanged", function(self) + local filterFunc = GetSearchFilterFunc(self) + if filterFunc then + srchActive = true + srchBg:SetEdgeColor(ZO_SECOND_CONTRAST_TEXT:UnpackRGBA()) + srchButton:SetState(BSTATE_PRESSED) + else + srchActive = false + srchBg:SetEdgeColor(ZO_DISABLED_TEXT:UnpackRGBA()) + srchButton:SetState(BSTATE_NORMAL) + end + srchBgUpdateAlpha() + PopulateAddonList(lam.addonList, filterFunc) + PlaySound(SOUNDS.SPINNER_DOWN) + end) - return boxControl + return boxControl end --INTERNAL FUNCTION --creates LAM's Addon Settings top-level window local function CreateAddonSettingsWindow() - local tlw = wm:CreateTopLevelWindow("LAMAddonSettingsWindow") - tlw:SetHidden(true) - tlw:SetDimensions(1010, 914) -- same height as ZO_OptionsWindow + local tlw = wm:CreateTopLevelWindow("LAMAddonSettingsWindow") + tlw:SetHidden(true) + tlw:SetDimensions(1010, 914) -- same height as ZO_OptionsWindow - ZO_ReanchorControlForLeftSidePanel(tlw) + ZO_ReanchorControlForLeftSidePanel(tlw) - -- create black background for the window (mimic ZO_RightFootPrintBackground) + -- create black background for the window (mimic ZO_RightFootPrintBackground) - local bgLeft = wm:CreateControl("$(parent)BackgroundLeft", tlw, CT_TEXTURE) - bgLeft:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_left.dds") - bgLeft:SetDimensions(1024, 1024) - bgLeft:SetAnchor(TOPLEFT, nil, TOPLEFT) - bgLeft:SetDrawLayer(DL_BACKGROUND) - bgLeft:SetExcludeFromResizeToFitExtents(true) + local bgLeft = wm:CreateControl("$(parent)BackgroundLeft", tlw, CT_TEXTURE) + bgLeft:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_left.dds") + bgLeft:SetDimensions(1024, 1024) + bgLeft:SetAnchor(TOPLEFT, nil, TOPLEFT) + bgLeft:SetDrawLayer(DL_BACKGROUND) + bgLeft:SetExcludeFromResizeToFitExtents(true) - local bgRight = wm:CreateControl("$(parent)BackgroundRight", tlw, CT_TEXTURE) - bgRight:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_right.dds") - bgRight:SetDimensions(64, 1024) - bgRight:SetAnchor(TOPLEFT, bgLeft, TOPRIGHT) - bgRight:SetDrawLayer(DL_BACKGROUND) - bgRight:SetExcludeFromResizeToFitExtents(true) + local bgRight = wm:CreateControl("$(parent)BackgroundRight", tlw, CT_TEXTURE) + bgRight:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_right.dds") + bgRight:SetDimensions(64, 1024) + bgRight:SetAnchor(TOPLEFT, bgLeft, TOPRIGHT) + bgRight:SetDrawLayer(DL_BACKGROUND) + bgRight:SetExcludeFromResizeToFitExtents(true) - -- create gray background for addon list (mimic ZO_TreeUnderlay) + -- create gray background for addon list (mimic ZO_TreeUnderlay) - local underlayLeft = wm:CreateControl("$(parent)UnderlayLeft", tlw, CT_TEXTURE) - underlayLeft:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_indexArea_left.dds") - underlayLeft:SetDimensions(256, 1024) - underlayLeft:SetAnchor(TOPLEFT, bgLeft, TOPLEFT) - underlayLeft:SetDrawLayer(DL_BACKGROUND) - underlayLeft:SetExcludeFromResizeToFitExtents(true) + local underlayLeft = wm:CreateControl("$(parent)UnderlayLeft", tlw, CT_TEXTURE) + underlayLeft:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_indexArea_left.dds") + underlayLeft:SetDimensions(256, 1024) + underlayLeft:SetAnchor(TOPLEFT, bgLeft, TOPLEFT) + underlayLeft:SetDrawLayer(DL_BACKGROUND) + underlayLeft:SetExcludeFromResizeToFitExtents(true) - local underlayRight = wm:CreateControl("$(parent)UnderlayRight", tlw, CT_TEXTURE) - underlayRight:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_indexArea_right.dds") - underlayRight:SetDimensions(128, 1024) - underlayRight:SetAnchor(TOPLEFT, underlayLeft, TOPRIGHT) - underlayRight:SetDrawLayer(DL_BACKGROUND) - underlayRight:SetExcludeFromResizeToFitExtents(true) + local underlayRight = wm:CreateControl("$(parent)UnderlayRight", tlw, CT_TEXTURE) + underlayRight:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_indexArea_right.dds") + underlayRight:SetDimensions(128, 1024) + underlayRight:SetAnchor(TOPLEFT, underlayLeft, TOPRIGHT) + underlayRight:SetDrawLayer(DL_BACKGROUND) + underlayRight:SetExcludeFromResizeToFitExtents(true) - -- create title bar (mimic ZO_OptionsWindow) + -- create title bar (mimic ZO_OptionsWindow) - local title = wm:CreateControl("$(parent)Title", tlw, CT_LABEL) - title:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 70) - title:SetFont("ZoFontWinH1") - title:SetModifyTextType(MODIFY_TEXT_TYPE_UPPERCASE) + local title = wm:CreateControl("$(parent)Title", tlw, CT_LABEL) + title:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 70) + title:SetFont("ZoFontWinH1") + title:SetModifyTextType(MODIFY_TEXT_TYPE_UPPERCASE) - local divider = wm:CreateControlFromVirtual("$(parent)Divider", tlw, "ZO_Options_Divider") - divider:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 108) + local divider = wm:CreateControlFromVirtual("$(parent)Divider", tlw, "ZO_Options_Divider") + divider:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 108) - -- create search filter box + -- create search filter box - local srchBox = CreateSearchFilterBox("$(parent)SearchFilter", tlw) - srchBox:SetAnchor(TOPLEFT, nil, TOPLEFT, 63, 120) - srchBox:SetDimensions(260, 30) + local srchBox = CreateSearchFilterBox("$(parent)SearchFilter", tlw) + srchBox:SetAnchor(TOPLEFT, nil, TOPLEFT, 63, 120) + srchBox:SetDimensions(260, 30) - -- create scrollable addon list + -- create scrollable addon list - local addonList = CreateAddonList("$(parent)AddonList", tlw) - addonList:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 160) - addonList:SetDimensions(285, 665) + local addonList = CreateAddonList("$(parent)AddonList", tlw) + addonList:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 160) + addonList:SetDimensions(285, 665) - lam.addonList = addonList -- for easy access from elsewhere + lam.addonList = addonList -- for easy access from elsewhere - -- create container for option panels + -- create container for option panels - local panelContainer = wm:CreateControl("$(parent)PanelContainer", tlw, CT_CONTROL) - panelContainer:SetAnchor(TOPLEFT, nil, TOPLEFT, 365, 120) - panelContainer:SetDimensions(645, 675) + local panelContainer = wm:CreateControl("$(parent)PanelContainer", tlw, CT_CONTROL) + panelContainer:SetAnchor(TOPLEFT, nil, TOPLEFT, 365, 120) + panelContainer:SetDimensions(645, 675) - return tlw + local defaultButton = wm:CreateControlFromVirtual("$(parent)ResetToDefaultButton", tlw, "ZO_DialogButton") + ZO_KeybindButtonTemplate_Setup(defaultButton, "OPTIONS_LOAD_DEFAULTS", HandleLoadDefaultsPressed, GetString(SI_OPTIONS_DEFAULTS)) + defaultButton:SetAnchor(TOPLEFT, panelContainer, BOTTOMLEFT, 0, 2) + lam.defaultButton = defaultButton + + local applyButton = wm:CreateControlFromVirtual("$(parent)ApplyButton", tlw, "ZO_DialogButton") + ZO_KeybindButtonTemplate_Setup(applyButton, "OPTIONS_APPLY_CHANGES", HandleReloadUIPressed, GetString(SI_ADDON_MANAGER_RELOAD)) + applyButton:SetAnchor(TOPRIGHT, panelContainer, BOTTOMRIGHT, 0, 2) + applyButton:SetHidden(true) + lam.applyButton = applyButton + + return tlw end @@ -763,47 +1189,60 @@ local hasInitialized = false local eventHandle = table.concat({MAJOR, MINOR}, "r") local function OnLoad(_, addonName) - -- wait for the first loaded event - em:UnregisterForEvent(eventHandle, EVENT_ADD_ON_LOADED) - safeToInitialize = true + -- wait for the first loaded event + em:UnregisterForEvent(eventHandle, EVENT_ADD_ON_LOADED) + safeToInitialize = true end em:RegisterForEvent(eventHandle, EVENT_ADD_ON_LOADED, OnLoad) -local function OnActivated(_, addonName) - em:UnregisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED) - FlushMessages() +local function OnActivated(_, initial) + em:UnregisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED) + FlushMessages() + + local reopenPanel = RetrievePanelForReopening() + if not initial and reopenPanel then + lam:OpenToPanel(reopenPanel) + end end em:RegisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED, OnActivated) function CheckSafetyAndInitialize(addonID) - if not safeToInitialize then - local msg = string.format("The panel with id '%s' was registered before addon loading has completed. This might break the AddOn Settings menu.", addonID) - PrintLater(msg) - end - if not hasInitialized then - hasInitialized = true - end + if not safeToInitialize then + local msg = string.format("The panel with id '%s' was registered before addon loading has completed. This might break the AddOn Settings menu.", addonID) + PrintLater(msg) + end + if not hasInitialized then + hasInitialized = true + end end --TODO documentation function lam:GetAddonPanelContainer() - local fragment = lam:GetAddonSettingsFragment() - local window = fragment:GetControl() - return window:GetNamedChild("PanelContainer") + local fragment = lam:GetAddonSettingsFragment() + local window = fragment:GetControl() + return window:GetNamedChild("PanelContainer") end --TODO documentation function lam:GetAddonSettingsFragment() - assert(hasInitialized or safeToInitialize) - if not LAMAddonSettingsFragment then - local window = CreateAddonSettingsWindow() - LAMAddonSettingsFragment = ZO_FadeSceneFragment:New(window, true, 100) - CreateAddonSettingsMenuEntry() - end - return LAMAddonSettingsFragment + assert(hasInitialized or safeToInitialize) + if not LAMAddonSettingsFragment then + local window = CreateAddonSettingsWindow() + LAMAddonSettingsFragment = ZO_FadeSceneFragment:New(window, true, 100) + LAMAddonSettingsFragment:RegisterCallback("StateChange", function(oldState, newState) + if(newState == SCENE_FRAGMENT_SHOWN) then + InitKeybindActions() + PushActionLayerByName("OptionsWindow") + OpenCurrentPanel() + elseif(newState == SCENE_FRAGMENT_HIDDEN) then + CloseCurrentPanel() + RemoveActionLayerByName("OptionsWindow") + ShowReloadDialogIfNeeded() + end + end) + CreateAddonSettingsMenuEntry() + end + return LAMAddonSettingsFragment end - - --- vi: noexpandtab diff --git a/Libs/LibAddonMenu-2.0/controls/button.lua b/Libs/LibAddonMenu-2.0/controls/button.lua index 7dad09e..be55dfc 100644 --- a/Libs/LibAddonMenu-2.0/controls/button.lua +++ b/Libs/LibAddonMenu-2.0/controls/button.lua @@ -1,89 +1,91 @@ --[[buttonData = { - type = "button", - name = "My Button", - tooltip = "Button's tooltip text.", - func = function() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - icon = "icon\\path.dds", --(optional) - warning = "Will need to reload the UI.", --(optional) - reference = "MyAddonButton" --(optional) unique global reference to control -} ]] + type = "button", + name = "My Button", -- string id or function returning a string + func = function() end, + tooltip = "Button's tooltip text.", -- string id or function returning a string (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + icon = "icon\\path.dds", --(optional) + isDangerous = false, -- boolean, if set to true, the button text will be red and a confirmation dialog with the button label and warning text will show on click before the callback is executed (optional) + warning = "Will need to reload the UI.", --(optional) + reference = "MyAddonButton", -- unique global reference to control (optional) +} ]] - -local widgetVersion = 7 +local widgetVersion = 11 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("button", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end - - control.button:SetEnabled(not disable) + local disable = control.data.disabled + if type(disable) == "function" then + disable = disable() + end + control.button:SetEnabled(not disable) end - --controlName is optional local MIN_HEIGHT = 28 -- default_button height local HALF_WIDTH_LINE_SPACING = 2 function LAMCreateControl.button(parent, buttonData, controlName) - local control = LAM.util.CreateBaseControl(parent, buttonData, controlName) - control:SetMouseEnabled(true) + local control = LAM.util.CreateBaseControl(parent, buttonData, controlName) + control:SetMouseEnabled(true) - local width = control:GetWidth() - if control.isHalfWidth then - control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING) - else - control:SetDimensions(width, MIN_HEIGHT) - end + local width = control:GetWidth() + if control.isHalfWidth then + control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING) + else + control:SetDimensions(width, MIN_HEIGHT) + end - if buttonData.icon then - control.button = wm:CreateControl(nil, control, CT_BUTTON) - control.button:SetDimensions(26, 26) - control.button:SetNormalTexture(buttonData.icon) - control.button:SetPressedOffset(2, 2) - else - --control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton") - control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton") - control.button:SetWidth(width / 3) - control.button:SetText(buttonData.name) - end - local button = control.button - button:SetAnchor(control.isHalfWidth and CENTER or RIGHT) - button:SetClickSound("Click") - button.data = {tooltipText = LAM.util.GetTooltipText(buttonData.tooltip)} - button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - button:SetHandler("OnClicked", function(self, ...) - buttonData.func(self, ...) - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - end) + if buttonData.icon then + control.button = wm:CreateControl(nil, control, CT_BUTTON) + control.button:SetDimensions(26, 26) + control.button:SetNormalTexture(buttonData.icon) + control.button:SetPressedOffset(2, 2) + else + --control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton") + control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton") + control.button:SetWidth(width / 3) + control.button:SetText(LAM.util.GetStringFromValue(buttonData.name)) + if buttonData.isDangerous then control.button:SetNormalFontColor(ZO_ERROR_COLOR:UnpackRGBA()) end + end + local button = control.button + button:SetAnchor(control.isHalfWidth and CENTER or RIGHT) + button:SetClickSound("Click") + button.data = {tooltipText = LAM.util.GetStringFromValue(buttonData.tooltip)} + button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + button:SetHandler("OnClicked", function(...) + local args = {...} + local function callback() + buttonData.func(unpack(args)) + LAM.util.RequestRefreshIfNeeded(control) + end - if buttonData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0) - control.warning.data = {tooltipText = buttonData.warning} - end + if(buttonData.isDangerous) then + local title = LAM.util.GetStringFromValue(buttonData.name) + local body = LAM.util.GetStringFromValue(buttonData.warning) + LAM.util.ShowConfirmationDialog(title, body, callback) + else + callback() + end + end) - if buttonData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() + if buttonData.warning ~= nil then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0) + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end - --this is here because buttons don't have an UpdateValue method - if control.panel.data.registerForRefresh then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end - end + if buttonData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end - return control -end \ No newline at end of file + LAM.util.RegisterForRefreshIfNeeded(control) + + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/checkbox.lua b/Libs/LibAddonMenu-2.0/controls/checkbox.lua index 8401dda..84710de 100644 --- a/Libs/LibAddonMenu-2.0/controls/checkbox.lua +++ b/Libs/LibAddonMenu-2.0/controls/checkbox.lua @@ -1,24 +1,24 @@ --[[checkboxData = { - type = "checkbox", - name = "My Checkbox", - tooltip = "Checkbox's tooltip text.", - getFunc = function() return db.var end, - setFunc = function(value) db.var = value doStuff() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonCheckbox" --(optional) unique global reference to control -} ]] + type = "checkbox", + name = "My Checkbox", -- or string id or function returning a string + getFunc = function() return db.var end, + setFunc = function(value) db.var = value doStuff() end, + tooltip = "Checkbox's tooltip text.", -- or string id or function returning a string (optional) + width = "full", -- or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional) + requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional) + default = defaults.var, -- a boolean or function that returns a boolean (optional) + reference = "MyAddonCheckbox", -- unique global reference to control (optional) +} ]] -local widgetVersion = 9 +local widgetVersion = 14 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("checkbox", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert + --label local enabledColor = ZO_DEFAULT_ENABLED_COLOR local enabledHLcolor = ZO_HIGHLIGHT_TEXT @@ -30,115 +30,113 @@ local checkboxHLcolor = ZO_HIGHLIGHT_TEXT local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end - control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA()) - control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA()) - --control:SetMouseEnabled(not disable) - --control:SetMouseEnabled(true) + control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA()) + control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA()) + --control:SetMouseEnabled(not disable) + --control:SetMouseEnabled(true) - control.isDisabled = disable + control.isDisabled = disable end local function ToggleCheckbox(control) - if control.value then - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.checkbox:SetText(control.checkedText) - else - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.checkbox:SetText(control.uncheckedText) - end + if control.value then + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.checkbox:SetText(control.checkedText) + else + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.checkbox:SetText(control.uncheckedText) + end end local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - elseif value ~= nil then --our value could be false - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - end - control.value = value + if forceDefault then --if we are forcing defaults + value = LAM.util.GetDefaultValue(control.data.default) + control.data.setFunc(value) + elseif value ~= nil then --our value could be false + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + LAM.util.RequestRefreshIfNeeded(control) + else + value = control.data.getFunc() + end + control.value = value - ToggleCheckbox(control) + ToggleCheckbox(control) end local function OnMouseEnter(control) - ZO_Options_OnMouseEnter(control) + ZO_Options_OnMouseEnter(control) - if control.isDisabled then return end + if control.isDisabled then return end - local label = control.label - if control.value then - label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) - else - label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) - end - control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) + local label = control.label + if control.value then + label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) + else + label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) + end + control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA()) end local function OnMouseExit(control) - ZO_Options_OnMouseExit(control) + ZO_Options_OnMouseExit(control) - if control.isDisabled then return end + if control.isDisabled then return end - local label = control.label - if control.value then - label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - else - label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - end - control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) + local label = control.label + if control.value then + label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + else + label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + end + control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) end --controlName is optional function LAMCreateControl.checkbox(parent, checkboxData, controlName) - local control = LAM.util.CreateLabelAndContainerControl(parent, checkboxData, controlName) - control:SetHandler("OnMouseEnter", OnMouseEnter) - control:SetHandler("OnMouseExit", OnMouseExit) - control:SetHandler("OnMouseUp", function(control) - if control.isDisabled then return end - PlaySound(SOUNDS.DEFAULT_CLICK) - control.value = not control.value - control:UpdateValue(false, control.value) - end) + local control = LAM.util.CreateLabelAndContainerControl(parent, checkboxData, controlName) + control:SetHandler("OnMouseEnter", OnMouseEnter) + control:SetHandler("OnMouseExit", OnMouseExit) + control:SetHandler("OnMouseUp", function(control) + if control.isDisabled then return end + PlaySound(SOUNDS.DEFAULT_CLICK) + control.value = not control.value + control:UpdateValue(false, control.value) + end) - control.checkbox = wm:CreateControl(nil, control.container, CT_LABEL) - local checkbox = control.checkbox - checkbox:SetAnchor(LEFT, control.container, LEFT, 0, 0) - checkbox:SetFont("ZoFontGameBold") - checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) - control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper() - control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper() + control.checkbox = wm:CreateControl(nil, control.container, CT_LABEL) + local checkbox = control.checkbox + checkbox:SetAnchor(LEFT, control.container, LEFT, 0, 0) + checkbox:SetFont("ZoFontGameBold") + checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA()) + control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper() + control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper() - if checkboxData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) - control.warning.data = {tooltipText = checkboxData.warning} - end + if checkboxData.warning ~= nil or checkboxData.requiresReload then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end - control.data.tooltipText = LAM.util.GetTooltipText(checkboxData.tooltip) + control.data.tooltipText = LAM.util.GetStringFromValue(checkboxData.tooltip) - if checkboxData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() + control.UpdateValue = UpdateValue + control:UpdateValue() + if checkboxData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + LAM.util.RegisterForRefreshIfNeeded(control) + LAM.util.RegisterForReloadIfNeeded(control) - return control -end \ No newline at end of file + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/colorpicker.lua b/Libs/LibAddonMenu-2.0/controls/colorpicker.lua index 011b4b5..db21260 100644 --- a/Libs/LibAddonMenu-2.0/controls/colorpicker.lua +++ b/Libs/LibAddonMenu-2.0/controls/colorpicker.lua @@ -1,110 +1,106 @@ --[[colorpickerData = { - type = "colorpicker", - name = "My Color Picker", - tooltip = "Color Picker's tooltip text.", - getFunc = function() return db.r, db.g, db.b, db.a end, --(alpha is optional) - setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end, --(alpha is optional) - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = {r = defaults.r, g = defaults.g, b = defaults.b, a = defaults.a}, --(optional) table of default color values (or default = defaultColor, where defaultColor is a table with keys of r, g, b[, a]) - reference = "MyAddonColorpicker" --(optional) unique global reference to control -} ]] + type = "colorpicker", + name = "My Color Picker", -- or string id or function returning a string + getFunc = function() return db.r, db.g, db.b, db.a end, --(alpha is optional) + setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end, --(alpha is optional) + tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional) + requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional) + default = {r = defaults.r, g = defaults.g, b = defaults.b, a = defaults.a}, --(optional) table of default color values (or default = defaultColor, where defaultColor is a table with keys of r, g, b[, a]) or a function that returns the color + reference = "MyAddonColorpicker" -- unique global reference to control (optional) +} ]] -local widgetVersion = 7 +local widgetVersion = 13 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end - control.isDisabled = disable + control.isDisabled = disable end local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA) - if forceDefault then --if we are forcing defaults - local color = control.data.default - valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a - control.data.setFunc(valueR, valueG, valueB, valueA) - elseif valueR and valueG and valueB then - control.data.setFunc(valueR, valueG, valueB, valueA or 1) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - valueR, valueG, valueB, valueA = control.data.getFunc() - end + if forceDefault then --if we are forcing defaults + local color = LAM.util.GetDefaultValue(control.data.default) + valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a + control.data.setFunc(valueR, valueG, valueB, valueA) + elseif valueR and valueG and valueB then + control.data.setFunc(valueR, valueG, valueB, valueA or 1) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + LAM.util.RequestRefreshIfNeeded(control) + else + valueR, valueG, valueB, valueA = control.data.getFunc() + end - control.thumb:SetColor(valueR, valueG, valueB, valueA or 1) + control.thumb:SetColor(valueR, valueG, valueB, valueA or 1) end function LAMCreateControl.colorpicker(parent, colorpickerData, controlName) - local control = LAM.util.CreateLabelAndContainerControl(parent, colorpickerData, controlName) + local control = LAM.util.CreateLabelAndContainerControl(parent, colorpickerData, controlName) - control.color = control.container - local color = control.color + control.color = control.container + local color = control.color - control.thumb = wm:CreateControl(nil, color, CT_TEXTURE) - local thumb = control.thumb - thumb:SetDimensions(36, 18) - thumb:SetAnchor(LEFT, color, LEFT, 4, 0) + control.thumb = wm:CreateControl(nil, color, CT_TEXTURE) + local thumb = control.thumb + thumb:SetDimensions(36, 18) + thumb:SetAnchor(LEFT, color, LEFT, 4, 0) - color.border = wm:CreateControl(nil, color, CT_TEXTURE) - local border = color.border - border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds") - border:SetTextureCoords(0, .625, 0, .8125) - border:SetDimensions(40, 22) - border:SetAnchor(CENTER, thumb, CENTER, 0, 0) + color.border = wm:CreateControl(nil, color, CT_TEXTURE) + local border = color.border + border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds") + border:SetTextureCoords(0, .625, 0, .8125) + border:SetDimensions(40, 22) + border:SetAnchor(CENTER, thumb, CENTER, 0, 0) - local function ColorPickerCallback(r, g, b, a) - control:UpdateValue(false, r, g, b, a) - end + local function ColorPickerCallback(r, g, b, a) + control:UpdateValue(false, r, g, b, a) + end - control:SetHandler("OnMouseUp", function(self, btn, upInside) - if self.isDisabled then return end + control:SetHandler("OnMouseUp", function(self, btn, upInside) + if self.isDisabled then return end - if upInside then - local r, g, b, a = colorpickerData.getFunc() - COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, colorpickerData.name) - end - end) + if upInside then + local r, g, b, a = colorpickerData.getFunc() + COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, LAM.util.GetStringFromValue(colorpickerData.name)) + end + end) - if colorpickerData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0) - control.warning.data = {tooltipText = colorpickerData.warning} - end + if colorpickerData.warning ~= nil or colorpickerData.requiresReload then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0) + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end - control.data.tooltipText = LAM.util.GetTooltipText(colorpickerData.tooltip) + control.data.tooltipText = LAM.util.GetStringFromValue(colorpickerData.tooltip) - if colorpickerData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() + control.UpdateValue = UpdateValue + control:UpdateValue() + if colorpickerData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + LAM.util.RegisterForRefreshIfNeeded(control) + LAM.util.RegisterForReloadIfNeeded(control) - return control -end \ No newline at end of file + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/custom.lua b/Libs/LibAddonMenu-2.0/controls/custom.lua index e7b7312..5d6111c 100644 --- a/Libs/LibAddonMenu-2.0/controls/custom.lua +++ b/Libs/LibAddonMenu-2.0/controls/custom.lua @@ -1,40 +1,35 @@ --[[customData = { - type = "custom", - reference = "MyAddonCustomControl", --(optional) unique name for your control to use as reference - refreshFunc = function(customControl) end, --(optional) function to call when panel/controls refresh - width = "full", --or "half" (optional) -} ]] + type = "custom", + reference = "MyAddonCustomControl", --(optional) unique name for your control to use as reference + refreshFunc = function(customControl) end, --(optional) function to call when panel/controls refresh + width = "full", --or "half" (optional) +} ]] -local widgetVersion = 6 +local widgetVersion = 7 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("custom", widgetVersion) then return end -local wm = WINDOW_MANAGER -local tinsert = table.insert - local function UpdateValue(control) - if control.data.refreshFunc then - control.data.refreshFunc(control) - end + if control.data.refreshFunc then + control.data.refreshFunc(control) + end end local MIN_HEIGHT = 26 function LAMCreateControl.custom(parent, customData, controlName) - local control = LAM.util.CreateBaseControl(parent, customData, controlName) - local width = control:GetWidth() - control:SetResizeToFitDescendents(true) + local control = LAM.util.CreateBaseControl(parent, customData, controlName) + local width = control:GetWidth() + control:SetResizeToFitDescendents(true) - if control.isHalfWidth then --note these restrictions - control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4) - else - control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4) - end + if control.isHalfWidth then --note these restrictions + control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4) + else + control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4) + end - control.UpdateValue = UpdateValue + control.UpdateValue = UpdateValue - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + LAM.util.RegisterForRefreshIfNeeded(control) - return control -end \ No newline at end of file + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/description.lua b/Libs/LibAddonMenu-2.0/controls/description.lua index 1929d5a..27c7192 100644 --- a/Libs/LibAddonMenu-2.0/controls/description.lua +++ b/Libs/LibAddonMenu-2.0/controls/description.lua @@ -1,64 +1,60 @@ --[[descriptionData = { - type = "description", - title = "My Title", --(optional) - text = "My description text to display.", - width = "full", --or "half" (optional) - reference = "MyAddonDescription" --(optional) unique global reference to control -} ]] + type = "description", + text = "My description text to display.", -- or string id or function returning a string + title = "My Title", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + reference = "MyAddonDescription" -- unique global reference to control (optional) +} ]] -local widgetVersion = 6 +local widgetVersion = 8 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("description", widgetVersion) then return end local wm = WINDOW_MANAGER -local tinsert = table.insert local function UpdateValue(control) - if control.title then - control.title:SetText(control.data.title) - end - control.desc:SetText(control.data.text) + if control.title then + control.title:SetText(LAM.util.GetStringFromValue(control.data.title)) + end + control.desc:SetText(LAM.util.GetStringFromValue(control.data.text)) end -local MIN_HEIGHT = 26 function LAMCreateControl.description(parent, descriptionData, controlName) - local control = LAM.util.CreateBaseControl(parent, descriptionData, controlName) - local isHalfWidth = control.isHalfWidth - local width = control:GetWidth() - control:SetResizeToFitDescendents(true) + local control = LAM.util.CreateBaseControl(parent, descriptionData, controlName) + local isHalfWidth = control.isHalfWidth + local width = control:GetWidth() + control:SetResizeToFitDescendents(true) - if isHalfWidth then - control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4) - else - control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4) - end + if isHalfWidth then + control:SetDimensionConstraints(width / 2, 0, width / 2, 0) + else + control:SetDimensionConstraints(width, 0, width, 0) + end - control.desc = wm:CreateControl(nil, control, CT_LABEL) - local desc = control.desc - desc:SetVerticalAlignment(TEXT_ALIGN_TOP) - desc:SetFont("ZoFontGame") - desc:SetText(descriptionData.text) - desc:SetWidth(isHalfWidth and width / 2 or width) + control.desc = wm:CreateControl(nil, control, CT_LABEL) + local desc = control.desc + desc:SetVerticalAlignment(TEXT_ALIGN_TOP) + desc:SetFont("ZoFontGame") + desc:SetText(LAM.util.GetStringFromValue(descriptionData.text)) + desc:SetWidth(isHalfWidth and width / 2 or width) - if descriptionData.title then - control.title = wm:CreateControl(nil, control, CT_LABEL) - local title = control.title - title:SetWidth(isHalfWidth and width / 2 or width) - title:SetAnchor(TOPLEFT, control, TOPLEFT) - title:SetFont("ZoFontWinH4") - title:SetText(descriptionData.title) - desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT) - else - desc:SetAnchor(TOPLEFT) - end + if descriptionData.title then + control.title = wm:CreateControl(nil, control, CT_LABEL) + local title = control.title + title:SetWidth(isHalfWidth and width / 2 or width) + title:SetAnchor(TOPLEFT, control, TOPLEFT) + title:SetFont("ZoFontWinH4") + title:SetText(LAM.util.GetStringFromValue(descriptionData.title)) + desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT) + else + desc:SetAnchor(TOPLEFT) + end - control.UpdateValue = UpdateValue + control.UpdateValue = UpdateValue - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + LAM.util.RegisterForRefreshIfNeeded(control) - return control + return control -end \ No newline at end of file +end diff --git a/Libs/LibAddonMenu-2.0/controls/divider.lua b/Libs/LibAddonMenu-2.0/controls/divider.lua new file mode 100644 index 0000000..b24e2fc --- /dev/null +++ b/Libs/LibAddonMenu-2.0/controls/divider.lua @@ -0,0 +1,45 @@ +--[[dividerData = { + type = "divider", + width = "full", --or "half" (optional) + height = 10, (optional) + alpha = 0.25, (optional) + reference = "MyAddonDivider" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 2 +local LAM = LibStub("LibAddonMenu-2.0") +if not LAM:RegisterWidget("divider", widgetVersion) then return end + +local wm = WINDOW_MANAGER + +local MIN_HEIGHT = 10 +local MAX_HEIGHT = 50 +local MIN_ALPHA = 0 +local MAX_ALPHA = 1 +local DEFAULT_ALPHA = 0.25 + +local function GetValueInRange(value, min, max, default) + if not value or type(value) ~= "number" then + return default + end + return math.min(math.max(min, value), max) +end + +function LAMCreateControl.divider(parent, dividerData, controlName) + local control = LAM.util.CreateBaseControl(parent, dividerData, controlName) + local isHalfWidth = control.isHalfWidth + local width = control:GetWidth() + local height = GetValueInRange(dividerData.height, MIN_HEIGHT, MAX_HEIGHT, MIN_HEIGHT) + local alpha = GetValueInRange(dividerData.alpha, MIN_ALPHA, MAX_ALPHA, DEFAULT_ALPHA) + + control:SetDimensions(isHalfWidth and width / 2 or width, height) + + control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider") + local divider = control.divider + divider:SetWidth(isHalfWidth and width / 2 or width) + divider:SetAnchor(TOPLEFT) + divider:SetAlpha(alpha) + + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/dropdown.lua b/Libs/LibAddonMenu-2.0/controls/dropdown.lua index 0731e94..c67624a 100644 --- a/Libs/LibAddonMenu-2.0/controls/dropdown.lua +++ b/Libs/LibAddonMenu-2.0/controls/dropdown.lua @@ -1,131 +1,387 @@ --[[dropdownData = { - type = "dropdown", - name = "My Dropdown", - tooltip = "Dropdown's tooltip text.", - choices = {"table", "of", "choices"}, - sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted - getFunc = function() return db.var end, - setFunc = function(var) db.var = var doStuff() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonDropdown" --(optional) unique global reference to control -} ]] + type = "dropdown", + name = "My Dropdown", -- or string id or function returning a string + choices = {"table", "of", "choices"}, + choicesValues = {"foo", 2, "three"}, -- if specified, these values will get passed to setFunc instead (optional) + getFunc = function() return db.var end, + setFunc = function(var) db.var = var doStuff() end, + tooltip = "Dropdown's tooltip text.", -- or string id or function returning a string (optional) + choicesTooltips = {"tooltip 1", "tooltip 2", "tooltip 3"}, -- or array of string ids or array of functions returning a string (optional) + sort = "name-up", --or "name-down", "numeric-up", "numeric-down", "value-up", "value-down", "numericvalue-up", "numericvalue-down" (optional) - if not provided, list will not be sorted + width = "full", --or "half" (optional) + scrollable = true, -- boolean or number, if set the dropdown will feature a scroll bar if there are a large amount of choices and limit the visible lines to the specified number or 10 if true is used (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional) + requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional) + default = defaults.var, -- default value or function that returns the default value (optional) + reference = "MyAddonDropdown" -- unique global reference to control (optional) +} ]] -local widgetVersion = 9 +local widgetVersion = 18 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("dropdown", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - +local SORT_BY_VALUE = { ["value"] = {} } +local SORT_BY_VALUE_NUMERIC = { ["value"] = { isNumeric = true } } +local SORT_TYPES = { + name = ZO_SORT_BY_NAME, + numeric = ZO_SORT_BY_NAME_NUMERIC, + value = SORT_BY_VALUE, + numericvalue = SORT_BY_VALUE_NUMERIC, +} +local SORT_ORDERS = { + up = ZO_SORT_ORDER_UP, + down = ZO_SORT_ORDER_DOWN, +} local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end - control.dropdown:SetEnabled(not disable) - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end + control.dropdown:SetEnabled(not disable) + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end end local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - control.dropdown:SetSelectedItem(value) - elseif value then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - control.dropdown:SetSelectedItem(value) - end + if forceDefault then --if we are forcing defaults + value = LAM.util.GetDefaultValue(control.data.default) + control.data.setFunc(value) + control.dropdown:SetSelectedItem(control.choices[value]) + elseif value then + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + LAM.util.RequestRefreshIfNeeded(control) + else + value = control.data.getFunc() + control.dropdown:SetSelectedItem(control.choices[value]) + end end local function DropdownCallback(control, choiceText, choice) - choice.control:UpdateValue(false, choiceText) + choice.control:UpdateValue(false, choice.value or choiceText) end -local function UpdateChoices(control, choices) - control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?) +local function SetupTooltips(comboBox, choicesTooltips) + local function ShowTooltip(control) + InitializeTooltip(InformationTooltip, control, TOPLEFT, 0, 0, BOTTOMRIGHT) + SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(control.tooltip)) + InformationTooltipTopLevel:BringWindowToTop() + end + local function HideTooltip(control) + ClearTooltip(InformationTooltip) + end - --build new list of choices - local choices = choices or control.data.choices - for i = 1, #choices do - local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback) - entry.control = control - control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort - end + -- allow for tooltips on the drop down entries + local originalShow = comboBox.ShowDropdownInternal + comboBox.ShowDropdownInternal = function(comboBox) + originalShow(comboBox) + local entries = ZO_Menu.items + for i = 1, #entries do + local entry = entries[i] + local control = entries[i].item + control.tooltip = choicesTooltips[i] + entry.onMouseEnter = control:GetHandler("OnMouseEnter") + entry.onMouseExit = control:GetHandler("OnMouseExit") + ZO_PreHookHandler(control, "OnMouseEnter", ShowTooltip) + ZO_PreHookHandler(control, "OnMouseExit", HideTooltip) + end + end + + local originalHide = comboBox.HideDropdownInternal + comboBox.HideDropdownInternal = function(self) + local entries = ZO_Menu.items + for i = 1, #entries do + local entry = entries[i] + local control = entries[i].item + control:SetHandler("OnMouseEnter", entry.onMouseEnter) + control:SetHandler("OnMouseExit", entry.onMouseExit) + control.tooltip = nil + end + originalHide(self) + end +end + +local function UpdateChoices(control, choices, choicesValues, choicesTooltips) + control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?) + ZO_ClearTable(control.choices) + + --build new list of choices + local choices = choices or control.data.choices + local choicesValues = choicesValues or control.data.choicesValues + local choicesTooltips = choicesTooltips or control.data.choicesTooltips + + if choicesValues then + assert(#choices == #choicesValues, "choices and choicesValues need to have the same size") + end + + if choicesTooltips then + assert(#choices == #choicesTooltips, "choices and choicesTooltips need to have the same size") + if not control.scrollHelper then -- only do this for non-scrollable + SetupTooltips(control.dropdown, choicesTooltips) + end + end + + for i = 1, #choices do + local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback) + entry.control = control + if choicesValues then + entry.value = choicesValues[i] + end + if choicesTooltips and control.scrollHelper then + entry.tooltip = choicesTooltips[i] + end + control.choices[entry.value or entry.name] = entry.name + control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort + end end local function GrabSortingInfo(sortInfo) - local t, i = {}, 1 - for info in string.gmatch(sortInfo, "([^%-]+)") do - t[i] = info - i = i + 1 - end + local t, i = {}, 1 + for info in string.gmatch(sortInfo, "([^%-]+)") do + t[i] = info + i = i + 1 + end - return t + return t +end + +local DEFAULT_VISIBLE_ROWS = 10 +local SCROLLABLE_ENTRY_TEMPLATE_HEIGHT = 25 -- same as in zo_combobox.lua +local CONTENT_PADDING = 24 +local SCROLLBAR_PADDING = 16 +local PADDING = GetMenuPadding() / 2 -- half the amount looks closer to the regular dropdown +local ROUNDING_MARGIN = 0.01 -- needed to avoid rare issue with too many anchors processed +local ScrollableDropdownHelper = ZO_Object:Subclass() + +function ScrollableDropdownHelper:New(...) + local object = ZO_Object.New(self) + object:Initialize(...) + return object +end + +function ScrollableDropdownHelper:Initialize(parent, control, visibleRows) + local combobox = control.combobox + local dropdown = control.dropdown + self.parent = parent + self.control = control + self.combobox = combobox + self.dropdown = dropdown + self.visibleRows = visibleRows + + -- clear anchors so we can adjust the width dynamically + dropdown.m_dropdown:ClearAnchors() + dropdown.m_dropdown:SetAnchor(TOPLEFT, combobox, BOTTOMLEFT) + + -- handle dropdown or settingsmenu opening/closing + local function onShow() self:OnShow() end + local function onHide() self:OnHide() end + local function doHide() self:DoHide() end + + ZO_PreHook(dropdown, "ShowDropdownOnMouseUp", onShow) + ZO_PreHook(dropdown, "HideDropdownInternal", onHide) + combobox:SetHandler("OnEffectivelyHidden", onHide) + parent:SetHandler("OnEffectivelyHidden", doHide) + + -- dont fade entries near the edges + local scrollList = dropdown.m_scroll + scrollList.selectionTemplate = nil + scrollList.highlightTemplate = nil + ZO_ScrollList_EnableSelection(scrollList, "ZO_SelectionHighlight") + ZO_ScrollList_EnableHighlight(scrollList, "ZO_SelectionHighlight") + ZO_Scroll_SetUseFadeGradient(scrollList, false) + + -- adjust scroll content anchor to mimic menu padding + local scroll = dropdown.m_dropdown:GetNamedChild("Scroll") + local anchor1 = {scroll:GetAnchor(0)} + local anchor2 = {scroll:GetAnchor(1)} + scroll:ClearAnchors() + scroll:SetAnchor(anchor1[2], anchor1[3], anchor1[4], anchor1[5] + PADDING, anchor1[6] + PADDING) + scroll:SetAnchor(anchor2[2], anchor2[3], anchor2[4], anchor2[5] - PADDING, anchor2[6] - PADDING) + ZO_ScrollList_Commit(scrollList) + + -- hook mouse enter/exit + local function onMouseEnter(control) self:OnMouseEnter(control) end + local function onMouseExit(control) self:OnMouseExit(control) end + + -- adjust row setup to mimic the highlight padding + local dataType1 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 1) + local dataType2 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 2) + local oSetup = dataType1.setupCallback -- both types have the same setup function + local function SetupEntry(control, data, list) + oSetup(control, data, list) + control.m_label:SetAnchor(LEFT, nil, nil, 2) + -- no need to store old ones since we have full ownership of our dropdown controls + if not control.hookedMouseHandlers then --only do it once per control + control.hookedMouseHandlers = true + ZO_PreHookHandler(control, "OnMouseEnter", onMouseEnter) + ZO_PreHookHandler(control, "OnMouseExit", onMouseExit) + -- we could also just replace the handlers + --control:SetHandler("OnMouseEnter", onMouseEnter) + --control:SetHandler("OnMouseExit", onMouseExit) + end + end + dataType1.setupCallback = SetupEntry + dataType2.setupCallback = SetupEntry + + -- adjust dimensions based on entries + local scrollContent = scroll:GetNamedChild("Contents") + ZO_PreHook(dropdown, "AddMenuItems", function() + local width = PADDING * 2 + zo_max(self:GetMaxWidth(), combobox:GetWidth()) + local numItems = #dropdown.m_sortedItems + local anchorOffset = 0 + if(numItems > self.visibleRows) then + width = width + CONTENT_PADDING + SCROLLBAR_PADDING + anchorOffset = -SCROLLBAR_PADDING + numItems = self.visibleRows + end + scrollContent:SetAnchor(BOTTOMRIGHT, nil, nil, anchorOffset) + local height = PADDING * 2 + numItems * (SCROLLABLE_ENTRY_TEMPLATE_HEIGHT + dropdown.m_spacing) - dropdown.m_spacing + ROUNDING_MARGIN + dropdown.m_dropdown:SetWidth(width) + dropdown.m_dropdown:SetHeight(height) + end) +end + +function ScrollableDropdownHelper:OnShow() + local dropdown = self.dropdown + if dropdown.m_lastParent ~= ZO_Menus then + dropdown.m_lastParent = dropdown.m_dropdown:GetParent() + dropdown.m_dropdown:SetParent(ZO_Menus) + ZO_Menus:BringWindowToTop() + end +end + +function ScrollableDropdownHelper:OnHide() + local dropdown = self.dropdown + if dropdown.m_lastParent then + dropdown.m_dropdown:SetParent(dropdown.m_lastParent) + dropdown.m_lastParent = nil + end +end + +function ScrollableDropdownHelper:DoHide() + local dropdown = self.dropdown + if dropdown:IsDropdownVisible() then + dropdown:HideDropdown() + end +end + +function ScrollableDropdownHelper:GetMaxWidth() + local dropdown = self.dropdown + local dataType = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 1) + + local dummy = dataType.pool:AcquireObject() + dataType.setupCallback(dummy, { + m_owner = dropdown, + name = "Dummy" + }, dropdown) + + local maxWidth = 0 + local label = dummy.m_label + local entries = dropdown.m_sortedItems + local numItems = #entries + for index = 1, numItems do + label:SetText(entries[index].name) + local width = label:GetTextWidth() + if (width > maxWidth) then + maxWidth = width + end + end + + dataType.pool:ReleaseObject(dummy.key) + return maxWidth +end + +function ScrollableDropdownHelper:OnMouseEnter(control) + -- call original code if we replace instead of hook the handler + --ZO_ScrollableComboBox_Entry_OnMouseEnter(control) + -- show tooltip + if control.m_data.tooltip then + InitializeTooltip(InformationTooltip, control, TOPLEFT, 0, 0, BOTTOMRIGHT) + SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(control.m_data.tooltip)) + InformationTooltipTopLevel:BringWindowToTop() + end +end +function ScrollableDropdownHelper:OnMouseExit(control) + -- call original code if we replace instead of hook the handler + --ZO_ScrollableComboBox_Entry_OnMouseExit(control) + -- hide tooltip + if control.m_data.tooltip then + ClearTooltip(InformationTooltip) + end end function LAMCreateControl.dropdown(parent, dropdownData, controlName) - local control = LAM.util.CreateLabelAndContainerControl(parent, dropdownData, controlName) + local control = LAM.util.CreateLabelAndContainerControl(parent, dropdownData, controlName) + control.choices = {} - local countControl = parent - local name = parent:GetName() - if not name or #name == 0 then - countControl = LAMCreateControl - name = "LAM" - end - local comboboxCount = (countControl.comboboxCount or 0) + 1 - countControl.comboboxCount = comboboxCount - control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, "ZO_ComboBox") + local countControl = parent + local name = parent:GetName() + if not name or #name == 0 then + countControl = LAMCreateControl + name = "LAM" + end + local comboboxCount = (countControl.comboboxCount or 0) + 1 + countControl.comboboxCount = comboboxCount + control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, dropdownData.scrollable and "ZO_ScrollableComboBox" or "ZO_ComboBox") - local combobox = control.combobox - combobox:SetAnchor(TOPLEFT) - combobox:SetDimensions(control.container:GetDimensions()) - combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) - control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox) - local dropdown = control.dropdown - if dropdownData.sort then - local sortInfo = GrabSortingInfo(dropdownData.sort) - local sortType, sortOrder = sortInfo[1], sortInfo[2] - dropdown:SetSortOrder(sortOrder == "up" and ZO_SORT_ORDER_UP or ZO_SORT_ORDER_DOWN, sortType == "name" and ZO_SORT_BY_NAME or ZO_SORT_BY_NAME_NUMERIC) - end + local combobox = control.combobox + combobox:SetAnchor(TOPLEFT) + combobox:SetDimensions(control.container:GetDimensions()) + combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) + control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox) + local dropdown = control.dropdown + dropdown:SetSortsItems(false) -- need to sort ourselves in order to be able to sort by value - if dropdownData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0) - control.warning.data = {tooltipText = dropdownData.warning} - end + if dropdownData.scrollable then + local visibleRows = type(dropdownData.scrollable) == "number" and dropdownData.scrollable or DEFAULT_VISIBLE_ROWS + control.scrollHelper = ScrollableDropdownHelper:New(parent, control, visibleRows) + end - if dropdownData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateChoices = UpdateChoices - control:UpdateChoices(dropdownData.choices) - control.UpdateValue = UpdateValue - control:UpdateValue() + ZO_PreHook(dropdown, "UpdateItems", function(self) + assert(not self.m_sortsItems, "built-in dropdown sorting was reactivated, sorting is handled by LAM") + if control.m_sortOrder ~= nil and control.m_sortType then + local sortKey = next(control.m_sortType) + local sortFunc = function(item1, item2) return ZO_TableOrderingFunction(item1, item2, sortKey, control.m_sortType, control.m_sortOrder) end + table.sort(self.m_sortedItems, sortFunc) + end + end) - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + if dropdownData.sort then + local sortInfo = GrabSortingInfo(dropdownData.sort) + control.m_sortType, control.m_sortOrder = SORT_TYPES[sortInfo[1]], SORT_ORDERS[sortInfo[2]] + elseif dropdownData.choicesValues then + control.m_sortType, control.m_sortOrder = ZO_SORT_ORDER_UP, SORT_BY_VALUE + end - return control -end \ No newline at end of file + if dropdownData.warning ~= nil or dropdownData.requiresReload then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0) + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end + + control.UpdateChoices = UpdateChoices + control:UpdateChoices(dropdownData.choices, dropdownData.choicesValues) + control.UpdateValue = UpdateValue + control:UpdateValue() + if dropdownData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + + LAM.util.RegisterForRefreshIfNeeded(control) + LAM.util.RegisterForReloadIfNeeded(control) + + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/editbox.lua b/Libs/LibAddonMenu-2.0/controls/editbox.lua index 78e7683..bcc6a7c 100644 --- a/Libs/LibAddonMenu-2.0/controls/editbox.lua +++ b/Libs/LibAddonMenu-2.0/controls/editbox.lua @@ -1,136 +1,156 @@ --[[editboxData = { - type = "editbox", - name = "My Editbox", - tooltip = "Editbox's tooltip text.", - getFunc = function() return db.text end, - setFunc = function(text) db.text = text doStuff() end, - isMultiline = true, --boolean - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.text, --(optional) - reference = "MyAddonEditbox" --(optional) unique global reference to control -} ]] + type = "editbox", + name = "My Editbox", -- or string id or function returning a string + getFunc = function() return db.text end, + setFunc = function(text) db.text = text doStuff() end, + tooltip = "Editbox's tooltip text.", -- or string id or function returning a string (optional) + isMultiline = true, --boolean (optional) + isExtraWide = true, --boolean (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional) + requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional) + default = defaults.text, -- default value or function that returns the default value (optional) + reference = "MyAddonEditbox" -- unique global reference to control (optional) +} ]] -local widgetVersion = 8 +local widgetVersion = 14 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("editbox", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert - local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end - --control.editbox:SetEditEnabled(not disable) - control.editbox:SetMouseEnabled(not disable) + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end + --control.editbox:SetEditEnabled(not disable) + control.editbox:SetMouseEnabled(not disable) end local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - control.editbox:SetText(value) - elseif value then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - control.editbox:SetText(value) - end + if forceDefault then --if we are forcing defaults + value = LAM.util.GetDefaultValue(control.data.default) + control.data.setFunc(value) + control.editbox:SetText(value) + elseif value then + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + LAM.util.RequestRefreshIfNeeded(control) + else + value = control.data.getFunc() + control.editbox:SetText(value) + end end -local MIN_HEIGHT = 26 +local MIN_HEIGHT = 24 local HALF_WIDTH_LINE_SPACING = 2 function LAMCreateControl.editbox(parent, editboxData, controlName) - local control = LAM.util.CreateLabelAndContainerControl(parent, editboxData, controlName) + local control = LAM.util.CreateLabelAndContainerControl(parent, editboxData, controlName) - local container = control.container - control.bg = wm:CreateControlFromVirtual(nil, container, "ZO_EditBackdrop") - local bg = control.bg - bg:SetAnchorFill() + local container = control.container + control.bg = wm:CreateControlFromVirtual(nil, container, "ZO_EditBackdrop") + local bg = control.bg + bg:SetAnchorFill() - if editboxData.isMultiline then - control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop") - control.editbox:SetHandler("OnMouseWheel", function(self, delta) - if self:HasFocus() then --only set focus to new spots if the editbox is currently in use - local cursorPos = self:GetCursorPosition() - local text = self:GetText() - local textLen = text:len() - local newPos - if delta > 0 then --scrolling up - local reverseText = text:reverse() - local revCursorPos = textLen - cursorPos - local revPos = reverseText:find("\n", revCursorPos+1) - newPos = revPos and textLen - revPos - else --scrolling down - newPos = text:find("\n", cursorPos+1) - end - if newPos then --if we found a new line, then scroll, otherwise don't - self:SetCursorPosition(newPos) - end - end - end) - else - control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop") - end - local editbox = control.editbox - editbox:SetText(editboxData.getFunc()) - editbox:SetMaxInputChars(3000) - editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end) - editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end) - editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) + if editboxData.isMultiline then + control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop") + control.editbox:SetHandler("OnMouseWheel", function(self, delta) + if self:HasFocus() then --only set focus to new spots if the editbox is currently in use + local cursorPos = self:GetCursorPosition() + local text = self:GetText() + local textLen = text:len() + local newPos + if delta > 0 then --scrolling up + local reverseText = text:reverse() + local revCursorPos = textLen - cursorPos + local revPos = reverseText:find("\n", revCursorPos+1) + newPos = revPos and textLen - revPos + else --scrolling down + newPos = text:find("\n", cursorPos+1) + end + if newPos then --if we found a new line, then scroll, otherwise don't + self:SetCursorPosition(newPos) + end + end + end) + else + control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop") + end + local editbox = control.editbox + editbox:SetText(editboxData.getFunc()) + editbox:SetMaxInputChars(3000) + editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end) + editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end) + editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) - if not editboxData.isMultiline then - container:SetHeight(24) - else - local width = container:GetWidth() - local height = control.isHalfWidth and 74 or 100 - container:SetHeight(height) - editbox:SetDimensionConstraints(width, height, width, 500) + local MIN_WIDTH = (parent.GetWidth and (parent:GetWidth() / 10)) or (parent.panel.GetWidth and (parent.panel:GetWidth() / 10)) or 0 - if control.lineControl then - control.lineControl:SetHeight(MIN_HEIGHT + height + HALF_WIDTH_LINE_SPACING) - else - control:SetHeight(height) - end - end + control.label:ClearAnchors() + container:ClearAnchors() - if editboxData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0) - control.warning.data = {tooltipText = editboxData.warning} - end + control.label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0) + container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0) - if editboxData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() + if control.isHalfWidth then + container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0) + end - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + if editboxData.isExtraWide then + container:SetAnchor(BOTTOMLEFT, control, BOTTOMLEFT, 0, 0) + else + container:SetWidth(MIN_WIDTH * 3.2) + end - return control -end \ No newline at end of file + if editboxData.isMultiline then + container:SetHeight(MIN_HEIGHT * 3) + else + container:SetHeight(MIN_HEIGHT) + end + + if control.isHalfWidth ~= true and editboxData.isExtraWide ~= true then + control:SetHeight(container:GetHeight()) + else + control:SetHeight(container:GetHeight() + control.label:GetHeight()) + end + + editbox:ClearAnchors() + editbox:SetAnchor(TOPLEFT, container, TOPLEFT, 2, 2) + editbox:SetAnchor(BOTTOMRIGHT, container, BOTTOMRIGHT, -2, -2) + + if editboxData.warning ~= nil or editboxData.requiresReload then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + if editboxData.isExtraWide then + control.warning:SetAnchor(BOTTOMRIGHT, control.bg, TOPRIGHT, 2, 0) + else + control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0) + end + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end + + control.UpdateValue = UpdateValue + control:UpdateValue() + if editboxData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + + LAM.util.RegisterForRefreshIfNeeded(control) + LAM.util.RegisterForReloadIfNeeded(control) + + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/header.lua b/Libs/LibAddonMenu-2.0/controls/header.lua index 266ac55..3290c89 100644 --- a/Libs/LibAddonMenu-2.0/controls/header.lua +++ b/Libs/LibAddonMenu-2.0/controls/header.lua @@ -1,45 +1,42 @@ --[[headerData = { - type = "header", - name = "My Header", - width = "full", --or "half" (optional) - reference = "MyAddonHeader" --(optional) unique global reference to control -} ]] + type = "header", + name = "My Header", -- or string id or function returning a string + width = "full", --or "half" (optional) + reference = "MyAddonHeader" -- unique global reference to control (optional) +} ]] -local widgetVersion = 6 +local widgetVersion = 8 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("header", widgetVersion) then return end local wm = WINDOW_MANAGER -local tinsert = table.insert local function UpdateValue(control) - control.header:SetText(control.data.name) + control.header:SetText(LAM.util.GetStringFromValue(control.data.name)) end local MIN_HEIGHT = 30 function LAMCreateControl.header(parent, headerData, controlName) - local control = LAM.util.CreateBaseControl(parent, headerData, controlName) - local isHalfWidth = control.isHalfWidth - local width = control:GetWidth() - control:SetDimensions(isHalfWidth and width / 2 or width, MIN_HEIGHT) + local control = LAM.util.CreateBaseControl(parent, headerData, controlName) + local isHalfWidth = control.isHalfWidth + local width = control:GetWidth() + control:SetDimensions(isHalfWidth and width / 2 or width, MIN_HEIGHT) - control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider") - local divider = control.divider - divider:SetWidth(isHalfWidth and width / 2 or width) - divider:SetAnchor(TOPLEFT) + control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider") + local divider = control.divider + divider:SetWidth(isHalfWidth and width / 2 or width) + divider:SetAnchor(TOPLEFT) - control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") - local header = control.header - header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT) - header:SetAnchor(BOTTOMRIGHT) - header:SetText(headerData.name) + control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") + local header = control.header + header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT) + header:SetAnchor(BOTTOMRIGHT) + header:SetText(LAM.util.GetStringFromValue(headerData.name)) - control.UpdateValue = UpdateValue + control.UpdateValue = UpdateValue - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + LAM.util.RegisterForRefreshIfNeeded(control) - return control -end \ No newline at end of file + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/iconpicker.lua b/Libs/LibAddonMenu-2.0/controls/iconpicker.lua index 1c34222..3485740 100644 --- a/Libs/LibAddonMenu-2.0/controls/iconpicker.lua +++ b/Libs/LibAddonMenu-2.0/controls/iconpicker.lua @@ -1,441 +1,436 @@ --[[iconpickerData = { - type = "iconpicker", - name = "My Icon Picker", - tooltip = "Color Picker's tooltip text.", - choices = {"texture path 1", "texture path 2", "texture path 3"}, - choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, --(optional) - getFunc = function() return db.var end, - setFunc = function(var) db.var = var doStuff() end, - maxColumns = 5, --(optional) number of icons in one row - visibleRows = 4.5, --(optional) number of visible rows - iconSize = 28, --(optional) size of the icons - defaultColor = ZO_ColorDef:New("FFFFFF"), --(optional) default color of the icons - width = "full", --or "half" (optional) - beforeShow = function(control, iconPicker) return preventShow end, --(optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonIconPicker" --(optional) unique global reference to control -} ]] + type = "iconpicker", + name = "My Icon Picker", -- or string id or function returning a string + choices = {"texture path 1", "texture path 2", "texture path 3"}, + getFunc = function() return db.var end, + setFunc = function(var) db.var = var doStuff() end, + tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional) + choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, -- or array of string ids or array of functions returning a string (optional) + maxColumns = 5, -- number of icons in one row (optional) + visibleRows = 4.5, -- number of visible rows (optional) + iconSize = 28, -- size of the icons (optional) + defaultColor = ZO_ColorDef:New("FFFFFF"), -- default color of the icons (optional) + width = "full", --or "half" (optional) + beforeShow = function(control, iconPicker) return preventShow end, --(optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional) + requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional) + default = defaults.var, -- default value or function that returns the default value (optional) + reference = "MyAddonIconPicker" -- unique global reference to control (optional) +} ]] -local widgetVersion = 2 +local widgetVersion = 8 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("iconpicker", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local tinsert = table.insert local IconPickerMenu = ZO_Object:Subclass() local iconPicker LAM.util.GetIconPickerMenu = function() - if not iconPicker then - iconPicker = IconPickerMenu:New("LAMIconPicker") - local sceneFragment = LAM:GetAddonSettingsFragment() - ZO_PreHook(sceneFragment, "OnHidden", function() - if not iconPicker.control:IsHidden() then - iconPicker:Clear() - end - end) - end - return iconPicker + if not iconPicker then + iconPicker = IconPickerMenu:New("LAMIconPicker") + local sceneFragment = LAM:GetAddonSettingsFragment() + ZO_PreHook(sceneFragment, "OnHidden", function() + if not iconPicker.control:IsHidden() then + iconPicker:Clear() + end + end) + end + return iconPicker end function IconPickerMenu:New(...) - local object = ZO_Object.New(self) - object:Initialize(...) - return object + local object = ZO_Object.New(self) + object:Initialize(...) + return object end function IconPickerMenu:Initialize(name) - local control = wm:CreateTopLevelWindow(name) - control:SetDrawTier(DT_HIGH) - control:SetHidden(true) - self.control = control + local control = wm:CreateTopLevelWindow(name) + control:SetDrawTier(DT_HIGH) + control:SetHidden(true) + self.control = control - local scrollContainer = wm:CreateControlFromVirtual(name .. "ScrollContainer", control, "ZO_ScrollContainer") - -- control:SetDimensions(control.container:GetWidth(), height) -- adjust to icon size / col count - scrollContainer:SetAnchorFill() - ZO_Scroll_SetUseFadeGradient(scrollContainer, false) - ZO_Scroll_SetHideScrollbarOnDisable(scrollContainer, false) - ZO_VerticalScrollbarBase_OnMouseExit(scrollContainer:GetNamedChild("ScrollBar")) -- scrollbar initialization seems to be broken so we force it to update the correct alpha value - local scroll = GetControl(scrollContainer, "ScrollChild") - self.scroll = scroll - self.scrollContainer = scrollContainer + local scrollContainer = wm:CreateControlFromVirtual(name .. "ScrollContainer", control, "ZO_ScrollContainer") + -- control:SetDimensions(control.container:GetWidth(), height) -- adjust to icon size / col count + scrollContainer:SetAnchorFill() + ZO_Scroll_SetUseFadeGradient(scrollContainer, false) + ZO_Scroll_SetHideScrollbarOnDisable(scrollContainer, false) + ZO_VerticalScrollbarBase_OnMouseExit(scrollContainer:GetNamedChild("ScrollBar")) -- scrollbar initialization seems to be broken so we force it to update the correct alpha value + local scroll = GetControl(scrollContainer, "ScrollChild") + self.scroll = scroll + self.scrollContainer = scrollContainer - local bg = wm:CreateControl(nil, scrollContainer, CT_BACKDROP) - bg:SetAnchor(TOPLEFT, scrollContainer, TOPLEFT, 0, -3) - bg:SetAnchor(BOTTOMRIGHT, scrollContainer, BOTTOMRIGHT, 2, 5) - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) - bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds") - bg:SetInsets(16, 16, -16, -16) + local bg = wm:CreateControl(nil, scrollContainer, CT_BACKDROP) + bg:SetAnchor(TOPLEFT, scrollContainer, TOPLEFT, 0, -3) + bg:SetAnchor(BOTTOMRIGHT, scrollContainer, BOTTOMRIGHT, 2, 5) + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) + bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds") + bg:SetInsets(16, 16, -16, -16) - local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE) - mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds") - mungeOverlay:SetDrawLevel(1) - mungeOverlay:SetAddressMode(TEX_MODE_WRAP) - mungeOverlay:SetAnchorFill() + local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE) + mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds") + mungeOverlay:SetDrawLevel(1) + mungeOverlay:SetAddressMode(TEX_MODE_WRAP) + mungeOverlay:SetAnchorFill() - local mouseOver = wm:CreateControl(nil, scrollContainer, CT_TEXTURE) - mouseOver:SetDrawLevel(2) - mouseOver:SetTexture("EsoUI/Art/Buttons/minmax_mouseover.dds") - mouseOver:SetHidden(true) + local mouseOver = wm:CreateControl(nil, scrollContainer, CT_TEXTURE) + mouseOver:SetDrawLevel(2) + mouseOver:SetTexture("EsoUI/Art/Buttons/minmax_mouseover.dds") + mouseOver:SetHidden(true) - local function IconFactory(pool) - local icon = wm:CreateControl(name .. "Entry" .. pool:GetNextControlId(), scroll, CT_TEXTURE) - icon:SetMouseEnabled(true) - icon:SetDrawLevel(3) - icon:SetHandler("OnMouseEnter", function() - mouseOver:SetAnchor(TOPLEFT, icon, TOPLEFT, 0, 0) - mouseOver:SetAnchor(BOTTOMRIGHT, icon, BOTTOMRIGHT, 0, 0) - mouseOver:SetHidden(false) - if self.customOnMouseEnter then - self.customOnMouseEnter(icon) - else - self:OnMouseEnter(icon) - end - end) - icon:SetHandler("OnMouseExit", function() - mouseOver:ClearAnchors() - mouseOver:SetHidden(true) - if self.customOnMouseExit then - self.customOnMouseExit(icon) - else - self:OnMouseExit(icon) - end - end) - icon:SetHandler("OnMouseUp", function(control, ...) - PlaySound("Click") - icon.OnSelect(icon, icon.texture) - self:Clear() - end) - return icon - end + local function IconFactory(pool) + local icon = wm:CreateControl(name .. "Entry" .. pool:GetNextControlId(), scroll, CT_TEXTURE) + icon:SetMouseEnabled(true) + icon:SetDrawLevel(3) + icon:SetHandler("OnMouseEnter", function() + mouseOver:SetAnchor(TOPLEFT, icon, TOPLEFT, 0, 0) + mouseOver:SetAnchor(BOTTOMRIGHT, icon, BOTTOMRIGHT, 0, 0) + mouseOver:SetHidden(false) + if self.customOnMouseEnter then + self.customOnMouseEnter(icon) + else + self:OnMouseEnter(icon) + end + end) + icon:SetHandler("OnMouseExit", function() + mouseOver:ClearAnchors() + mouseOver:SetHidden(true) + if self.customOnMouseExit then + self.customOnMouseExit(icon) + else + self:OnMouseExit(icon) + end + end) + icon:SetHandler("OnMouseUp", function(control, ...) + PlaySound("Click") + icon.OnSelect(icon, icon.texture) + self:Clear() + end) + return icon + end - local function ResetFunction(icon) - icon:ClearAnchors() - end + local function ResetFunction(icon) + icon:ClearAnchors() + end - self.iconPool = ZO_ObjectPool:New(IconFactory, ResetFunction) - self:SetMaxColumns(1) - self.icons = {} - self.color = ZO_DEFAULT_ENABLED_COLOR + self.iconPool = ZO_ObjectPool:New(IconFactory, ResetFunction) + self:SetMaxColumns(1) + self.icons = {} + self.color = ZO_DEFAULT_ENABLED_COLOR - EVENT_MANAGER:RegisterForEvent(name .. "_OnGlobalMouseUp", EVENT_GLOBAL_MOUSE_UP, function() - if self.refCount ~= nil then - local moc = wm:GetMouseOverControl() - if(moc:GetOwningWindow() ~= control) then - self.refCount = self.refCount - 1 - if self.refCount <= 0 then - self:Clear() - end - end - end - end) + EVENT_MANAGER:RegisterForEvent(name .. "_OnGlobalMouseUp", EVENT_GLOBAL_MOUSE_UP, function() + if self.refCount ~= nil then + local moc = wm:GetMouseOverControl() + if(moc:GetOwningWindow() ~= control) then + self.refCount = self.refCount - 1 + if self.refCount <= 0 then + self:Clear() + end + end + end + end) end function IconPickerMenu:OnMouseEnter(icon) - InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT) - SetTooltipText(InformationTooltip, LAM.util.GetTooltipText(icon.tooltip)) - InformationTooltipTopLevel:BringWindowToTop() + InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT) + SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(icon.tooltip)) + InformationTooltipTopLevel:BringWindowToTop() end function IconPickerMenu:OnMouseExit(icon) - ClearTooltip(InformationTooltip) + ClearTooltip(InformationTooltip) end function IconPickerMenu:SetMaxColumns(value) - self.maxCols = value ~= nil and value or 5 + self.maxCols = value ~= nil and value or 5 end local DEFAULT_SIZE = 28 function IconPickerMenu:SetIconSize(value) - local iconSize = DEFAULT_SIZE - if value ~= nil then iconSize = math.max(iconSize, value) end - self.iconSize = iconSize + local iconSize = DEFAULT_SIZE + if value ~= nil then iconSize = math.max(iconSize, value) end + self.iconSize = iconSize end function IconPickerMenu:SetVisibleRows(value) - self.visibleRows = value ~= nil and value or 4.5 + self.visibleRows = value ~= nil and value or 4.5 end function IconPickerMenu:SetMouseHandlers(onEnter, onExit) - self.customOnMouseEnter = onEnter - self.customOnMouseExit = onExit + self.customOnMouseEnter = onEnter + self.customOnMouseExit = onExit end function IconPickerMenu:UpdateDimensions() - local iconSize = self.iconSize - local width = iconSize * self.maxCols + 20 - local height = iconSize * self.visibleRows - self.control:SetDimensions(width, height) + local iconSize = self.iconSize + local width = iconSize * self.maxCols + 20 + local height = iconSize * self.visibleRows + self.control:SetDimensions(width, height) - local icons = self.icons - for i = 1, #icons do - local icon = icons[i] - icon:SetDimensions(iconSize, iconSize) - end + local icons = self.icons + for i = 1, #icons do + local icon = icons[i] + icon:SetDimensions(iconSize, iconSize) + end end function IconPickerMenu:UpdateAnchors() - local iconSize = self.iconSize - local col, maxCols = 1, self.maxCols - local previousCol, previousRow - local scroll = self.scroll - local icons = self.icons + local iconSize = self.iconSize + local col, maxCols = 1, self.maxCols + local previousCol, previousRow + local scroll = self.scroll + local icons = self.icons - for i = 1, #icons do - local icon = icons[i] - icon:ClearAnchors() - if i == 1 then - icon:SetAnchor(TOPLEFT, scroll, TOPLEFT, 0, 0) - previousRow = icon - elseif col == 1 then - icon:SetAnchor(TOPLEFT, previousRow, BOTTOMLEFT, 0, 0) - previousRow = icon - else - icon:SetAnchor(TOPLEFT, previousCol, TOPRIGHT, 0, 0) - end - previousCol = icon - col = col >= maxCols and 1 or col + 1 - end + for i = 1, #icons do + local icon = icons[i] + icon:ClearAnchors() + if i == 1 then + icon:SetAnchor(TOPLEFT, scroll, TOPLEFT, 0, 0) + previousRow = icon + elseif col == 1 then + icon:SetAnchor(TOPLEFT, previousRow, BOTTOMLEFT, 0, 0) + previousRow = icon + else + icon:SetAnchor(TOPLEFT, previousCol, TOPRIGHT, 0, 0) + end + previousCol = icon + col = col >= maxCols and 1 or col + 1 + end end function IconPickerMenu:Clear() - self.icons = {} - self.iconPool:ReleaseAllObjects() - self.control:SetHidden(true) - self.color = ZO_DEFAULT_ENABLED_COLOR - self.refCount = nil - self.parent = nil - self.customOnMouseEnter = nil - self.customOnMouseExit = nil + self.icons = {} + self.iconPool:ReleaseAllObjects() + self.control:SetHidden(true) + self.color = ZO_DEFAULT_ENABLED_COLOR + self.refCount = nil + self.parent = nil + self.customOnMouseEnter = nil + self.customOnMouseExit = nil end function IconPickerMenu:AddIcon(texturePath, callback, tooltip) - local icon, key = self.iconPool:AcquireObject() - icon:SetTexture(texturePath) - icon:SetColor(self.color:UnpackRGBA()) - icon.texture = texturePath - icon.tooltip = tooltip - icon.OnSelect = callback - self.icons[#self.icons + 1] = icon + local icon, key = self.iconPool:AcquireObject() + icon:SetTexture(texturePath) + icon:SetColor(self.color:UnpackRGBA()) + icon.texture = texturePath + icon.tooltip = tooltip + icon.OnSelect = callback + self.icons[#self.icons + 1] = icon end function IconPickerMenu:Show(parent) - if #self.icons == 0 then return false end - if not self.control:IsHidden() then self:Clear() return false end - self:UpdateDimensions() - self:UpdateAnchors() + if #self.icons == 0 then return false end + if not self.control:IsHidden() then self:Clear() return false end + self:UpdateDimensions() + self:UpdateAnchors() - local control = self.control - control:ClearAnchors() - control:SetAnchor(TOPLEFT, parent, BOTTOMLEFT, 0, 8) - control:SetHidden(false) - control:BringWindowToTop() - self.parent = parent - self.refCount = 2 + local control = self.control + control:ClearAnchors() + control:SetAnchor(TOPLEFT, parent, BOTTOMLEFT, 0, 8) + control:SetHidden(false) + control:BringWindowToTop() + self.parent = parent + self.refCount = 2 - return true + return true end function IconPickerMenu:SetColor(color) - local icons = self.icons - self.color = color - for i = 1, #icons do - local icon = icons[i] - icon:SetColor(color:UnpackRGBA()) - end + local icons = self.icons + self.color = color + for i = 1, #icons do + local icon = icons[i] + icon:SetColor(color:UnpackRGBA()) + end end ------------------------------------------------------------- local function UpdateChoices(control, choices, choicesTooltips) - local data = control.data - if not choices then - choices, choicesTooltips = data.choices, data.choicesTooltips - end - local addedChoices = {} + local data = control.data + if not choices then + choices, choicesTooltips = data.choices, data.choicesTooltips or {} + end + local addedChoices = {} - local iconPicker = LAM.util.GetIconPickerMenu() - iconPicker:Clear() - for i = 1, #choices do - local texture = choices[i] - if not addedChoices[texture] then -- remove duplicates - iconPicker:AddIcon(choices[i], function(self, texture) - control.icon:SetTexture(texture) - data.setFunc(texture) - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - end, choicesTooltips[i]) - addedChoices[texture] = true - end - end + local iconPicker = LAM.util.GetIconPickerMenu() + iconPicker:Clear() + for i = 1, #choices do + local texture = choices[i] + if not addedChoices[texture] then -- remove duplicates + iconPicker:AddIcon(choices[i], function(self, texture) + control.icon:SetTexture(texture) + data.setFunc(texture) + LAM.util.RequestRefreshIfNeeded(control) + end, LAM.util.GetStringFromValue(choicesTooltips[i])) + addedChoices[texture] = true + end + end end local function IsDisabled(control) - if type(control.data.disabled) == "function" then - return control.data.disabled() - else - return control.data.disabled - end + if type(control.data.disabled) == "function" then + return control.data.disabled() + else + return control.data.disabled + end end local function SetColor(control, color) - local icon = control.icon - if IsDisabled(control) then - icon:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - else - icon.color = color or control.data.defaultColor or ZO_DEFAULT_ENABLED_COLOR - icon:SetColor(icon.color:UnpackRGBA()) - end + local icon = control.icon + if IsDisabled(control) then + icon:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + else + icon.color = color or control.data.defaultColor or ZO_DEFAULT_ENABLED_COLOR + icon:SetColor(icon.color:UnpackRGBA()) + end - local iconPicker = LAM.util.GetIconPickerMenu() - if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then - iconPicker:SetColor(icon.color) - end + local iconPicker = LAM.util.GetIconPickerMenu() + if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then + iconPicker:SetColor(icon.color) + end end local function UpdateDisabled(control) - local disable = IsDisabled(control) + local disable = IsDisabled(control) - control.dropdown:SetMouseEnabled(not disable) - control.dropdownButton:SetEnabled(not disable) + control.dropdown:SetMouseEnabled(not disable) + control.dropdownButton:SetEnabled(not disable) - local iconPicker = LAM.util.GetIconPickerMenu() - if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then - iconPicker:Clear() - end + local iconPicker = LAM.util.GetIconPickerMenu() + if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then + iconPicker:Clear() + end - SetColor(control) - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end + SetColor(control, control.icon.color) + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end end local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - control.icon:SetTexture(value) - elseif value then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - control.icon:SetTexture(value) - end + if forceDefault then --if we are forcing defaults + value = LAM.util.GetDefaultValue(control.data.default) + control.data.setFunc(value) + control.icon:SetTexture(value) + elseif value then + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + LAM.util.RequestRefreshIfNeeded(control) + else + value = control.data.getFunc() + control.icon:SetTexture(value) + end end local MIN_HEIGHT = 26 local HALF_WIDTH_LINE_SPACING = 2 local function SetIconSize(control, size) - local icon = control.icon - icon.size = size - icon:SetDimensions(size, size) + local icon = control.icon + icon.size = size + icon:SetDimensions(size, size) - local height = size + 4 - control.dropdown:SetDimensions(size + 20, height) - height = math.max(height, MIN_HEIGHT) - control.container:SetHeight(height) - if control.lineControl then - control.lineControl:SetHeight(MIN_HEIGHT + size + HALF_WIDTH_LINE_SPACING) - else - control:SetHeight(height) - end + local height = size + 4 + control.dropdown:SetDimensions(size + 20, height) + height = math.max(height, MIN_HEIGHT) + control.container:SetHeight(height) + if control.lineControl then + control.lineControl:SetHeight(MIN_HEIGHT + size + HALF_WIDTH_LINE_SPACING) + else + control:SetHeight(height) + end - local iconPicker = LAM.util.GetIconPickerMenu() - if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then - iconPicker:SetIconSize(size) - iconPicker:UpdateDimensions() - iconPicker:UpdateAnchors() - end + local iconPicker = LAM.util.GetIconPickerMenu() + if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then + iconPicker:SetIconSize(size) + iconPicker:UpdateDimensions() + iconPicker:UpdateAnchors() + end end function LAMCreateControl.iconpicker(parent, iconpickerData, controlName) - local control = LAM.util.CreateLabelAndContainerControl(parent, iconpickerData, controlName) + local control = LAM.util.CreateLabelAndContainerControl(parent, iconpickerData, controlName) - local function ShowIconPicker() - local iconPicker = LAM.util.GetIconPickerMenu() - if iconPicker.parent == control.container then - iconPicker:Clear() - else - iconPicker:SetMaxColumns(iconpickerData.maxColumns) - iconPicker:SetVisibleRows(iconpickerData.visibleRows) - iconPicker:SetIconSize(control.icon.size) - UpdateChoices(control) - iconPicker:SetColor(control.icon.color) - if iconpickerData.beforeShow then - if iconpickerData.beforeShow(control, iconPicker) then - iconPicker:Clear() - return - end - end - iconPicker:Show(control.container) - end - end + local function ShowIconPicker() + local iconPicker = LAM.util.GetIconPickerMenu() + if iconPicker.parent == control.container then + iconPicker:Clear() + else + iconPicker:SetMaxColumns(iconpickerData.maxColumns) + iconPicker:SetVisibleRows(iconpickerData.visibleRows) + iconPicker:SetIconSize(control.icon.size) + UpdateChoices(control) + iconPicker:SetColor(control.icon.color) + if iconpickerData.beforeShow then + if iconpickerData.beforeShow(control, iconPicker) then + iconPicker:Clear() + return + end + end + iconPicker:Show(control.container) + end + end - local iconSize = iconpickerData.iconSize ~= nil and iconpickerData.iconSize or DEFAULT_SIZE - control.dropdown = wm:CreateControl(nil, control.container, CT_CONTROL) - local dropdown = control.dropdown - dropdown:SetAnchor(LEFT, control.container, LEFT, 0, 0) - dropdown:SetMouseEnabled(true) - dropdown:SetHandler("OnMouseUp", ShowIconPicker) - dropdown:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - dropdown:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) + local iconSize = iconpickerData.iconSize ~= nil and iconpickerData.iconSize or DEFAULT_SIZE + control.dropdown = wm:CreateControl(nil, control.container, CT_CONTROL) + local dropdown = control.dropdown + dropdown:SetAnchor(LEFT, control.container, LEFT, 0, 0) + dropdown:SetMouseEnabled(true) + dropdown:SetHandler("OnMouseUp", ShowIconPicker) + dropdown:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + dropdown:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) - control.icon = wm:CreateControl(nil, dropdown, CT_TEXTURE) - local icon = control.icon - icon:SetAnchor(LEFT, dropdown, LEFT, 3, 0) - icon:SetDrawLevel(2) + control.icon = wm:CreateControl(nil, dropdown, CT_TEXTURE) + local icon = control.icon + icon:SetAnchor(LEFT, dropdown, LEFT, 3, 0) + icon:SetDrawLevel(2) - local dropdownButton = wm:CreateControlFromVirtual(nil, dropdown, "ZO_DropdownButton") - dropdownButton:SetDimensions(16, 16) - dropdownButton:SetHandler("OnClicked", ShowIconPicker) - dropdownButton:SetAnchor(RIGHT, dropdown, RIGHT, -3, 0) - control.dropdownButton = dropdownButton + local dropdownButton = wm:CreateControlFromVirtual(nil, dropdown, "ZO_DropdownButton") + dropdownButton:SetDimensions(16, 16) + dropdownButton:SetHandler("OnClicked", ShowIconPicker) + dropdownButton:SetAnchor(RIGHT, dropdown, RIGHT, -3, 0) + control.dropdownButton = dropdownButton - control.bg = wm:CreateControl(nil, dropdown, CT_BACKDROP) - local bg = control.bg - bg:SetAnchor(TOPLEFT, dropdown, TOPLEFT, 0, -3) - bg:SetAnchor(BOTTOMRIGHT, dropdown, BOTTOMRIGHT, 2, 5) - bg:SetEdgeTexture("EsoUI/Art/Tooltips/UI-Border.dds", 128, 16) - bg:SetCenterTexture("EsoUI/Art/Tooltips/UI-TooltipCenter.dds") - bg:SetInsets(16, 16, -16, -16) - local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE) - mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds") - mungeOverlay:SetDrawLevel(1) - mungeOverlay:SetAddressMode(TEX_MODE_WRAP) - mungeOverlay:SetAnchorFill() + control.bg = wm:CreateControl(nil, dropdown, CT_BACKDROP) + local bg = control.bg + bg:SetAnchor(TOPLEFT, dropdown, TOPLEFT, 0, -3) + bg:SetAnchor(BOTTOMRIGHT, dropdown, BOTTOMRIGHT, 2, 5) + bg:SetEdgeTexture("EsoUI/Art/Tooltips/UI-Border.dds", 128, 16) + bg:SetCenterTexture("EsoUI/Art/Tooltips/UI-TooltipCenter.dds") + bg:SetInsets(16, 16, -16, -16) + local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE) + mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds") + mungeOverlay:SetDrawLevel(1) + mungeOverlay:SetAddressMode(TEX_MODE_WRAP) + mungeOverlay:SetAnchorFill() - if iconpickerData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0) - control.warning.data = {tooltipText = iconpickerData.warning} - end - - if iconpickerData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - - control.UpdateChoices = UpdateChoices - control.UpdateValue = UpdateValue - control:UpdateValue() - control.SetColor = SetColor - control:SetColor() - control.SetIconSize = SetIconSize - control:SetIconSize(iconSize) - - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + if iconpickerData.warning ~= nil or iconpickerData.requiresReload then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0) + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end - return control + control.UpdateChoices = UpdateChoices + control.UpdateValue = UpdateValue + control:UpdateValue() + control.SetColor = SetColor + control:SetColor() + control.SetIconSize = SetIconSize + control:SetIconSize(iconSize) + + if iconpickerData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + + LAM.util.RegisterForRefreshIfNeeded(control) + LAM.util.RegisterForReloadIfNeeded(control) + + return control end diff --git a/Libs/LibAddonMenu-2.0/controls/panel.lua b/Libs/LibAddonMenu-2.0/controls/panel.lua index 0d698c7..d6956d8 100644 --- a/Libs/LibAddonMenu-2.0/controls/panel.lua +++ b/Libs/LibAddonMenu-2.0/controls/panel.lua @@ -1,18 +1,19 @@ --[[panelData = { - type = "panel", - name = "Window Title", - displayName = "My Longer Window Title", --(optional) (can be useful for long addon names or if you want to colorize it) - author = "Seerah", --(optional) - version = "2.0", --(optional) - keywords = "settings", --(optional) additional keywords for search filter (it looks for matches in name..keywords..author) - slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel (don't forget to include the slash!) - registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown) - registerForDefaults = true, --boolean (optional) (will set all options controls back to default values) - resetFunc = function() print("defaults reset") end, --(optional) custom function to run after settings are reset to defaults -} ]] + type = "panel", + name = "Window Title", -- or string id or function returning a string + displayName = "My Longer Window Title", -- or string id or function returning a string (optional) (can be useful for long addon names or if you want to colorize it) + author = "Seerah", -- or string id or function returning a string (optional) + version = "2.0", -- or string id or function returning a string (optional) + website = "http://www.esoui.com/downloads/info7-LibAddonMenu.html", -- URL of website where the addon can be updated (optional) + keywords = "settings", -- additional keywords for search filter (it looks for matches in name..keywords..author) (optional) + slashCommand = "/myaddon", -- will register a keybind to open to this panel (don't forget to include the slash!) (optional) + registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown) + registerForDefaults = true, --boolean (optional) (will set all options controls back to default values) + resetFunc = function() print("defaults reset") end, --(optional) custom function to run after settings are reset to defaults +} ]] -local widgetVersion = 9 +local widgetVersion = 13 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("panel", widgetVersion) then return end @@ -20,113 +21,106 @@ local wm = WINDOW_MANAGER local cm = CALLBACK_MANAGER local function RefreshPanel(control) - local panel = control.panel or control --callback can be fired by a single control or by the panel showing - local panelControls = panel.controlsToRefresh + local panel = LAM.util.GetTopPanel(control) --callback can be fired by a single control, by the panel showing or by a nested submenu + local panelControls = panel.controlsToRefresh - for i = 1, #panelControls do - local updateControl = panelControls[i] - if updateControl ~= control then - if updateControl.UpdateValue then - updateControl:UpdateValue() - end - if updateControl.UpdateDisabled then - updateControl:UpdateDisabled() - end - end - end + for i = 1, #panelControls do + local updateControl = panelControls[i] + if updateControl ~= control and updateControl.UpdateValue then + updateControl:UpdateValue() + end + if updateControl.UpdateDisabled then + updateControl:UpdateDisabled() + end + if updateControl.UpdateWarning then + updateControl:UpdateWarning() + end + end end local function ForceDefaults(panel) - local panelControls = panel.controlsToRefresh + local panelControls = panel.controlsToRefresh - for i = 1, #panelControls do - local updateControl = panelControls[i] - if updateControl.UpdateValue and updateControl.data.default ~= nil then - updateControl:UpdateValue(true) - end - end + for i = 1, #panelControls do + local updateControl = panelControls[i] + if updateControl.UpdateValue and updateControl.data.default ~= nil then + updateControl:UpdateValue(true) + end + end - if panel.data.resetFunc then - panel.data.resetFunc() - end + if panel.data.resetFunc then + panel.data.resetFunc() + end - cm:FireCallbacks("LAM-RefreshPanel", panel) + cm:FireCallbacks("LAM-RefreshPanel", panel) end -ESO_Dialogs["LAM_DEFAULTS"] = { - title = { - text = SI_INTERFACE_OPTIONS_RESET_TO_DEFAULT_TOOLTIP, - }, - mainText = { - text = SI_OPTIONS_RESET_PROMPT, - align = TEXT_ALIGN_CENTER, - }, - buttons = { - [1] = { - text = SI_OPTIONS_RESET, - callback = function(dialog) ForceDefaults(dialog.data[1]) end, - }, - [2] = { - text = SI_DIALOG_CANCEL, - }, - }, -} local callbackRegistered = false LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1 +local SEPARATOR = " - " +local LINK_COLOR = ZO_ColorDef:New("5959D5") +local LINK_MOUSE_OVER_COLOR = ZO_ColorDef:New("B8B8D3") + function LAMCreateControl.panel(parent, panelData, controlName) - local control = wm:CreateControl(controlName, parent, CT_CONTROL) + local control = wm:CreateControl(controlName, parent, CT_CONTROL) - control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") - local label = control.label - label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4) - label:SetText(panelData.displayName or panelData.name) + control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") + local label = control.label + label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4) + label:SetText(LAM.util.GetStringFromValue(panelData.displayName or panelData.name)) - if panelData.author or panelData.version then - control.info = wm:CreateControl(nil, control, CT_LABEL) - local info = control.info - info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin") - info:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, -2) - if panelData.author and panelData.version then - info:SetText(string.format("Version: %s - %s: %s", panelData.version, GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) - elseif panelData.author then - info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) - else - info:SetText("Version: "..panelData.version) - end - end + if panelData.author or panelData.version then + control.info = wm:CreateControl(nil, control, CT_LABEL) + local info = control.info + info:SetFont(LAM.util.L["PANEL_INFO_FONT"]) + info:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, -2) - control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer") - LAMCreateControl.scrollCount = LAMCreateControl.scrollCount + 1 - local container = control.container - container:SetAnchor(TOPLEFT, control.info or label, BOTTOMLEFT, 0, 20) - container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3) - control.scroll = GetControl(control.container, "ScrollChild") - control.scroll:SetResizeToFitPadding(0, 20) + local output = {} + if panelData.author then + output[#output + 1] = zo_strformat(LAM.util.L["AUTHOR"], LAM.util.GetStringFromValue(panelData.author)) + end + if panelData.version then + output[#output + 1] = zo_strformat(LAM.util.L["VERSION"], LAM.util.GetStringFromValue(panelData.version)) + end + info:SetText(table.concat(output, SEPARATOR)) + end - if panelData.registerForDefaults then - control.defaultButton = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultTextButton") - local defaultButton = control.defaultButton - defaultButton:SetFont("ZoFontDialogKeybindDescription") - defaultButton:SetHorizontalAlignment(TEXT_ALIGN_LEFT) - --defaultButton:SetText("Reset To Defaults") - defaultButton:SetText(GetString(SI_OPTIONS_DEFAULTS)) - defaultButton:SetDimensions(200, 30) - defaultButton:SetAnchor(TOPLEFT, control, BOTTOMLEFT, 0, 2) - defaultButton:SetHandler("OnClicked", function() - ZO_Dialogs_ShowDialog("LAM_DEFAULTS", {control}) - end) - end + if panelData.website then + control.website = wm:CreateControl(nil, control, CT_BUTTON) + local website = control.website + website:SetClickSound("Click") + website:SetFont(LAM.util.L["PANEL_INFO_FONT"]) + website:SetNormalFontColor(LINK_COLOR:UnpackRGBA()) + website:SetMouseOverFontColor(LINK_MOUSE_OVER_COLOR:UnpackRGBA()) + if(control.info) then + website:SetAnchor(TOPLEFT, control.info, TOPRIGHT, 0, 0) + website:SetText(string.format("|cffffff%s|r%s", SEPARATOR, LAM.util.L["WEBSITE"])) + else + website:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, -2) + website:SetText(LAM.util.L["WEBSITE"]) + end + website:SetDimensions(website:GetLabelControl():GetTextDimensions()) + website:SetHandler("OnClicked", function() + RequestOpenUnsafeURL(panelData.website) + end) + end - if panelData.registerForRefresh and not callbackRegistered then --don't want to register our callback more than once - cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel) - callbackRegistered = true - end + control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer") + LAMCreateControl.scrollCount = LAMCreateControl.scrollCount + 1 + local container = control.container + container:SetAnchor(TOPLEFT, control.info or label, BOTTOMLEFT, 0, 20) + container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3) + control.scroll = GetControl(control.container, "ScrollChild") + control.scroll:SetResizeToFitPadding(0, 20) - control.data = panelData - control.controlsToRefresh = {} + if panelData.registerForRefresh and not callbackRegistered then --don't want to register our callback more than once + cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel) + callbackRegistered = true + end - return control + control.ForceDefaults = ForceDefaults + control.data = panelData + control.controlsToRefresh = {} + + return control end - - --- vi: noexpandtab diff --git a/Libs/LibAddonMenu-2.0/controls/slider.lua b/Libs/LibAddonMenu-2.0/controls/slider.lua index 93eafd8..7a85d57 100644 --- a/Libs/LibAddonMenu-2.0/controls/slider.lua +++ b/Libs/LibAddonMenu-2.0/controls/slider.lua @@ -1,157 +1,212 @@ --[[sliderData = { - type = "slider", - name = "My Slider", - tooltip = "Slider's tooltip text.", - min = 0, - max = 20, - step = 1, --(optional) - getFunc = function() return db.var end, - setFunc = function(value) db.var = value doStuff() end, - width = "full", --or "half" (optional) - disabled = function() return db.someBooleanSetting end, --or boolean (optional) - warning = "Will need to reload the UI.", --(optional) - default = defaults.var, --(optional) - reference = "MyAddonSlider" --(optional) unique global reference to control -} ]] + type = "slider", + name = "My Slider", -- or string id or function returning a string + getFunc = function() return db.var end, + setFunc = function(value) db.var = value doStuff() end, + min = 0, + max = 20, + step = 1, --(optional) + clampInput = true, -- boolean, if set to false the input won't clamp to min and max and allow any number instead (optional) + decimals = 0, -- when specified the input value is rounded to the specified number of decimals (optional) + autoSelect = false, -- boolean, automatically select everything in the text input field when it gains focus (optional) + inputLocation = "below", -- or "right", determines where the input field is shown. This should not be used within the addon menu and is for custom sliders (optional) + tooltip = "Slider's tooltip text.", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional) + requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional) + default = defaults.var, -- default value or function that returns the default value (optional) + reference = "MyAddonSlider" -- unique global reference to control (optional) +} ]] - -local widgetVersion = 7 +local widgetVersion = 12 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("slider", widgetVersion) then return end local wm = WINDOW_MANAGER -local cm = CALLBACK_MANAGER -local round = zo_round local strformat = string.format -local tinsert = table.insert + +local function RoundDecimalToPlace(d, place) + return tonumber(strformat("%." .. tostring(place) .. "f", d)) +end local function UpdateDisabled(control) - local disable - if type(control.data.disabled) == "function" then - disable = control.data.disabled() - else - disable = control.data.disabled - end + local disable + if type(control.data.disabled) == "function" then + disable = control.data.disabled() + else + disable = control.data.disabled + end - control.slider:SetEnabled(not disable) - control.slidervalue:SetEditEnabled(not disable) - if disable then - control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) - control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) - else - control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) - end + control.slider:SetEnabled(not disable) + control.slidervalue:SetEditEnabled(not disable) + if disable then + control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) + control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA()) + else + control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA()) + end end local function UpdateValue(control, forceDefault, value) - if forceDefault then --if we are forcing defaults - value = control.data.default - control.data.setFunc(value) - elseif value and value >= control.data.min and value <= control.data.max then - control.data.setFunc(value) - --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed - if control.panel.data.registerForRefresh then - cm:FireCallbacks("LAM-RefreshPanel", control) - end - else - value = control.data.getFunc() - end + if forceDefault then --if we are forcing defaults + value = LAM.util.GetDefaultValue(control.data.default) + control.data.setFunc(value) + elseif value then + if control.data.decimals then + value = RoundDecimalToPlace(value, control.data.decimals) + end + if control.data.clampInput ~= false then + value = math.max(math.min(value, control.data.max), control.data.min) + end + control.data.setFunc(value) + --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed + LAM.util.RequestRefreshIfNeeded(control) + else + value = control.data.getFunc() + end - control.slider:SetValue(value) - control.slidervalue:SetText(value) + control.slider:SetValue(value) + control.slidervalue:SetText(value) end - function LAMCreateControl.slider(parent, sliderData, controlName) - local control = LAM.util.CreateLabelAndContainerControl(parent, sliderData, controlName) + local control = LAM.util.CreateLabelAndContainerControl(parent, sliderData, controlName) + local isInputOnRight = sliderData.inputLocation == "right" - --skipping creating the backdrop... Is this the actual slider texture? - control.slider = wm:CreateControl(nil, control.container, CT_SLIDER) - local slider = control.slider - slider:SetAnchor(TOPLEFT) - slider:SetAnchor(TOPRIGHT) - slider:SetHeight(14) - slider:SetMouseEnabled(true) - slider:SetOrientation(ORIENTATION_HORIZONTAL) - --put nil for highlighted texture file path, and what look to be texture coords - slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16) - local minValue = sliderData.min - local maxValue = sliderData.max - slider:SetMinMax(minValue, maxValue) - slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) - slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseExit(control) end) + --skipping creating the backdrop... Is this the actual slider texture? + control.slider = wm:CreateControl(nil, control.container, CT_SLIDER) + local slider = control.slider + slider:SetAnchor(TOPLEFT) + slider:SetHeight(14) + if(isInputOnRight) then + slider:SetAnchor(TOPRIGHT, nil, nil, -60) + else + slider:SetAnchor(TOPRIGHT) + end + slider:SetMouseEnabled(true) + slider:SetOrientation(ORIENTATION_HORIZONTAL) + --put nil for highlighted texture file path, and what look to be texture coords + slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16) + local minValue = sliderData.min + local maxValue = sliderData.max + slider:SetMinMax(minValue, maxValue) + slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) + slider:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) - slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP) - local bg = slider.bg - bg:SetCenterColor(0, 0, 0) - bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4) - bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4) - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4) + slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP) + local bg = slider.bg + bg:SetCenterColor(0, 0, 0) + bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4) + bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4) + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4) - control.minText = wm:CreateControl(nil, slider, CT_LABEL) - local minText = control.minText - minText:SetFont("ZoFontGameSmall") - minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT) - minText:SetText(sliderData.min) + control.minText = wm:CreateControl(nil, slider, CT_LABEL) + local minText = control.minText + minText:SetFont("ZoFontGameSmall") + minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT) + minText:SetText(sliderData.min) - control.maxText = wm:CreateControl(nil, slider, CT_LABEL) - local maxText = control.maxText - maxText:SetFont("ZoFontGameSmall") - maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT) - maxText:SetText(sliderData.max) + control.maxText = wm:CreateControl(nil, slider, CT_LABEL) + local maxText = control.maxText + maxText:SetFont("ZoFontGameSmall") + maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT) + maxText:SetText(sliderData.max) - control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop") - control.slidervalueBG:SetDimensions(50, 16) - control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0) - control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop") - local slidervalue = control.slidervalue - slidervalue:ClearAnchors() - slidervalue:SetAnchor(TOPLEFT, control.slidervalueBG, TOPLEFT, 3, 1) - slidervalue:SetAnchor(BOTTOMRIGHT, control.slidervalueBG, BOTTOMRIGHT, -3, -1) - slidervalue:SetTextType(TEXT_TYPE_NUMERIC) - slidervalue:SetFont("ZoFontGameSmall") - slidervalue:SetHandler("OnEscape", function(self) - self:LoseFocus() - control:UpdateValue() - end) - slidervalue:SetHandler("OnEnter", function(self) - self:LoseFocus() - control:UpdateValue(false, tonumber(self:GetText())) - end) + control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop") + if(isInputOnRight) then + control.slidervalueBG:SetDimensions(60, 26) + control.slidervalueBG:SetAnchor(LEFT, slider, RIGHT, 5, 0) + else + control.slidervalueBG:SetDimensions(50, 16) + control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0) + end + control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop") + local slidervalue = control.slidervalue + slidervalue:ClearAnchors() + slidervalue:SetAnchor(TOPLEFT, control.slidervalueBG, TOPLEFT, 3, 1) + slidervalue:SetAnchor(BOTTOMRIGHT, control.slidervalueBG, BOTTOMRIGHT, -3, -1) + slidervalue:SetTextType(TEXT_TYPE_NUMERIC) + if(isInputOnRight) then + slidervalue:SetFont("ZoFontGameLarge") + else + slidervalue:SetFont("ZoFontGameSmall") + end - local range = maxValue - minValue - slider:SetValueStep(sliderData.step or 1) - slider:SetHandler("OnValueChanged", function(self, value, eventReason) - if eventReason == EVENT_REASON_SOFTWARE then return end - self:SetValue(value) --do we actually need this line? - slidervalue:SetText(value) - end) - slider:SetHandler("OnSliderReleased", function(self, value) - --sliderData.setFunc(value) - control:UpdateValue(false, value) --does this work here instead? - end) + local isHandlingChange = false + local function HandleValueChanged(value) + if isHandlingChange then return end + if sliderData.decimals then + value = RoundDecimalToPlace(value, sliderData.decimals) + end + isHandlingChange = true + slider:SetValue(value) + slidervalue:SetText(value) + isHandlingChange = false + end - if sliderData.warning then - control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") - control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0) - control.warning.data = {tooltipText = sliderData.warning} - end + slidervalue:SetHandler("OnEscape", function(self) + HandleValueChanged(sliderData.getFunc()) + self:LoseFocus() + end) + slidervalue:SetHandler("OnEnter", function(self) + self:LoseFocus() + end) + slidervalue:SetHandler("OnFocusLost", function(self) + local value = tonumber(self:GetText()) + control:UpdateValue(false, value) + end) + slidervalue:SetHandler("OnTextChanged", function(self) + local input = self:GetText() + if(#input > 1 and not input:sub(-1):match("[0-9]")) then return end + local value = tonumber(input) + if(value) then + HandleValueChanged(value) + end + end) + if(sliderData.autoSelect) then + ZO_PreHookHandler(slidervalue, "OnFocusGained", function(self) + self:SelectAll() + end) + end - if sliderData.disabled then - control.UpdateDisabled = UpdateDisabled - control:UpdateDisabled() - end - control.UpdateValue = UpdateValue - control:UpdateValue() + local range = maxValue - minValue + slider:SetValueStep(sliderData.step or 1) + slider:SetHandler("OnValueChanged", function(self, value, eventReason) + if eventReason == EVENT_REASON_SOFTWARE then return end + HandleValueChanged(value) + end) + slider:SetHandler("OnSliderReleased", function(self, value) + control:UpdateValue(false, value) + end) + slider:SetHandler("OnMouseWheel", function(self, value) + if(not self:GetEnabled()) then return end + local new_value = (tonumber(slidervalue:GetText()) or sliderData.min or 0) + ((sliderData.step or 1) * value) + control:UpdateValue(false, new_value) + end) - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + if sliderData.warning ~= nil or sliderData.requiresReload then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0) + control.UpdateWarning = LAM.util.UpdateWarning + control:UpdateWarning() + end - return control -end \ No newline at end of file + control.UpdateValue = UpdateValue + control:UpdateValue() + + if sliderData.disabled ~= nil then + control.UpdateDisabled = UpdateDisabled + control:UpdateDisabled() + end + + LAM.util.RegisterForRefreshIfNeeded(control) + LAM.util.RegisterForReloadIfNeeded(control) + + return control +end diff --git a/Libs/LibAddonMenu-2.0/controls/submenu.lua b/Libs/LibAddonMenu-2.0/controls/submenu.lua index 8022809..94087cb 100644 --- a/Libs/LibAddonMenu-2.0/controls/submenu.lua +++ b/Libs/LibAddonMenu-2.0/controls/submenu.lua @@ -1,112 +1,108 @@ --[[submenuData = { - type = "submenu", - name = "Submenu Title", - tooltip = "My submenu tooltip", --(optional) - controls = {sliderData, buttonData} --(optional) used by LAM - reference = "MyAddonSubmenu" --(optional) unique global reference to control -} ]] + type = "submenu", + name = "Submenu Title", -- or string id or function returning a string + tooltip = "My submenu tooltip", -- -- or string id or function returning a string (optional) + controls = {sliderData, buttonData} --(optional) used by LAM + reference = "MyAddonSubmenu" --(optional) unique global reference to control +} ]] -local widgetVersion = 9 +local widgetVersion = 11 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("submenu", widgetVersion) then return end local wm = WINDOW_MANAGER local am = ANIMATION_MANAGER -local tinsert = table.insert - local function UpdateValue(control) - control.label:SetText(control.data.name) - if control.data.tooltip then - control.label.data.tooltipText = LAM.util.GetTooltipText(control.data.tooltip) - end + control.label:SetText(LAM.util.GetStringFromValue(control.data.name)) + if control.data.tooltip then + control.label.data.tooltipText = LAM.util.GetStringFromValue(control.data.tooltip) + end end local function AnimateSubmenu(clicked) - local control = clicked:GetParent() - control.open = not control.open + local control = clicked:GetParent() + control.open = not control.open - if control.open then - control.animation:PlayFromStart() - else - control.animation:PlayFromEnd() - end + if control.open then + control.animation:PlayFromStart() + else + control.animation:PlayFromEnd() + end end function LAMCreateControl.submenu(parent, submenuData, controlName) - local width = parent:GetWidth() - 45 - local control = wm:CreateControl(controlName or submenuData.reference, parent.scroll or parent, CT_CONTROL) - control.panel = parent - control.data = submenuData + local width = parent:GetWidth() - 45 + local control = wm:CreateControl(controlName or submenuData.reference, parent.scroll or parent, CT_CONTROL) + control.panel = parent + control.data = submenuData - control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") - local label = control.label - label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5) - label:SetDimensions(width, 30) - label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) - label:SetText(submenuData.name) - label:SetMouseEnabled(true) - if submenuData.tooltip then - label.data = {tooltipText = LAM.util.GetTooltipText(submenuData.tooltip)} - label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) - end + control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel") + local label = control.label + label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5) + label:SetDimensions(width, 30) + label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) + label:SetText(LAM.util.GetStringFromValue(submenuData.name)) + label:SetMouseEnabled(true) + if submenuData.tooltip then + label.data = {tooltipText = LAM.util.GetStringFromValue(submenuData.tooltip)} + label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + end - control.scroll = wm:CreateControl(nil, control, CT_SCROLL) - local scroll = control.scroll - scroll:SetParent(control) - scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10) - scroll:SetDimensionConstraints(width + 5, 0, width + 5, 2500) + control.scroll = wm:CreateControl(nil, control, CT_SCROLL) + local scroll = control.scroll + scroll:SetParent(control) + scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10) + scroll:SetDimensionConstraints(width + 5, 0, width + 5, 0) - control.bg = wm:CreateControl(nil, label, CT_BACKDROP) - local bg = control.bg - bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5) - bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0) - bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) - bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds") - bg:SetInsets(16, 16, -16, -16) + control.bg = wm:CreateControl(nil, label, CT_BACKDROP) + local bg = control.bg + bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5) + bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0) + bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16) + bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds") + bg:SetInsets(16, 16, -16, -16) - control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE) - local arrow = control.arrow - arrow:SetDimensions(28, 28) - arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") --list_sortup for the other way - arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5) + control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE) + local arrow = control.arrow + arrow:SetDimensions(28, 28) + arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") --list_sortup for the other way + arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5) - --figure out the cool animation later... - control.animation = am:CreateTimeline() - local animation = control.animation - animation:SetPlaybackType(ANIMATION_SIZE, 0) --2nd arg = loop count + --figure out the cool animation later... + control.animation = am:CreateTimeline() + local animation = control.animation + animation:SetPlaybackType(ANIMATION_SIZE, 0) --2nd arg = loop count - control:SetResizeToFitDescendents(true) - control.open = false - label:SetHandler("OnMouseUp", AnimateSubmenu) - animation:SetHandler("OnStop", function(self, completedPlaying) - scroll:SetResizeToFitDescendents(control.open) - if control.open then - control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds") - scroll:SetResizeToFitPadding(5, 20) - else - control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") - scroll:SetResizeToFitPadding(5, 0) - scroll:SetHeight(0) - end - end) + control:SetResizeToFitDescendents(true) + control.open = false + label:SetHandler("OnMouseUp", AnimateSubmenu) + animation:SetHandler("OnStop", function(self, completedPlaying) + scroll:SetResizeToFitDescendents(control.open) + if control.open then + control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds") + scroll:SetResizeToFitPadding(5, 20) + else + control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") + scroll:SetResizeToFitPadding(5, 0) + scroll:SetHeight(0) + end + end) - --small strip at the bottom of the submenu that you can click to close it - control.btmToggle = wm:CreateControl(nil, control, CT_TEXTURE) - local btmToggle = control.btmToggle - btmToggle:SetMouseEnabled(true) - btmToggle:SetAnchor(BOTTOMLEFT, control.scroll, BOTTOMLEFT) - btmToggle:SetAnchor(BOTTOMRIGHT, control.scroll, BOTTOMRIGHT) - btmToggle:SetHeight(15) - btmToggle:SetAlpha(0) - btmToggle:SetHandler("OnMouseUp", AnimateSubmenu) + --small strip at the bottom of the submenu that you can click to close it + control.btmToggle = wm:CreateControl(nil, control, CT_TEXTURE) + local btmToggle = control.btmToggle + btmToggle:SetMouseEnabled(true) + btmToggle:SetAnchor(BOTTOMLEFT, control.scroll, BOTTOMLEFT) + btmToggle:SetAnchor(BOTTOMRIGHT, control.scroll, BOTTOMRIGHT) + btmToggle:SetHeight(15) + btmToggle:SetAlpha(0) + btmToggle:SetHandler("OnMouseUp", AnimateSubmenu) - control.UpdateValue = UpdateValue + control.UpdateValue = UpdateValue - if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list - tinsert(control.panel.controlsToRefresh, control) - end + LAM.util.RegisterForRefreshIfNeeded(control) - return control + return control end diff --git a/Libs/LibAddonMenu-2.0/controls/texture.lua b/Libs/LibAddonMenu-2.0/controls/texture.lua index c6ef95d..4604fea 100644 --- a/Libs/LibAddonMenu-2.0/controls/texture.lua +++ b/Libs/LibAddonMenu-2.0/controls/texture.lua @@ -1,16 +1,16 @@ --[[textureData = { - type = "texture", - image = "file/path.dds", - imageWidth = 64, --max of 250 for half width, 510 for full - imageHeight = 32, --max of 100 - tooltip = "Image's tooltip text.", --(optional) - width = "full", --or "half" (optional) - reference = "MyAddonTexture" --(optional) unique global reference to control -} ]] + type = "texture", + image = "file/path.dds", + imageWidth = 64, --max of 250 for half width, 510 for full + imageHeight = 32, --max of 100 + tooltip = "Image's tooltip text.", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + reference = "MyAddonTexture" --(optional) unique global reference to control +} ]] --add texture coords support? -local widgetVersion = 7 +local widgetVersion = 9 local LAM = LibStub("LibAddonMenu-2.0") if not LAM:RegisterWidget("texture", widgetVersion) then return end @@ -18,28 +18,28 @@ local wm = WINDOW_MANAGER local MIN_HEIGHT = 26 function LAMCreateControl.texture(parent, textureData, controlName) - local control = LAM.util.CreateBaseControl(parent, textureData, controlName) - local width = control:GetWidth() - control:SetResizeToFitDescendents(true) + local control = LAM.util.CreateBaseControl(parent, textureData, controlName) + local width = control:GetWidth() + control:SetResizeToFitDescendents(true) - if control.isHalfWidth then --note these restrictions - control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4) - else - control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4) - end + if control.isHalfWidth then --note these restrictions + control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4) + else + control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4) + end - control.texture = wm:CreateControl(nil, control, CT_TEXTURE) - local texture = control.texture - texture:SetAnchor(CENTER) - texture:SetDimensions(textureData.imageWidth, textureData.imageHeight) - texture:SetTexture(textureData.image) + control.texture = wm:CreateControl(nil, control, CT_TEXTURE) + local texture = control.texture + texture:SetAnchor(CENTER) + texture:SetDimensions(textureData.imageWidth, textureData.imageHeight) + texture:SetTexture(textureData.image) - if textureData.tooltip then - texture:SetMouseEnabled(true) - texture.data = {tooltipText = LAM.util.GetTooltipText(textureData.tooltip)} - texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) - texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit) - end + if textureData.tooltip then + texture:SetMouseEnabled(true) + texture.data = {tooltipText = LAM.util.GetStringFromValue(textureData.tooltip)} + texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + texture:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + end - return control -end \ No newline at end of file + return control +end diff --git a/Libs/LibStub/LibStub.lua b/Libs/LibStub/LibStub.lua index 41293bc..4c35014 100644 --- a/Libs/LibStub/LibStub.lua +++ b/Libs/LibStub/LibStub.lua @@ -3,7 +3,7 @@ -- LibStub developed for World of Warcraft by above members of the WowAce community. -- Ported to Elder Scrolls Online by Seerah -local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 3 +local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 4 local LibStub = _G[LIBSTUB_MAJOR] local strformat = string.format @@ -34,3 +34,5 @@ if not LibStub or LibStub.minor < LIBSTUB_MINOR then function LibStub:IterateLibraries() return pairs(self.libs) end setmetatable(LibStub, { __call = LibStub.GetLibrary }) end + +LibStub.SILENT = true \ No newline at end of file diff --git a/Libs/exampleoptions.lua b/Libs/exampleoptions.lua index 4059b9d..9b4d9ea 100644 --- a/Libs/exampleoptions.lua +++ b/Libs/exampleoptions.lua @@ -1,119 +1,119 @@ local panelData = { - type = "panel", - name = "Window Title", - displayName = "Longer Window Title", - author = "Seerah", - version = "1.3", - slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel - registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown) - registerForDefaults = true, --boolean (optional) (will set all options controls back to default values) + type = "panel", + name = "Window Title", + displayName = "Longer Window Title", + author = "Seerah", + version = "1.3", + slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel + registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown) + registerForDefaults = true, --boolean (optional) (will set all options controls back to default values) } local optionsTable = { - [1] = { - type = "header", - name = "My Header", - width = "full", --or "half" (optional) - }, - [2] = { - type = "description", - --title = "My Title", --(optional) - title = nil, --(optional) - text = "My description text to display. blah blah blah blah blah blah blah - even more sample text!!", - width = "full", --or "half" (optional) - }, - [3] = { - type = "dropdown", - name = "My Dropdown", - tooltip = "Dropdown's tooltip text.", - choices = {"table", "of", "choices"}, - getFunc = function() return "of" end, - setFunc = function(var) print(var) end, - width = "half", --or "half" (optional) - warning = "Will need to reload the UI.", --(optional) - }, - [4] = { - type = "dropdown", - name = "My Dropdown", - tooltip = "Dropdown's tooltip text.", - choices = {"table", "of", "choices"}, - getFunc = function() return "of" end, - setFunc = function(var) print(var) end, - width = "half", --or "half" (optional) - warning = "Will need to reload the UI.", --(optional) - }, - [5] = { - type = "slider", - name = "My Slider", - tooltip = "Slider's tooltip text.", - min = 0, - max = 20, - step = 1, --(optional) - getFunc = function() return 3 end, - setFunc = function(value) d(value) end, - width = "half", --or "half" (optional) - default = 5, --(optional) - }, - [6] = { - type = "button", - name = "My Button", - tooltip = "Button's tooltip text.", - func = function() d("button pressed!") end, - width = "half", --or "half" (optional) - warning = "Will need to reload the UI.", --(optional) - }, - [7] = { - type = "submenu", - name = "Submenu Title", - tooltip = "My submenu tooltip", --(optional) - controls = { - [1] = { - type = "checkbox", - name = "My Checkbox", - tooltip = "Checkbox's tooltip text.", - getFunc = function() return true end, - setFunc = function(value) d(value) end, - width = "half", --or "half" (optional) - warning = "Will need to reload the UI.", --(optional) - }, - [2] = { - type = "colorpicker", - name = "My Color Picker", - tooltip = "Color Picker's tooltip text.", - getFunc = function() return 1, 0, 0, 1 end, --(alpha is optional) - setFunc = function(r,g,b,a) print(r, g, b, a) end, --(alpha is optional) - width = "half", --or "half" (optional) - warning = "warning text", - }, - [3] = { - type = "editbox", - name = "My Editbox", - tooltip = "Editbox's tooltip text.", - getFunc = function() return "this is some text" end, - setFunc = function(text) print(text) end, - isMultiline = false, --boolean - width = "half", --or "half" (optional) - warning = "Will need to reload the UI.", --(optional) - default = "", --(optional) - }, - }, - }, - [8] = { - type = "custom", - reference = "MyAddonCustomControl", --unique name for your control to use as reference - refreshFunc = function(customControl) end, --(optional) function to call when panel/controls refresh - width = "half", --or "half" (optional) - }, - [9] = { - type = "texture", - image = "EsoUI\\Art\\ActionBar\\abilityframe64_up.dds", - imageWidth = 64, --max of 250 for half width, 510 for full - imageHeight = 64, --max of 100 - tooltip = "Image's tooltip text.", --(optional) - width = "half", --or "half" (optional) - }, + [1] = { + type = "header", + name = "My Header", + width = "full", --or "half" (optional) + }, + [2] = { + type = "description", + --title = "My Title", --(optional) + title = nil, --(optional) + text = "My description text to display. blah blah blah blah blah blah blah - even more sample text!!", + width = "full", --or "half" (optional) + }, + [3] = { + type = "dropdown", + name = "My Dropdown", + tooltip = "Dropdown's tooltip text.", + choices = {"table", "of", "choices"}, + getFunc = function() return "of" end, + setFunc = function(var) print(var) end, + width = "half", --or "half" (optional) + warning = "Will need to reload the UI.", --(optional) + }, + [4] = { + type = "dropdown", + name = "My Dropdown", + tooltip = "Dropdown's tooltip text.", + choices = {"table", "of", "choices"}, + getFunc = function() return "of" end, + setFunc = function(var) print(var) end, + width = "half", --or "half" (optional) + warning = "Will need to reload the UI.", --(optional) + }, + [5] = { + type = "slider", + name = "My Slider", + tooltip = "Slider's tooltip text.", + min = 0, + max = 20, + step = 1, --(optional) + getFunc = function() return 3 end, + setFunc = function(value) d(value) end, + width = "half", --or "half" (optional) + default = 5, --(optional) + }, + [6] = { + type = "button", + name = "My Button", + tooltip = "Button's tooltip text.", + func = function() d("button pressed!") end, + width = "half", --or "half" (optional) + warning = "Will need to reload the UI.", --(optional) + }, + [7] = { + type = "submenu", + name = "Submenu Title", + tooltip = "My submenu tooltip", --(optional) + controls = { + [1] = { + type = "checkbox", + name = "My Checkbox", + tooltip = "Checkbox's tooltip text.", + getFunc = function() return true end, + setFunc = function(value) d(value) end, + width = "half", --or "half" (optional) + warning = "Will need to reload the UI.", --(optional) + }, + [2] = { + type = "colorpicker", + name = "My Color Picker", + tooltip = "Color Picker's tooltip text.", + getFunc = function() return 1, 0, 0, 1 end, --(alpha is optional) + setFunc = function(r,g,b,a) print(r, g, b, a) end, --(alpha is optional) + width = "half", --or "half" (optional) + warning = "warning text", + }, + [3] = { + type = "editbox", + name = "My Editbox", + tooltip = "Editbox's tooltip text.", + getFunc = function() return "this is some text" end, + setFunc = function(text) print(text) end, + isMultiline = false, --boolean + width = "half", --or "half" (optional) + warning = "Will need to reload the UI.", --(optional) + default = "", --(optional) + }, + }, + }, + [8] = { + type = "custom", + reference = "MyAddonCustomControl", --unique name for your control to use as reference + refreshFunc = function(customControl) end, --(optional) function to call when panel/controls refresh + width = "half", --or "half" (optional) + }, + [9] = { + type = "texture", + image = "EsoUI\\Art\\ActionBar\\abilityframe64_up.dds", + imageWidth = 64, --max of 250 for half width, 510 for full + imageHeight = 64, --max of 100 + tooltip = "Image's tooltip text.", --(optional) + width = "half", --or "half" (optional) + }, } local LAM = LibStub("LibAddonMenu-2.0") LAM:RegisterAddonPanel("MyAddon", panelData) -LAM:RegisterOptionControls("MyAddon", optionsTable) \ No newline at end of file +LAM:RegisterOptionControls("MyAddon", optionsTable)