100029 #5

Merged
fbrinker merged 6 commits from 100029 into master 2019-10-26 21:52:41 +00:00
17 changed files with 418 additions and 138 deletions
Showing only changes of commit 02cbf2cd2b - Show all commits

View File

@ -1,9 +1,11 @@
## APIVersion: 100022 100023
## APIVersion: 100029 100030
## Title: LibAddonMenu-2.0
## Version: 2.0 r26
## AddOnVersion: 26
## Version: 2.0 r30
## AddOnVersion: 30
## IsLibrary: true
## OptionalDependsOn: LibStub LibDebugLogger
## Author: Seerah, sirinsidiator, et al.
## Contributors: votan, merlight, Garkin, Randactyl, KuroiLight, silvereyes333, Baertram, kyoma
## Contributors: votan, merlight, Garkin, Randactyl, KuroiLight, silvereyes333, Baertram, kyoma, klingo, phuein
## 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.

View File

@ -4,9 +4,10 @@
--Register LAM with LibStub
local MAJOR, MINOR = "LibAddonMenu-2.0", 26
local MAJOR, MINOR = "LibAddonMenu-2.0", 30
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
LibAddonMenu2 = lam
local messages = {}
local MESSAGE_PREFIX = "[LAM2] "
@ -25,6 +26,11 @@ local function FlushMessages()
messages = {}
end
local logger
if LibDebugLogger then
logger = LibDebugLogger(MAJOR)
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
@ -72,6 +78,10 @@ local function GetStringFromValue(value)
return value
end
local function GetColorForState(disabled)
return disabled and ZO_DEFAULT_DISABLED_COLOR or ZO_DEFAULT_ENABLED_COLOR
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
@ -144,12 +154,14 @@ local function RefreshReloadUIButton()
end
end
if lam.applyButton then
lam.applyButton:SetHidden(not lam.requiresReload)
end
end
local function RequestRefreshIfNeeded(control)
-- if our parent window wants to refresh controls, then fire the callback
local panel = GetTopPanel(control.panel)
local panel = GetTopPanel(control)
local panelData = panel.data
if panelData.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
@ -313,9 +325,9 @@ local function UpdateWarning(control)
if control.data.requiresReload then
if not warning then
warning = string.format("|cff0000%s", util.L["RELOAD_UI_WARNING"])
warning = string.format("%s", util.L["RELOAD_UI_WARNING"])
else
warning = string.format("%s\n\n|cff0000%s", warning, util.L["RELOAD_UI_WARNING"])
warning = string.format("%s\n\n%s", warning, util.L["RELOAD_UI_WARNING"])
end
end
@ -333,10 +345,13 @@ local localization = {
AUTHOR = string.format("%s: <<X:1>>", GetString(SI_ADDON_MANAGER_AUTHOR)), -- "Author: <<X:1>>"
VERSION = "Version: <<X:1>>",
WEBSITE = "Visit Website",
FEEDBACK = "Feedback",
TRANSLATION = "Translation",
DONATION = "Donate",
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_UI_WARNING = "Changes to this setting require a UI reload in order to take effect.",
RELOAD_DIALOG_TITLE = "UI Reload Required",
RELOAD_DIALOG_TEXT = "Some changes require a 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",
},
@ -344,6 +359,9 @@ local localization = {
PANEL_NAME = "Addon",
VERSION = "Versione: <<X:1>>",
WEBSITE = "Visita il Sitoweb",
FEEDBACK = "Feedback",
TRANSLATION = "Traduzione",
DONATION = "Donare",
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?",
@ -353,6 +371,9 @@ local localization = {
fr = { -- provided by Ayantir
PANEL_NAME = "Extensions",
WEBSITE = "Visiter le site Web",
FEEDBACK = "Réaction",
TRANSLATION = "Traduction",
DONATION = "Donner",
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 ?",
@ -362,6 +383,9 @@ local localization = {
de = { -- provided by sirinsidiator
PANEL_NAME = "Erweiterungen",
WEBSITE = "Webseite besuchen",
FEEDBACK = "Feedback",
TRANSLATION = "Übersetzung",
DONATION = "Spende",
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?",
@ -372,6 +396,9 @@ local localization = {
PANEL_NAME = "Дополнения",
VERSION = "Версия: <<X:1>>",
WEBSITE = "Посетить сайт",
FEEDBACK = "отзыв",
TRANSLATION = "Перевод",
DONATION = "жертвовать",
PANEL_INFO_FONT = "RuESO/fonts/Univers57.otf|14|soft-shadow-thin",
RELOAD_UI_WARNING = "Для применения этой настройки необходима перезагрузка интерфейса.",
RELOAD_DIALOG_TITLE = "Необходима перезагрузка интерфейса",
@ -383,6 +410,9 @@ local localization = {
PANEL_NAME = "Configuración",
VERSION = "Versión: <<X:1>>",
WEBSITE = "Visita la página web",
FEEDBACK = "Reaccion",
TRANSLATION = "Traducción",
DONATION = "Donar",
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?",
@ -392,6 +422,9 @@ local localization = {
jp = { -- provided by k0ta0uchi
PANEL_NAME = "アドオン設定",
WEBSITE = "ウェブサイトを見る",
FEEDBACK = "フィードバック",
TRANSLATION = "訳書",
DONATION = "寄贈する",
},
zh = { -- provided by bssthu
PANEL_NAME = "插件",
@ -409,34 +442,49 @@ local localization = {
RELOAD_DIALOG_RELOAD_BUTTON = "Przeładuj",
RELOAD_DIALOG_DISCARD_BUTTON = "Porzuć",
},
kr = { -- provided by p.walker
PANEL_NAME = "蝠盜蠨",
VERSION = "纄訄: <<X:1>>",
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
br = { -- provided by mlsevero & FelipeS11
PANEL_NAME = "Addons",
AUTHOR = string.format("%s: <<X:1>>", GetString(SI_ADDON_MANAGER_AUTHOR)), -- "Autor: <<X:1>>"
VERSION = "Versão: <<X:1>>",
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",
FEEDBACK = "Feedback",
TRANSLATION = "Tradução",
DONATION = "Doação",
RELOAD_UI_WARNING = "Mudanças nessa configuração requerem o recarregamento da UI para ter efeito.",
RELOAD_DIALOG_TITLE = "Recarregamento da UI requerida",
RELOAD_DIALOG_TEXT = "Algumas mudanças requerem o recarregamento da UI para ter efeito. Você deseja recarregar agora ou descartar as mudanças?",
RELOAD_DIALOG_RELOAD_BUTTON = "Recarregar",
RELOAD_DIALOG_DISCARD_BUTTON = "Descartar",
},
}
do
local EsoKR = EsoKR
if EsoKR and EsoKR:isKorean() then
util.L = ZO_ShallowTableCopy({ -- provided by whya5448
PANEL_NAME = EsoKR:E("애드온"),
AUTHOR = string.format("%s: <<X:1>>", GetString(SI_ADDON_MANAGER_AUTHOR)), -- "Author: <<X:1>>"
VERSION = EsoKR:E("버전: <<X:1>>"),
WEBSITE = EsoKR:E("웹사이트 방문"),
FEEDBACK = EsoKR:E("피드백"),
TRANSLATION = EsoKR:E("번역"),
DONATION = EsoKR:E("기부"),
PANEL_INFO_FONT = "EsoKR/fonts/Univers57.otf|14|soft-shadow-thin",
RELOAD_UI_WARNING = EsoKR:E("이 설정을 변경하면 효과를 적용하기위해 UI 새로고침이 필요합니다."),
RELOAD_DIALOG_TITLE = EsoKR:E("UI 새로고침 필요"),
RELOAD_DIALOG_TEXT = EsoKR:E("변경된 설정 중 UI 새로고침을 필요로하는 사항이 있습니다. 지금 새로고침하시겠습니까? 아니면 변경을 취소하시겠습니까?"),
RELOAD_DIALOG_RELOAD_BUTTON = EsoKR:E("새로고침"),
RELOAD_DIALOG_DISCARD_BUTTON = EsoKR:E("변경취소"),
}, localization["en"])
else
util.L = ZO_ShallowTableCopy(localization[GetCVar("Language.2")] or {}, localization["en"])
end
end
util.GetTooltipText = GetStringFromValue -- deprecated, use util.GetStringFromValue instead
util.GetStringFromValue = GetStringFromValue
util.GetDefaultValue = GetDefaultValue
util.GetColorForState = GetColorForState
util.CreateBaseControl = CreateBaseControl
util.CreateLabelAndContainerControl = CreateLabelAndContainerControl
util.RequestRefreshIfNeeded = RequestRefreshIfNeeded
@ -776,6 +824,9 @@ local function CreateOptionsControls(panel)
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))
if logger then
logger:Error(err)
end
end
if isSubmenu then
@ -833,6 +884,22 @@ local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel
end
local CheckSafetyAndInitialize
local function ShowSetHandlerWarning(panel, handler)
local hint
if(handler == "OnShow" or handler == "OnEffectivelyShown") then
hint = "'LAM-PanelControlsCreated' or 'LAM-PanelOpened'"
elseif(handler == "OnHide" or handler == "OnEffectivelyHidden") then
hint = "'LAM-PanelClosed'"
end
if hint then
local message = ("Setting a handler on a panel is not recommended. Use the global callback %s instead. (%s on %s)"):format(hint, handler, panel.data.name)
PrintLater(message)
if logger then
logger:Warn(message)
end
end
end
--METHOD: REGISTER ADDON PANEL
--registers your addon with LibAddonMenu and creates a panel
@ -845,7 +912,8 @@ function lam:RegisterAddonPanel(addonID, panelData)
local panel = lamcc.panel(container, panelData, addonID) --addonID==global name of panel
panel:SetHidden(true)
panel:SetAnchorFill(container)
panel:SetHandler("OnShow", ToggleAddonPanels)
panel:SetHandler("OnEffectivelyShown", ToggleAddonPanels)
ZO_PreHook(panel, "SetHandler", ShowSetHandlerWarning)
local function stripMarkup(str)
return str:gsub("|[Cc]%x%x%x%x%x%x", ""):gsub("|[Rr]", "")
@ -897,6 +965,7 @@ local function CreateAddonSettingsMenuEntry()
KEYBOARD_OPTIONS.currentPanelId = panelData.id + 1
KEYBOARD_OPTIONS.panelNames[panelData.id] = panelData.name
KEYBOARD_OPTIONS.controlTable[panelData.id] = {}
lam.panelId = panelData.id

View File

@ -13,7 +13,7 @@
} ]]
local widgetVersion = 13
local widgetVersion = 14
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end
@ -79,7 +79,11 @@ function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
if upInside then
local r, g, b, a = colorpickerData.getFunc()
COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, LAM.util.GetStringFromValue(colorpickerData.name))
if IsInGamepadPreferredMode() then
COLOR_PICKER_GAMEPAD:Show(ColorPickerCallback, r, g, b, a)
else
COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a)
end
end
end)

View File

@ -1,7 +1,7 @@
--[[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
reference = "MyAddonCustomControl", -- unique name for your control to use as reference (optional)
refreshFunc = function(customControl) end, -- function to call when panel/controls refresh (optional)
width = "full", -- or "half" (optional)
} ]]

View File

@ -3,16 +3,38 @@
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)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
enableLinks = nil, -- or true for default tooltips, or function OnLinkClicked handler (optional)
-- see: https://wiki.esoui.com/UI_XML#OnLinkClicked
reference = "MyAddonDescription" -- unique global reference to control (optional)
} ]]
local widgetVersion = 8
local widgetVersion = 10
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("description", widgetVersion) then return end
local wm = WINDOW_MANAGER
local GetDefaultValue = LAM.util.GetDefaultValue
local GetColorForState = LAM.util.GetColorForState
local function OnLinkClicked(control, linkData, linkText, button)
ZO_LinkHandler_OnLinkClicked(linkText, button)
end
local function UpdateDisabled(control)
local disable = GetDefaultValue(control.data.disabled)
if disable ~= control.disabled then
local color = GetColorForState(disable)
control.desc:SetColor(color:UnpackRGBA())
if control.title then
control.title:SetColor(color:UnpackRGBA())
end
control.disabled = disable
end
end
local function UpdateValue(control)
if control.title then
control.title:SetText(LAM.util.GetStringFromValue(control.data.title))
@ -51,7 +73,21 @@ function LAMCreateControl.description(parent, descriptionData, controlName)
desc:SetAnchor(TOPLEFT)
end
if descriptionData.enableLinks then
desc:SetMouseEnabled(true)
desc:SetLinkEnabled(true)
if type(descriptionData.enableLinks) == "function" then
desc:SetHandler("OnLinkClicked", descriptionData.enableLinks)
else
desc:SetHandler("OnLinkClicked", OnLinkClicked)
end
end
control.UpdateValue = UpdateValue
if descriptionData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)

View File

@ -1,8 +1,8 @@
--[[dividerData = {
type = "divider",
width = "full", -- or "half" (optional)
height = 10, (optional)
alpha = 0.25, (optional)
height = 10, -- (optional)
alpha = 0.25, -- (optional)
reference = "MyAddonDivider" -- unique global reference to control (optional)
} ]]

View File

@ -18,11 +18,12 @@
} ]]
local widgetVersion = 18
local widgetVersion = 20
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local SORT_BY_VALUE = { ["value"] = {} }
local SORT_BY_VALUE_NUMERIC = { ["value"] = { isNumeric = true } }
local SORT_TYPES = {
@ -155,11 +156,16 @@ local function GrabSortingInfo(sortInfo)
return t
end
local ENTRY_ID = 1
local LAST_ENTRY_ID = 2
local OFFSET_X_INDEX = 4
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 SCROLLABLE_ENTRY_TEMPLATE_HEIGHT = ZO_SCROLLABLE_ENTRY_TEMPLATE_HEIGHT
local SCROLLBAR_PADDING = ZO_SCROLL_BAR_WIDTH
local PADDING_X = GetMenuPadding()
local PADDING_Y = ZO_SCROLLABLE_COMBO_BOX_LIST_PADDING_Y
local LABEL_OFFSET_X = 2
local CONTENT_PADDING = PADDING_X * 4
local ROUNDING_MARGIN = 0.01 -- needed to avoid rare issue with too many anchors processed
local ScrollableDropdownHelper = ZO_Object:Subclass()
@ -169,10 +175,10 @@ function ScrollableDropdownHelper:New(...)
return object
end
function ScrollableDropdownHelper:Initialize(parent, control, visibleRows)
function ScrollableDropdownHelper:Initialize(panel, control, visibleRows)
local combobox = control.combobox
local dropdown = control.dropdown
self.parent = parent
self.panel = panel
self.control = control
self.combobox = combobox
self.dropdown = dropdown
@ -183,14 +189,16 @@ function ScrollableDropdownHelper:Initialize(parent, control, visibleRows)
dropdown.m_dropdown:SetAnchor(TOPLEFT, combobox, BOTTOMLEFT)
-- handle dropdown or settingsmenu opening/closing
local function onShow() self:OnShow() end
local function onShow() return self:OnShow() end
local function onHide() self:OnHide() end
local function doHide() self:DoHide() end
local function doHide(closedPanel)
if closedPanel == panel then self:DoHide() end
end
ZO_PreHook(dropdown, "ShowDropdownOnMouseUp", onShow)
ZO_PreHook(dropdown, "HideDropdownInternal", onHide)
combobox:SetHandler("OnEffectivelyHidden", onHide)
parent:SetHandler("OnEffectivelyHidden", doHide)
cm:RegisterCallback("LAM-PanelClosed", doHide)
-- dont fade entries near the edges
local scrollList = dropdown.m_scroll
@ -202,11 +210,13 @@ function ScrollableDropdownHelper:Initialize(parent, control, visibleRows)
-- 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)}
local anchor1 = {select(2, scroll:GetAnchor(0))}
local anchor2 = {select(2, scroll:GetAnchor(1))}
anchor1[OFFSET_X_INDEX] = PADDING_X - LABEL_OFFSET_X
anchor2[OFFSET_X_INDEX] = -anchor1[OFFSET_X_INDEX]
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)
scroll:SetAnchor(unpack(anchor1))
scroll:SetAnchor(unpack(anchor2))
ZO_ScrollList_Commit(scrollList)
-- hook mouse enter/exit
@ -214,20 +224,18 @@ function ScrollableDropdownHelper:Initialize(parent, control, visibleRows)
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 dataType1 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, ENTRY_ID)
local dataType2 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, LAST_ENTRY_ID)
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)
control.m_label:SetAnchor(LEFT, nil, nil, LABEL_OFFSET_X)
control.m_label:SetAnchor(RIGHT, nil, nil, -LABEL_OFFSET_X)
-- 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
@ -235,24 +243,61 @@ function ScrollableDropdownHelper:Initialize(parent, control, visibleRows)
-- 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())
dropdown.AddMenuItems = ScrollableDropdownHelper.AddMenuItems
dropdown.AdjustDimensions = function()
local numItems = #dropdown.m_sortedItems
local contentWidth = self:CalculateContentWidth() + CONTENT_PADDING
local anchorOffset = 0
if(numItems > self.visibleRows) then
width = width + CONTENT_PADDING + SCROLLBAR_PADDING
anchorOffset = -SCROLLBAR_PADDING
numItems = self.visibleRows
contentWidth = contentWidth + SCROLLBAR_PADDING
anchorOffset = -SCROLLBAR_PADDING
end
scrollContent:SetAnchor(BOTTOMRIGHT, nil, nil, anchorOffset)
local height = PADDING * 2 + numItems * (SCROLLABLE_ENTRY_TEMPLATE_HEIGHT + dropdown.m_spacing) - dropdown.m_spacing + ROUNDING_MARGIN
local width = zo_max(contentWidth, dropdown.m_container:GetWidth())
local height = dropdown:GetEntryTemplateHeightWithSpacing() * numItems - dropdown.m_spacing + (PADDING_Y * 2) + ROUNDING_MARGIN
dropdown.m_dropdown:SetWidth(width)
dropdown.m_dropdown:SetHeight(height)
end)
ZO_ScrollList_SetHeight(dropdown.m_scroll, height)
scrollContent:SetAnchor(BOTTOMRIGHT, nil, nil, anchorOffset)
end
end
local function CreateScrollableComboBoxEntry(self, item, index, isLast)
item.m_index = index
item.m_owner = self
local entryType = isLast and LAST_ENTRY_ID or ENTRY_ID
local entry = ZO_ScrollList_CreateDataEntry(entryType, item)
return entry
end
function ScrollableDropdownHelper.AddMenuItems(self) -- self refers to the ZO_ScrollableComboBox here
ZO_ScrollList_Clear(self.m_scroll)
local numItems = #self.m_sortedItems
local dataList = ZO_ScrollList_GetDataList(self.m_scroll)
for i = 1, numItems do
local item = self.m_sortedItems[i]
local entry = CreateScrollableComboBoxEntry(self, item, i, i == numItems)
table.insert(dataList, entry)
end
self:AdjustDimensions()
ZO_ScrollList_Commit(self.m_scroll)
end
function ScrollableDropdownHelper:OnShow()
local dropdown = self.dropdown
-- don't show if there are no entries
if #dropdown.m_sortedItems == 0 then return true end
if dropdown.m_lastParent ~= ZO_Menus then
dropdown.m_lastParent = dropdown.m_dropdown:GetParent()
dropdown.m_dropdown:SetParent(ZO_Menus)
@ -275,7 +320,7 @@ function ScrollableDropdownHelper:DoHide()
end
end
function ScrollableDropdownHelper:GetMaxWidth()
function ScrollableDropdownHelper:CalculateContentWidth()
local dropdown = self.dropdown
local dataType = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 1)
@ -345,7 +390,7 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
if dropdownData.scrollable then
local visibleRows = type(dropdownData.scrollable) == "number" and dropdownData.scrollable or DEFAULT_VISIBLE_ROWS
control.scrollHelper = ScrollableDropdownHelper:New(parent, control, visibleRows)
control.scrollHelper = ScrollableDropdownHelper:New(LAM.util.GetTopPanel(parent), control, visibleRows)
end
ZO_PreHook(dropdown, "UpdateItems", function(self)

View File

@ -4,16 +4,19 @@
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)
website = "http://www.esoui.com/downloads/info7-LibAddonMenu.html", -- URL of website where the addon can be updated or function (optional)
feedback = "https://www.esoui.com/portal.php?uid=5815", -- URL of website where feedback/feature requests/bugs can be reported for the addon or function (optional)
translation = "https://www.esoui.com/portal.php?uid=5815", -- URL of website where translation texts of the addon can be helped with or function (optional)
donation = "http://www.esoui.com/downloads/info7-LibAddonMenu.html", -- URL of website where a donation for the addon author can be raised or function (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
registerForRefresh = true, -- boolean will refresh all options controls when a setting is changed and when the panel is shown (optional)
registerForDefaults = true, -- boolean will set all options controls back to default values (optional)
resetFunc = function() print("defaults reset") end, -- custom function to run after settings are reset to defaults (optional)
} ]]
local widgetVersion = 13
local widgetVersion = 15
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("panel", widgetVersion) then return end
@ -22,6 +25,8 @@ local cm = CALLBACK_MANAGER
local function RefreshPanel(control)
local panel = LAM.util.GetTopPanel(control) --callback can be fired by a single control, by the panel showing or by a nested submenu
if LAM.currentAddonPanel ~= panel or not LAM.currentPanelOpened then return end -- we refresh it later when the panel is opened
local panelControls = panel.controlsToRefresh
for i = 1, #panelControls do
@ -58,8 +63,39 @@ end
local callbackRegistered = false
LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1
local SEPARATOR = " - "
local COLORED_SEPARATOR = ZO_WHITE:Colorize(SEPARATOR)
local LINK_COLOR = ZO_ColorDef:New("5959D5")
local LINK_MOUSE_OVER_COLOR = ZO_ColorDef:New("B8B8D3")
local LINK_COLOR_DONATE = ZO_ColorDef:New("FFD700") -- golden
local LINK_MOUSE_OVER_COLOR_DONATE = ZO_ColorDef:New("FFF6CC")
local function CreateButtonControl(control, label, clickAction, relativeTo)
local button = wm:CreateControl(nil, control, CT_BUTTON)
button:SetClickSound("Click")
button:SetFont(LAM.util.L["PANEL_INFO_FONT"])
button:SetNormalFontColor(LINK_COLOR:UnpackRGBA())
button:SetMouseOverFontColor(LINK_MOUSE_OVER_COLOR:UnpackRGBA())
local OnClicked
local actionType = type(clickAction)
if actionType == "string" then
OnClicked = function() RequestOpenUnsafeURL(clickAction) end
elseif actionType == "function" then
OnClicked = clickAction
end
button:SetHandler("OnClicked", OnClicked)
if relativeTo then
button:SetAnchor(TOPLEFT, relativeTo, TOPRIGHT, 0, 0)
button:SetText(COLORED_SEPARATOR .. label)
else
button:SetAnchor(TOPLEFT, control.label, BOTTOMLEFT, 0, -2)
button:SetText(label)
end
button:SetDimensions(button:GetLabelControl():GetTextDimensions())
return button
end
function LAMCreateControl.panel(parent, panelData, controlName)
local control = wm:CreateControl(controlName, parent, CT_CONTROL)
@ -69,6 +105,7 @@ function LAMCreateControl.panel(parent, panelData, controlName)
label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4)
label:SetText(LAM.util.GetStringFromValue(panelData.displayName or panelData.name))
local previousInfoControl
if panelData.author or panelData.version then
control.info = wm:CreateControl(nil, control, CT_LABEL)
local info = control.info
@ -83,26 +120,30 @@ function LAMCreateControl.panel(parent, panelData, controlName)
output[#output + 1] = zo_strformat(LAM.util.L["VERSION"], LAM.util.GetStringFromValue(panelData.version))
end
info:SetText(table.concat(output, SEPARATOR))
previousInfoControl = info
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"])
control.website = CreateButtonControl(control, LAM.util.L["WEBSITE"], panelData.website, previousInfoControl)
previousInfoControl = control.website
end
website:SetDimensions(website:GetLabelControl():GetTextDimensions())
website:SetHandler("OnClicked", function()
RequestOpenUnsafeURL(panelData.website)
end)
if panelData.feedback then
control.feedback = CreateButtonControl(control, LAM.util.L["FEEDBACK"], panelData.feedback, previousInfoControl)
previousInfoControl = control.feedback
end
if panelData.translation then
control.translation = CreateButtonControl(control, LAM.util.L["TRANSLATION"], panelData.translation, previousInfoControl)
previousInfoControl = control.translation
end
if panelData.donation then
control.donation = CreateButtonControl(control, LAM.util.L["DONATION"], panelData.donation, previousInfoControl)
local donation = control.donation
previousInfoControl = donation
donation:SetNormalFontColor(LINK_COLOR_DONATE:UnpackRGBA())
donation:SetMouseOverFontColor(LINK_MOUSE_OVER_COLOR_DONATE:UnpackRGBA())
end
control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer")
@ -119,6 +160,7 @@ function LAMCreateControl.panel(parent, panelData, controlName)
end
control.ForceDefaults = ForceDefaults
control.RefreshPanel = LAM.util.RequestRefreshIfNeeded
control.data = panelData
control.controlsToRefresh = {}

View File

@ -7,6 +7,7 @@
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)
clampFunction = function(value, min, max) return math.max(math.min(value, max), min) end, -- function that is called to clamp the value (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)
@ -19,7 +20,7 @@
reference = "MyAddonSlider" -- unique global reference to control (optional)
} ]]
local widgetVersion = 12
local widgetVersion = 13
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("slider", widgetVersion) then return end
@ -30,6 +31,10 @@ local function RoundDecimalToPlace(d, place)
return tonumber(strformat("%." .. tostring(place) .. "f", d))
end
local function ClampValue(value, min, max)
return math.max(math.min(value, max), min)
end
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
@ -62,7 +67,8 @@ local function UpdateValue(control, forceDefault, value)
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)
local clamp = control.data.clampFunction or ClampValue
value = clamp(value, control.data.min, control.data.max)
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
@ -182,7 +188,9 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
HandleValueChanged(value)
end)
slider:SetHandler("OnSliderReleased", function(self, value)
if self:GetEnabled() then
control:UpdateValue(false, value)
end
end)
slider:SetHandler("OnMouseWheel", function(self, value)
if(not self:GetEnabled()) then return end

View File

@ -1,20 +1,61 @@
--[[submenuData = {
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
icon = "path/to/my/icon.dds", -- or function returning a string (optional)
iconTextureCoords = {left, right, top, bottom}, -- or function returning a table (optional)
tooltip = "My submenu tooltip", -- or string id or function returning a string (optional)
controls = {sliderData, buttonData} -- used by LAM (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
disabledLabel = function() return db.someBooleanSetting end, -- or boolean (optional)
reference = "MyAddonSubmenu" -- unique global reference to control (optional)
} ]]
local widgetVersion = 11
local widgetVersion = 13
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("submenu", widgetVersion) then return end
local wm = WINDOW_MANAGER
local am = ANIMATION_MANAGER
local ICON_SIZE = 32
local GetDefaultValue = LAM.util.GetDefaultValue
local GetColorForState = LAM.util.GetColorForState
local function UpdateDisabled(control)
local disable = GetDefaultValue(control.data.disabled)
if disable ~= control.disabled then
local color = GetColorForState(disable)
if disable and control.open then
control.open = false
control.animation:PlayFromStart()
end
control.arrow:SetColor(color:UnpackRGBA())
control.disabled = disable
end
local disableLabel = control.disabled or GetDefaultValue(control.data.disabledLabel)
if disableLabel ~= control.disabledLabel then
local color = GetColorForState(disableLabel)
control.label:SetColor(color:UnpackRGBA())
if(control.icon) then
control.icon:SetDesaturation(disableLabel and 1 or 0)
end
control.disabledLabel = disableLabel
end
end
local function UpdateValue(control)
control.label:SetText(LAM.util.GetStringFromValue(control.data.name))
if control.icon then
control.icon:SetTexture(GetDefaultValue(control.data.icon))
if(control.data.iconTextureCoords) then
local coords = GetDefaultValue(control.data.iconTextureCoords)
control.icon:SetTextureCoords(unpack(coords))
end
end
if control.data.tooltip then
control.label.data.tooltipText = LAM.util.GetStringFromValue(control.data.tooltip)
end
@ -22,8 +63,9 @@ end
local function AnimateSubmenu(clicked)
local control = clicked:GetParent()
control.open = not control.open
if control.disabled then return end
control.open = not control.open
if control.open then
control.animation:PlayFromStart()
else
@ -39,30 +81,55 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
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.icon then
control.icon = wm:CreateControl(nil, control, CT_TEXTURE)
local icon = control.icon
icon:SetTexture(GetDefaultValue(submenuData.icon))
if(submenuData.iconTextureCoords) then
local coords = GetDefaultValue(submenuData.iconTextureCoords)
icon:SetTextureCoords(unpack(coords))
end
icon:SetDimensions(ICON_SIZE, ICON_SIZE)
icon:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
icon:SetMouseEnabled(true)
icon:SetDrawLayer(DL_CONTROLS)
label:SetAnchor(TOP, control, TOP, 0, 5, ANCHOR_CONSTRAINS_Y)
label:SetAnchor(LEFT, icon, RIGHT, 10, 0, ANCHOR_CONSTRAINS_X)
label:SetDimensions(width - ICON_SIZE - 5, 30)
else
label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
label:SetDimensions(width, 30)
end
if submenuData.tooltip then
label.data = {tooltipText = LAM.util.GetStringFromValue(submenuData.tooltip)}
label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
if control.icon then
control.icon.data = label.data
control.icon:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
control.icon:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
end
end
control.scroll = wm:CreateControl(nil, control, CT_SCROLL)
local scroll = control.scroll
scroll:SetParent(control)
scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10)
scroll:SetAnchor(TOPLEFT, control.icon or label, BOTTOMLEFT, 0, 10)
scroll:SetDimensionConstraints(width + 5, 0, width + 5, 0)
control.bg = wm:CreateControl(nil, label, CT_BACKDROP)
control.bg = wm:CreateControl(nil, control.icon or label, CT_BACKDROP)
local bg = control.bg
bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5)
bg:SetAnchor(TOPLEFT, control.icon or 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)
bg:SetDrawLayer(DL_BACKGROUND)
control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE)
local arrow = control.arrow
@ -78,6 +145,9 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
control:SetResizeToFitDescendents(true)
control.open = false
label:SetHandler("OnMouseUp", AnimateSubmenu)
if(control.icon) then
control.icon:SetHandler("OnMouseUp", AnimateSubmenu)
end
animation:SetHandler("OnStop", function(self, completedPlaying)
scroll:SetResizeToFitDescendents(control.open)
if control.open then
@ -101,6 +171,10 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
btmToggle:SetHandler("OnMouseUp", AnimateSubmenu)
control.UpdateValue = UpdateValue
if submenuData.disabled ~= nil or submenuData.disabledLabel ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)

View File

@ -5,10 +5,10 @@
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
reference = "MyAddonTexture" -- unique global reference to control (optional)
} ]]
--add texture coords support?
-- TODO: add texture coords support?
local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0")

View File

@ -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", 4
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 5
local LibStub = _G[LIBSTUB_MAJOR]
local strformat = string.format