New Api version, new LibAddonMenu version, enabled new categories by default in the settings

This commit is contained in:
Florian Brinker 2019-02-10 15:12:44 +01:00
parent dadd1bf70c
commit 2f38fb14e3
22 changed files with 2715 additions and 1909 deletions

View File

@ -1,10 +1,11 @@
## Title: AchievementInfo ## 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. ## 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 ## Author: |c87B7CCAsto|r, @Astarax
## Contact: mail@coded-with-heart.com ## Contact: mail@coded-with-heart.com
## APIVersion: 100022 ## APIVersion: 100025
## SavedVariables: ACHIEVEMENT_INFO_DB ## SavedVariables: ACHIEVEMENT_INFO_DB
## OptionalDependsOn: LibAddonMenu-2.0, LibStub ## OptionalDependsOn: LibAddonMenu-2.0, LibStub

View File

@ -8,7 +8,7 @@
AchievementInfo = {} AchievementInfo = {}
AchievementInfo.name = "AchievementInfo" AchievementInfo.name = "AchievementInfo"
AchievementInfo.author = "Asto, @Astarax" AchievementInfo.author = "Asto, @Astarax"
AchievementInfo.version = 2.16 AchievementInfo.version = 2.20
AchievementInfo.savedVars = nil AchievementInfo.savedVars = nil
AchievementInfo.LangStore = {} AchievementInfo.LangStore = {}

View File

@ -24,6 +24,18 @@ function AchievementInfo.loadSavedVars()
cat8 = true, cat8 = true,
cat9 = true, cat9 = true,
cat10 = 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 devDebug = false
} }

View File

@ -1,10 +1,16 @@
## APIVersion: 100011 ## APIVersion: 100022 100023
## Title: LibAddonMenu-2.0 ## Title: LibAddonMenu-2.0
## Version: 2.0 r18 ## Version: 2.0 r26
## AddOnVersion: 26
## Author: Seerah, sirinsidiator, et al. ## 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. ## 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 LibStub\LibStub.lua
@ -23,3 +29,4 @@ LibAddonMenu-2.0\controls\header.lua
LibAddonMenu-2.0\controls\slider.lua LibAddonMenu-2.0\controls\slider.lua
LibAddonMenu-2.0\controls\texture.lua LibAddonMenu-2.0\controls\texture.lua
LibAddonMenu-2.0\controls\iconpicker.lua LibAddonMenu-2.0\controls\iconpicker.lua
LibAddonMenu-2.0\controls\divider.lua

View File

@ -1,6 +1,6 @@
The Artistic License 2.0 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 Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.

View File

@ -4,7 +4,7 @@
--Register LAM with LibStub --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) 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
@ -38,21 +38,38 @@ local cm = CALLBACK_MANAGER
local tconcat = table.concat local tconcat = table.concat
local tinsert = table.insert 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 addonsForList = {}
local addonToOptionsMap = {} local addonToOptionsMap = {}
local optionsCreated = {} local optionsState = {}
lam.widgets = lam.widgets or {} lam.widgets = lam.widgets or {}
local widgets = lam.widgets local widgets = lam.widgets
lam.util = {} lam.util = lam.util or {}
local util = lam.util local util = lam.util
lam.controlsForReload = lam.controlsForReload or {}
local controlsForReload = lam.controlsForReload
local function GetTooltipText(tooltip) local function GetDefaultValue(default)
if type(tooltip) == "string" then if type(default) == "function" then
return tooltip return default()
elseif type(tooltip) == "function" then
return tostring(tooltip())
end end
return nil 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 end
local function CreateBaseControl(parent, controlData, controlName) local function CreateBaseControl(parent, controlData, controlName)
@ -61,12 +78,12 @@ local function CreateBaseControl(parent, controlData, controlName)
control.data = controlData control.data = controlData
control.isHalfWidth = controlData.width == "half" control.isHalfWidth = controlData.width == "half"
control:SetWidth(control.panel:GetWidth() - 60) 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 return control
end end
local MIN_HEIGHT = 26
local HALF_WIDTH_LINE_SPACING = 2
local function CreateLabelAndContainerControl(parent, controlData, controlName) local function CreateLabelAndContainerControl(parent, controlData, controlName)
local control = CreateBaseControl(parent, controlData, controlName) local control = CreateBaseControl(parent, controlData, controlName)
local width = control:GetWidth() local width = control:GetWidth()
@ -79,7 +96,7 @@ local function CreateLabelAndContainerControl(parent, controlData, controlName)
label:SetFont("ZoFontWinH4") label:SetFont("ZoFontWinH4")
label:SetHeight(MIN_HEIGHT) label:SetHeight(MIN_HEIGHT)
label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
label:SetText(controlData.name) label:SetText(GetStringFromValue(controlData.name))
control.label = label control.label = label
if control.isHalfWidth then if control.isHalfWidth then
@ -94,16 +111,340 @@ local function CreateLabelAndContainerControl(parent, controlData, controlName)
label:SetAnchor(TOPRIGHT, container, TOPLEFT, 5, 0) label:SetAnchor(TOPRIGHT, container, TOPLEFT, 5, 0)
end end
control.data.tooltipText = GetTooltipText(control.data.tooltip) control.data.tooltipText = GetStringFromValue(control.data.tooltip)
control:SetMouseEnabled(true) control:SetMouseEnabled(true)
control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
return control return control
end 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: <<X:1>>", GetString(SI_ADDON_MANAGER_AUTHOR)), -- "Author: <<X:1>>"
VERSION = "Version: <<X:1>>",
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: <<X:1>>",
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 = "Версия: <<X:1>>",
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: <<X:1>>",
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 = "版本: <<X:1>>",
WEBSITE = "访问网站",
PANEL_INFO_FONT = "EsoZh/fonts/univers57.otf|14|soft-shadow-thin",
},
pl = { -- provided by EmiruTegryfon
PANEL_NAME = "Dodatki",
VERSION = "Wersja: <<X:1>>",
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 = "纄訄: <<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
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",
},
}
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.CreateBaseControl = CreateBaseControl
util.CreateLabelAndContainerControl = CreateLabelAndContainerControl 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 ADDON_DATA_TYPE = 1
local RESELECTING_DURING_REBUILD = true local RESELECTING_DURING_REBUILD = true
@ -122,7 +463,7 @@ local function ScrollDataIntoView(list, data)
local scrollMin, scrollMax = list.scrollbar:GetMinMax() local scrollMin, scrollMax = list.scrollbar:GetMinMax()
local scrollTop = list.scrollbar:GetValue() local scrollTop = list.scrollbar:GetValue()
local controlHeight = list.controlHeight local controlHeight = list.uniformControlHeight or list.controlHeight
local targetMin = controlHeight * (targetIndex - 1) - 64 local targetMin = controlHeight * (targetIndex - 1) - 64
-- subtracting 64 ain't arbitrary, it's the maximum fading height -- subtracting 64 ain't arbitrary, it's the maximum fading height
-- (libraries/zo_templates/scrolltemplates.lua/UpdateScrollFade) -- (libraries/zo_templates/scrolltemplates.lua/UpdateScrollFade)
@ -175,6 +516,7 @@ local function PopulateAddonList(addonList, filter)
local entryList = ZO_ScrollList_GetDataList(addonList) local entryList = ZO_ScrollList_GetDataList(addonList)
local numEntries = 0 local numEntries = 0
local selectedData = nil local selectedData = nil
local selectionIsFinal = false
ZO_ScrollList_Clear(addonList) ZO_ScrollList_Clear(addonList)
@ -186,9 +528,15 @@ local function PopulateAddonList(addonList, filter)
entryList[numEntries] = dataEntry entryList[numEntries] = dataEntry
-- select the first panel passing the filter, or the currently -- select the first panel passing the filter, or the currently
-- shown panel, but only if it passes the filter as well -- shown panel, but only if it passes the filter as well
if selectedData == nil or data.panel == lam.currentAddonPanel then if selectedData == nil or data.panel == lam.pendingAddonPanel or data.panel == lam.currentAddonPanel then
if not selectionIsFinal then
selectedData = data selectedData = data
end end
if data.panel == lam.pendingAddonPanel then
lam.pendingAddonPanel = nil
selectionIsFinal = true
end
end
else else
data.sortIndex = nil data.sortIndex = nil
end end
@ -225,6 +573,45 @@ function lam:RegisterWidget(widgetType, widgetVersion)
end end
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-- --METHOD: OPEN TO ADDON PANEL--
--opens to a specific addon's option panel --opens to a specific addon's option panel
@ -242,6 +629,7 @@ function lam:OpenToPanel(panel)
if addonData.panel == panel then if addonData.panel == panel then
selectedData = addonData selectedData = addonData
ScrollDataIntoView(addonList, selectedData) ScrollDataIntoView(addonList, selectedData)
lam.pendingAddonPanel = addonData.panel
break break
end end
end end
@ -282,14 +670,50 @@ function lam:OpenToPanel(panel)
end end
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 --INTERNAL FUNCTION
--creates controls when options panel is first shown --creates controls when options panel is first shown
--controls anchoring of these controls in the panel --controls anchoring of these controls in the panel
local function CreateOptionsControls(panel) local function CreateOptionsControls(panel)
local addonID = panel:GetName() local addonID = panel:GetName()
local optionsTable = addonToOptionsMap[addonID] if(optionsState[addonID] == OPTIONS_CREATED) then
return false
elseif(optionsState[addonID] == OPTIONS_CREATION_RUNNING) then
return true
end
optionsState[addonID] = OPTIONS_CREATION_RUNNING
local function CreationFinished()
optionsState[addonID] = OPTIONS_CREATED
cm:FireCallbacks("LAM-PanelControlsCreated", panel)
OpenCurrentPanel()
end
local optionsTable = addonToOptionsMap[addonID]
if optionsTable then if optionsTable then
local function CreateAndAnchorWidget(parent, widgetData, offsetX, offsetY, anchorTarget, wasHalf) local function CreateAndAnchorWidget(parent, widgetData, offsetX, offsetY, anchorTarget, wasHalf)
local widget local widget
@ -302,12 +726,12 @@ local function CreateOptionsControls(panel)
widget:SetAnchor(TOPLEFT) widget:SetAnchor(TOPLEFT)
anchorTarget = widget 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 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 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 isHalf = false
offsetY = 0
anchorTarget = TwinOptionsContainer(parent, anchorTarget, widget)
else -- otherwise we just put it below the previous one normally else -- otherwise we just put it below the previous one normally
widget:SetAnchor(TOPLEFT, anchorTarget, BOTTOMLEFT, 0, 15 + offsetY) widget:SetAnchor(TOPLEFT, anchorTarget, BOTTOMLEFT, 0, 15)
offsetY = 0 offsetY = 0
anchorTarget = widget anchorTarget = widget
end end
@ -351,12 +775,12 @@ local function CreateOptionsControls(panel)
err, anchorOffset, lastAddedControl, wasHalf = CreateAndAnchorWidget(parent, widgetData, offsetX, anchorOffset, lastAddedControl, wasHalf) err, anchorOffset, lastAddedControl, wasHalf = CreateAndAnchorWidget(parent, widgetData, offsetX, anchorOffset, lastAddedControl, wasHalf)
if err then if err then
PrintLater(("Could not create %s '%s' of %s."):format(widgetData.type, widgetData.name or "unnamed", addonID)) PrintLater(("Could not create %s '%s' of %s."):format(widgetData.type, GetStringFromValue(widgetData.name or "unnamed"), addonID))
end end
if isSubmenu then if isSubmenu then
if SetupCreationCalls(lastAddedControl, widgetData.controls) then if SetupCreationCalls(lastAddedControl, widgetData.controls) then
PrintLater(("The sub menu '%s' of %s is missing some entries."):format(widgetData.name or "unnamed", addonID)) PrintLater(("The sub menu '%s' of %s is missing some entries."):format(GetStringFromValue(widgetData.name or "unnamed"), addonID))
end end
end end
end end
@ -373,8 +797,7 @@ local function CreateOptionsControls(panel)
zo_callLater(DoCreateSettings, THROTTLE_TIMEOUT) zo_callLater(DoCreateSettings, THROTTLE_TIMEOUT)
end end
else else
optionsCreated[addonID] = true CreationFinished()
cm:FireCallbacks("LAM-PanelControlsCreated", panel)
end end
end end
@ -382,9 +805,12 @@ local function CreateOptionsControls(panel)
PrintLater(("The settings menu of %s is missing some entries."):format(addonID)) PrintLater(("The settings menu of %s is missing some entries."):format(addonID))
end end
DoCreateSettings() DoCreateSettings()
else
CreationFinished()
end end
end
return true
end
--INTERNAL FUNCTION --INTERNAL FUNCTION
--handles switching between panels --handles switching between panels
@ -392,14 +818,15 @@ local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel
local currentlySelected = lam.currentAddonPanel local currentlySelected = lam.currentAddonPanel
if currentlySelected and currentlySelected ~= panel then if currentlySelected and currentlySelected ~= panel then
currentlySelected:SetHidden(true) currentlySelected:SetHidden(true)
CloseCurrentPanel()
end end
lam.currentAddonPanel = panel lam.currentAddonPanel = panel
-- refresh visible rows to reflect panel IsHidden status -- refresh visible rows to reflect panel IsHidden status
ZO_ScrollList_RefreshVisible(lam.addonList) ZO_ScrollList_RefreshVisible(lam.addonList)
if not optionsCreated[panel:GetName()] then --if this is the first time opening this panel, create these options if not CreateOptionsControls(panel) then
CreateOptionsControls(panel) OpenCurrentPanel()
end end
cm:FireCallbacks("LAM-RefreshPanel", panel) cm:FireCallbacks("LAM-RefreshPanel", panel)
@ -460,24 +887,12 @@ function lam:RegisterOptionControls(addonID, optionsTable) --optionsTable = {sli
addonToOptionsMap[addonID] = optionsTable addonToOptionsMap[addonID] = optionsTable
end end
--INTERNAL FUNCTION --INTERNAL FUNCTION
--creates LAM's Addon Settings entry in ZO_GameMenu --creates LAM's Addon Settings entry in ZO_GameMenu
local function CreateAddonSettingsMenuEntry() 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 = { local panelData = {
id = KEYBOARD_OPTIONS.currentPanelId, id = KEYBOARD_OPTIONS.currentPanelId,
name = controlPanelNames[GetCVar("Language.2")] or controlPanelNames["en"], name = util.L["PANEL_NAME"],
} }
KEYBOARD_OPTIONS.currentPanelId = panelData.id + 1 KEYBOARD_OPTIONS.currentPanelId = panelData.id + 1
@ -753,6 +1168,17 @@ local function CreateAddonSettingsWindow()
panelContainer:SetAnchor(TOPLEFT, nil, TOPLEFT, 365, 120) panelContainer:SetAnchor(TOPLEFT, nil, TOPLEFT, 365, 120)
panelContainer:SetDimensions(645, 675) panelContainer:SetDimensions(645, 675)
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 return tlw
end end
@ -769,9 +1195,14 @@ local function OnLoad(_, addonName)
end end
em:RegisterForEvent(eventHandle, EVENT_ADD_ON_LOADED, OnLoad) em:RegisterForEvent(eventHandle, EVENT_ADD_ON_LOADED, OnLoad)
local function OnActivated(_, addonName) local function OnActivated(_, initial)
em:UnregisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED) em:UnregisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED)
FlushMessages() FlushMessages()
local reopenPanel = RetrievePanelForReopening()
if not initial and reopenPanel then
lam:OpenToPanel(reopenPanel)
end
end end
em:RegisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED, OnActivated) em:RegisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED, OnActivated)
@ -800,10 +1231,18 @@ function lam:GetAddonSettingsFragment()
if not LAMAddonSettingsFragment then if not LAMAddonSettingsFragment then
local window = CreateAddonSettingsWindow() local window = CreateAddonSettingsWindow()
LAMAddonSettingsFragment = ZO_FadeSceneFragment:New(window, true, 100) 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() CreateAddonSettingsMenuEntry()
end end
return LAMAddonSettingsFragment return LAMAddonSettingsFragment
end end
-- vi: noexpandtab

View File

@ -1,36 +1,30 @@
--[[buttonData = { --[[buttonData = {
type = "button", type = "button",
name = "My Button", name = "My Button", -- string id or function returning a string
tooltip = "Button's tooltip text.",
func = function() end, func = function() end,
tooltip = "Button's tooltip text.", -- string id or function returning a string (optional)
width = "full", --or "half" (optional) width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
icon = "icon\\path.dds", --(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) warning = "Will need to reload the UI.", --(optional)
reference = "MyAddonButton" --(optional) unique global reference to control reference = "MyAddonButton", -- unique global reference to control (optional)
} ]] } ]]
local widgetVersion = 11
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("button", widgetVersion) then return end if not LAM:RegisterWidget("button", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control) local function UpdateDisabled(control)
local disable local disable = control.data.disabled
if type(control.data.disabled) == "function" then if type(disable) == "function" then
disable = control.data.disabled() disable = disable()
else
disable = control.data.disabled
end end
control.button:SetEnabled(not disable) control.button:SetEnabled(not disable)
end end
--controlName is optional --controlName is optional
local MIN_HEIGHT = 28 -- default_button height local MIN_HEIGHT = 28 -- default_button height
local HALF_WIDTH_LINE_SPACING = 2 local HALF_WIDTH_LINE_SPACING = 2
@ -54,36 +48,44 @@ function LAMCreateControl.button(parent, buttonData, controlName)
--control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton") --control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton")
control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton") control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton")
control.button:SetWidth(width / 3) control.button:SetWidth(width / 3)
control.button:SetText(buttonData.name) control.button:SetText(LAM.util.GetStringFromValue(buttonData.name))
if buttonData.isDangerous then control.button:SetNormalFontColor(ZO_ERROR_COLOR:UnpackRGBA()) end
end end
local button = control.button local button = control.button
button:SetAnchor(control.isHalfWidth and CENTER or RIGHT) button:SetAnchor(control.isHalfWidth and CENTER or RIGHT)
button:SetClickSound("Click") button:SetClickSound("Click")
button.data = {tooltipText = LAM.util.GetTooltipText(buttonData.tooltip)} button.data = {tooltipText = LAM.util.GetStringFromValue(buttonData.tooltip)}
button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
button:SetHandler("OnClicked", function(self, ...) button:SetHandler("OnClicked", function(...)
buttonData.func(self, ...) local args = {...}
if control.panel.data.registerForRefresh then local function callback()
cm:FireCallbacks("LAM-RefreshPanel", control) buttonData.func(unpack(args))
LAM.util.RequestRefreshIfNeeded(control)
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
end) end)
if buttonData.warning then if buttonData.warning ~= nil then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0) control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0)
control.warning.data = {tooltipText = buttonData.warning} control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end end
if buttonData.disabled then if buttonData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled() control:UpdateDisabled()
end
--this is here because buttons don't have an UpdateValue method LAM.util.RegisterForRefreshIfNeeded(control)
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
return control return control
end end

View File

@ -1,24 +1,24 @@
--[[checkboxData = { --[[checkboxData = {
type = "checkbox", type = "checkbox",
name = "My Checkbox", name = "My Checkbox", -- or string id or function returning a string
tooltip = "Checkbox's tooltip text.",
getFunc = function() return db.var end, getFunc = function() return db.var end,
setFunc = function(value) db.var = value doStuff() end, setFunc = function(value) db.var = value doStuff() end,
width = "full", --or "half" (optional) 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) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional) warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
default = defaults.var, --(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)
reference = "MyAddonCheckbox" --(optional) unique global reference to control 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") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("checkbox", widgetVersion) then return end if not LAM:RegisterWidget("checkbox", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
--label --label
local enabledColor = ZO_DEFAULT_ENABLED_COLOR local enabledColor = ZO_DEFAULT_ENABLED_COLOR
local enabledHLcolor = ZO_HIGHLIGHT_TEXT local enabledHLcolor = ZO_HIGHLIGHT_TEXT
@ -57,14 +57,12 @@ end
local function UpdateValue(control, forceDefault, value) local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults if forceDefault then --if we are forcing defaults
value = control.data.default value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value) control.data.setFunc(value)
elseif value ~= nil then --our value could be false elseif value ~= nil then --our value could be false
control.data.setFunc(value) 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 --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 LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else else
value = control.data.getFunc() value = control.data.getFunc()
end end
@ -121,24 +119,24 @@ function LAMCreateControl.checkbox(parent, checkboxData, controlName)
control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper() control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper()
control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper() control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper()
if checkboxData.warning then if checkboxData.warning ~= nil or checkboxData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0) control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0)
control.warning.data = {tooltipText = checkboxData.warning} control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end end
control.data.tooltipText = LAM.util.GetTooltipText(checkboxData.tooltip) control.data.tooltipText = LAM.util.GetStringFromValue(checkboxData.tooltip)
if checkboxData.disabled then control.UpdateValue = UpdateValue
control:UpdateValue()
if checkboxData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled() control:UpdateDisabled()
end end
control.UpdateValue = UpdateValue
control: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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control) LAM.util.RegisterForReloadIfNeeded(control)
end
return control return control
end end

View File

@ -1,25 +1,23 @@
--[[colorpickerData = { --[[colorpickerData = {
type = "colorpicker", type = "colorpicker",
name = "My Color Picker", name = "My Color Picker", -- or string id or function returning a string
tooltip = "Color Picker's tooltip text.",
getFunc = function() return db.r, db.g, db.b, db.a end, --(alpha is optional) 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) 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) width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional) warning = "May cause permanent awesomeness.", -- or string id or function returning a string (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]) 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)
reference = "MyAddonColorpicker" --(optional) unique global reference to control 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") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control) local function UpdateDisabled(control)
local disable local disable
@ -40,15 +38,13 @@ end
local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA) local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA)
if forceDefault then --if we are forcing defaults if forceDefault then --if we are forcing defaults
local color = control.data.default local color = LAM.util.GetDefaultValue(control.data.default)
valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a
control.data.setFunc(valueR, valueG, valueB, valueA) control.data.setFunc(valueR, valueG, valueB, valueA)
elseif valueR and valueG and valueB then elseif valueR and valueG and valueB then
control.data.setFunc(valueR, valueG, valueB, valueA or 1) 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 --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 LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else else
valueR, valueG, valueB, valueA = control.data.getFunc() valueR, valueG, valueB, valueA = control.data.getFunc()
end end
@ -83,28 +79,28 @@ function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
if upInside then if upInside then
local r, g, b, a = colorpickerData.getFunc() local r, g, b, a = colorpickerData.getFunc()
COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, colorpickerData.name) COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, LAM.util.GetStringFromValue(colorpickerData.name))
end end
end) end)
if colorpickerData.warning then if colorpickerData.warning ~= nil or colorpickerData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0) control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0)
control.warning.data = {tooltipText = colorpickerData.warning} control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end end
control.data.tooltipText = LAM.util.GetTooltipText(colorpickerData.tooltip) control.data.tooltipText = LAM.util.GetStringFromValue(colorpickerData.tooltip)
if colorpickerData.disabled then control.UpdateValue = UpdateValue
control:UpdateValue()
if colorpickerData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled() control:UpdateDisabled()
end end
control.UpdateValue = UpdateValue
control: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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control) LAM.util.RegisterForReloadIfNeeded(control)
end
return control return control
end end

View File

@ -5,13 +5,10 @@
width = "full", --or "half" (optional) width = "full", --or "half" (optional)
} ]] } ]]
local widgetVersion = 6 local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("custom", widgetVersion) then return end if not LAM:RegisterWidget("custom", widgetVersion) then return end
local wm = WINDOW_MANAGER
local tinsert = table.insert
local function UpdateValue(control) local function UpdateValue(control)
if control.data.refreshFunc then if control.data.refreshFunc then
control.data.refreshFunc(control) control.data.refreshFunc(control)
@ -32,9 +29,7 @@ function LAMCreateControl.custom(parent, customData, controlName)
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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control)
end
return control return control
end end

View File

@ -1,27 +1,25 @@
--[[descriptionData = { --[[descriptionData = {
type = "description", type = "description",
title = "My Title", --(optional) text = "My description text to display.", -- or string id or function returning a string
text = "My description text to display.", title = "My Title", -- or string id or function returning a string (optional)
width = "full", --or "half" (optional) width = "full", --or "half" (optional)
reference = "MyAddonDescription" --(optional) unique global reference to control reference = "MyAddonDescription" -- unique global reference to control (optional)
} ]] } ]]
local widgetVersion = 6 local widgetVersion = 8
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("description", widgetVersion) then return end if not LAM:RegisterWidget("description", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local tinsert = table.insert
local function UpdateValue(control) local function UpdateValue(control)
if control.title then if control.title then
control.title:SetText(control.data.title) control.title:SetText(LAM.util.GetStringFromValue(control.data.title))
end end
control.desc:SetText(control.data.text) control.desc:SetText(LAM.util.GetStringFromValue(control.data.text))
end end
local MIN_HEIGHT = 26
function LAMCreateControl.description(parent, descriptionData, controlName) function LAMCreateControl.description(parent, descriptionData, controlName)
local control = LAM.util.CreateBaseControl(parent, descriptionData, controlName) local control = LAM.util.CreateBaseControl(parent, descriptionData, controlName)
local isHalfWidth = control.isHalfWidth local isHalfWidth = control.isHalfWidth
@ -29,16 +27,16 @@ function LAMCreateControl.description(parent, descriptionData, controlName)
control:SetResizeToFitDescendents(true) control:SetResizeToFitDescendents(true)
if isHalfWidth then if isHalfWidth then
control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4) control:SetDimensionConstraints(width / 2, 0, width / 2, 0)
else else
control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4) control:SetDimensionConstraints(width, 0, width, 0)
end end
control.desc = wm:CreateControl(nil, control, CT_LABEL) control.desc = wm:CreateControl(nil, control, CT_LABEL)
local desc = control.desc local desc = control.desc
desc:SetVerticalAlignment(TEXT_ALIGN_TOP) desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
desc:SetFont("ZoFontGame") desc:SetFont("ZoFontGame")
desc:SetText(descriptionData.text) desc:SetText(LAM.util.GetStringFromValue(descriptionData.text))
desc:SetWidth(isHalfWidth and width / 2 or width) desc:SetWidth(isHalfWidth and width / 2 or width)
if descriptionData.title then if descriptionData.title then
@ -47,7 +45,7 @@ function LAMCreateControl.description(parent, descriptionData, controlName)
title:SetWidth(isHalfWidth and width / 2 or width) title:SetWidth(isHalfWidth and width / 2 or width)
title:SetAnchor(TOPLEFT, control, TOPLEFT) title:SetAnchor(TOPLEFT, control, TOPLEFT)
title:SetFont("ZoFontWinH4") title:SetFont("ZoFontWinH4")
title:SetText(descriptionData.title) title:SetText(LAM.util.GetStringFromValue(descriptionData.title))
desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT) desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT)
else else
desc:SetAnchor(TOPLEFT) desc:SetAnchor(TOPLEFT)
@ -55,9 +53,7 @@ function LAMCreateControl.description(parent, descriptionData, controlName)
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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control)
end
return control return control

View File

@ -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

View File

@ -1,27 +1,40 @@
--[[dropdownData = { --[[dropdownData = {
type = "dropdown", type = "dropdown",
name = "My Dropdown", name = "My Dropdown", -- or string id or function returning a string
tooltip = "Dropdown's tooltip text.",
choices = {"table", "of", "choices"}, choices = {"table", "of", "choices"},
sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted choicesValues = {"foo", 2, "three"}, -- if specified, these values will get passed to setFunc instead (optional)
getFunc = function() return db.var end, getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() 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) 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) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional) warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
default = defaults.var, --(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)
reference = "MyAddonDropdown" --(optional) unique global reference to control 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") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("dropdown", widgetVersion) then return end if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER local SORT_BY_VALUE = { ["value"] = {} }
local tinsert = table.insert 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 function UpdateDisabled(control)
local disable local disable
@ -41,33 +54,93 @@ end
local function UpdateValue(control, forceDefault, value) local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults if forceDefault then --if we are forcing defaults
value = control.data.default value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value) control.data.setFunc(value)
control.dropdown:SetSelectedItem(value) control.dropdown:SetSelectedItem(control.choices[value])
elseif value then elseif value then
control.data.setFunc(value) 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 --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 LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else else
value = control.data.getFunc() value = control.data.getFunc()
control.dropdown:SetSelectedItem(value) control.dropdown:SetSelectedItem(control.choices[value])
end end
end end
local function DropdownCallback(control, choiceText, choice) local function DropdownCallback(control, choiceText, choice)
choice.control:UpdateValue(false, choiceText) choice.control:UpdateValue(false, choice.value or choiceText)
end end
local function UpdateChoices(control, choices) 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
-- 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()?) control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?)
ZO_ClearTable(control.choices)
--build new list of choices --build new list of choices
local choices = choices or control.data.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 for i = 1, #choices do
local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback) local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback)
entry.control = control 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 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
end end
@ -82,8 +155,174 @@ local function GrabSortingInfo(sortInfo)
return t return t
end 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) 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 countControl = parent
local name = parent:GetName() local name = parent:GetName()
@ -93,7 +332,7 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
end end
local comboboxCount = (countControl.comboboxCount or 0) + 1 local comboboxCount = (countControl.comboboxCount or 0) + 1
countControl.comboboxCount = comboboxCount countControl.comboboxCount = comboboxCount
control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, "ZO_ComboBox") control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, dropdownData.scrollable and "ZO_ScrollableComboBox" or "ZO_ComboBox")
local combobox = control.combobox local combobox = control.combobox
combobox:SetAnchor(TOPLEFT) combobox:SetAnchor(TOPLEFT)
@ -102,30 +341,47 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox) control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox)
local dropdown = control.dropdown local dropdown = control.dropdown
dropdown:SetSortsItems(false) -- need to sort ourselves in order to be able to sort by value
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
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 dropdownData.sort then if dropdownData.sort then
local sortInfo = GrabSortingInfo(dropdownData.sort) local sortInfo = GrabSortingInfo(dropdownData.sort)
local sortType, sortOrder = sortInfo[1], sortInfo[2] control.m_sortType, control.m_sortOrder = SORT_TYPES[sortInfo[1]], SORT_ORDERS[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) elseif dropdownData.choicesValues then
control.m_sortType, control.m_sortOrder = ZO_SORT_ORDER_UP, SORT_BY_VALUE
end end
if dropdownData.warning then if dropdownData.warning ~= nil or dropdownData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0) control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0)
control.warning.data = {tooltipText = dropdownData.warning} control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end end
if dropdownData.disabled then control.UpdateChoices = UpdateChoices
control:UpdateChoices(dropdownData.choices, dropdownData.choicesValues)
control.UpdateValue = UpdateValue
control:UpdateValue()
if dropdownData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled() control:UpdateDisabled()
end end
control.UpdateChoices = UpdateChoices
control:UpdateChoices(dropdownData.choices)
control.UpdateValue = UpdateValue
control: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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control) LAM.util.RegisterForReloadIfNeeded(control)
end
return control return control
end end

View File

@ -1,26 +1,25 @@
--[[editboxData = { --[[editboxData = {
type = "editbox", type = "editbox",
name = "My Editbox", name = "My Editbox", -- or string id or function returning a string
tooltip = "Editbox's tooltip text.",
getFunc = function() return db.text end, getFunc = function() return db.text end,
setFunc = function(text) db.text = text doStuff() end, setFunc = function(text) db.text = text doStuff() end,
isMultiline = true, --boolean 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) width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional) warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
default = defaults.text, --(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)
reference = "MyAddonEditbox" --(optional) unique global reference to control 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") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("editbox", widgetVersion) then return end if not LAM:RegisterWidget("editbox", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control) local function UpdateDisabled(control)
local disable local disable
@ -43,22 +42,20 @@ end
local function UpdateValue(control, forceDefault, value) local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults if forceDefault then --if we are forcing defaults
value = control.data.default value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value) control.data.setFunc(value)
control.editbox:SetText(value) control.editbox:SetText(value)
elseif value then elseif value then
control.data.setFunc(value) 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 --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 LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else else
value = control.data.getFunc() value = control.data.getFunc()
control.editbox:SetText(value) control.editbox:SetText(value)
end end
end end
local MIN_HEIGHT = 26 local MIN_HEIGHT = 24
local HALF_WIDTH_LINE_SPACING = 2 local HALF_WIDTH_LINE_SPACING = 2
function LAMCreateControl.editbox(parent, editboxData, controlName) function LAMCreateControl.editbox(parent, editboxData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, editboxData, controlName) local control = LAM.util.CreateLabelAndContainerControl(parent, editboxData, controlName)
@ -100,37 +97,60 @@ function LAMCreateControl.editbox(parent, editboxData, controlName)
editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end) editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
if not editboxData.isMultiline then local MIN_WIDTH = (parent.GetWidth and (parent:GetWidth() / 10)) or (parent.panel.GetWidth and (parent.panel:GetWidth() / 10)) or 0
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)
if control.lineControl then control.label:ClearAnchors()
control.lineControl:SetHeight(MIN_HEIGHT + height + HALF_WIDTH_LINE_SPACING) container:ClearAnchors()
else
control:SetHeight(height) control.label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0)
end container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0)
if control.isHalfWidth then
container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0)
end end
if editboxData.warning then if editboxData.isExtraWide then
container:SetAnchor(BOTTOMLEFT, control, BOTTOMLEFT, 0, 0)
else
container:SetWidth(MIN_WIDTH * 3.2)
end
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") 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) control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0)
control.warning.data = {tooltipText = editboxData.warning} end
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end end
if editboxData.disabled then control.UpdateValue = UpdateValue
control:UpdateValue()
if editboxData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled() control:UpdateDisabled()
end end
control.UpdateValue = UpdateValue
control: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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control) LAM.util.RegisterForReloadIfNeeded(control)
end
return control return control
end end

View File

@ -1,20 +1,19 @@
--[[headerData = { --[[headerData = {
type = "header", type = "header",
name = "My Header", name = "My Header", -- or string id or function returning a string
width = "full", --or "half" (optional) width = "full", --or "half" (optional)
reference = "MyAddonHeader" --(optional) unique global reference to control reference = "MyAddonHeader" -- unique global reference to control (optional)
} ]] } ]]
local widgetVersion = 6 local widgetVersion = 8
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("header", widgetVersion) then return end if not LAM:RegisterWidget("header", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local tinsert = table.insert
local function UpdateValue(control) local function UpdateValue(control)
control.header:SetText(control.data.name) control.header:SetText(LAM.util.GetStringFromValue(control.data.name))
end end
local MIN_HEIGHT = 30 local MIN_HEIGHT = 30
@ -33,13 +32,11 @@ function LAMCreateControl.header(parent, headerData, controlName)
local header = control.header local header = control.header
header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT) header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT)
header:SetAnchor(BOTTOMRIGHT) header:SetAnchor(BOTTOMRIGHT)
header:SetText(headerData.name) 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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control)
end
return control return control
end end

View File

@ -1,30 +1,29 @@
--[[iconpickerData = { --[[iconpickerData = {
type = "iconpicker", type = "iconpicker",
name = "My Icon Picker", name = "My Icon Picker", -- or string id or function returning a string
tooltip = "Color Picker's tooltip text.",
choices = {"texture path 1", "texture path 2", "texture path 3"}, 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, getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() end, setFunc = function(var) db.var = var doStuff() end,
maxColumns = 5, --(optional) number of icons in one row tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional)
visibleRows = 4.5, --(optional) number of visible rows choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, -- or array of string ids or array of functions returning a string (optional)
iconSize = 28, --(optional) size of the icons maxColumns = 5, -- number of icons in one row (optional)
defaultColor = ZO_ColorDef:New("FFFFFF"), --(optional) default color of the icons 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) width = "full", --or "half" (optional)
beforeShow = function(control, iconPicker) return preventShow end, --(optional) beforeShow = function(control, iconPicker) return preventShow end, --(optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional) warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
default = defaults.var, --(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)
reference = "MyAddonIconPicker" --(optional) unique global reference to control 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") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("iconpicker", widgetVersion) then return end if not LAM:RegisterWidget("iconpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local IconPickerMenu = ZO_Object:Subclass() local IconPickerMenu = ZO_Object:Subclass()
local iconPicker local iconPicker
@ -136,7 +135,7 @@ end
function IconPickerMenu:OnMouseEnter(icon) function IconPickerMenu:OnMouseEnter(icon)
InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT) InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT)
SetTooltipText(InformationTooltip, LAM.util.GetTooltipText(icon.tooltip)) SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(icon.tooltip))
InformationTooltipTopLevel:BringWindowToTop() InformationTooltipTopLevel:BringWindowToTop()
end end
@ -253,7 +252,7 @@ end
local function UpdateChoices(control, choices, choicesTooltips) local function UpdateChoices(control, choices, choicesTooltips)
local data = control.data local data = control.data
if not choices then if not choices then
choices, choicesTooltips = data.choices, data.choicesTooltips choices, choicesTooltips = data.choices, data.choicesTooltips or {}
end end
local addedChoices = {} local addedChoices = {}
@ -265,10 +264,8 @@ local function UpdateChoices(control, choices, choicesTooltips)
iconPicker:AddIcon(choices[i], function(self, texture) iconPicker:AddIcon(choices[i], function(self, texture)
control.icon:SetTexture(texture) control.icon:SetTexture(texture)
data.setFunc(texture) data.setFunc(texture)
if control.panel.data.registerForRefresh then LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control) end, LAM.util.GetStringFromValue(choicesTooltips[i]))
end
end, choicesTooltips[i])
addedChoices[texture] = true addedChoices[texture] = true
end end
end end
@ -308,7 +305,7 @@ local function UpdateDisabled(control)
iconPicker:Clear() iconPicker:Clear()
end end
SetColor(control) SetColor(control, control.icon.color)
if disable then if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA()) control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else else
@ -318,15 +315,13 @@ end
local function UpdateValue(control, forceDefault, value) local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults if forceDefault then --if we are forcing defaults
value = control.data.default value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value) control.data.setFunc(value)
control.icon:SetTexture(value) control.icon:SetTexture(value)
elseif value then elseif value then
control.data.setFunc(value) 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 --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 LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else else
value = control.data.getFunc() value = control.data.getFunc()
control.icon:SetTexture(value) control.icon:SetTexture(value)
@ -414,15 +409,11 @@ function LAMCreateControl.iconpicker(parent, iconpickerData, controlName)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP) mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill() mungeOverlay:SetAnchorFill()
if iconpickerData.warning then if iconpickerData.warning ~= nil or iconpickerData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0) control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0)
control.warning.data = {tooltipText = iconpickerData.warning} control.UpdateWarning = LAM.util.UpdateWarning
end control:UpdateWarning()
if iconpickerData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end end
control.UpdateChoices = UpdateChoices control.UpdateChoices = UpdateChoices
@ -433,9 +424,13 @@ function LAMCreateControl.iconpicker(parent, iconpickerData, controlName)
control.SetIconSize = SetIconSize control.SetIconSize = SetIconSize
control:SetIconSize(iconSize) 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 if iconpickerData.disabled ~= nil then
tinsert(control.panel.controlsToRefresh, control) control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control return control
end end

View File

@ -1,18 +1,19 @@
--[[panelData = { --[[panelData = {
type = "panel", type = "panel",
name = "Window Title", name = "Window Title", -- or string id or function returning a string
displayName = "My Longer Window Title", --(optional) (can be useful for long addon names or if you want to colorize it) 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", --(optional) author = "Seerah", -- or string id or function returning a string (optional)
version = "2.0", --(optional) version = "2.0", -- or string id or function returning a string (optional)
keywords = "settings", --(optional) additional keywords for search filter (it looks for matches in name..keywords..author) website = "http://www.esoui.com/downloads/info7-LibAddonMenu.html", -- URL of website where the addon can be updated (optional)
slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel (don't forget to include the slash!) 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) 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) 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 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") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("panel", widgetVersion) then return end if not LAM:RegisterWidget("panel", widgetVersion) then return end
@ -20,18 +21,19 @@ local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER local cm = CALLBACK_MANAGER
local function RefreshPanel(control) local function RefreshPanel(control)
local panel = control.panel or control --callback can be fired by a single control or by the panel showing 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 local panelControls = panel.controlsToRefresh
for i = 1, #panelControls do for i = 1, #panelControls do
local updateControl = panelControls[i] local updateControl = panelControls[i]
if updateControl ~= control then if updateControl ~= control and updateControl.UpdateValue then
if updateControl.UpdateValue then
updateControl:UpdateValue() updateControl:UpdateValue()
end end
if updateControl.UpdateDisabled then if updateControl.UpdateDisabled then
updateControl:UpdateDisabled() updateControl:UpdateDisabled()
end end
if updateControl.UpdateWarning then
updateControl:UpdateWarning()
end end
end end
end end
@ -52,47 +54,55 @@ local function ForceDefaults(panel)
cm:FireCallbacks("LAM-RefreshPanel", panel) cm:FireCallbacks("LAM-RefreshPanel", panel)
end 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 local callbackRegistered = false
LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1 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) 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") control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local label = control.label local label = control.label
label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4) label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4)
label:SetText(panelData.displayName or panelData.name) label:SetText(LAM.util.GetStringFromValue(panelData.displayName or panelData.name))
if panelData.author or panelData.version then if panelData.author or panelData.version then
control.info = wm:CreateControl(nil, control, CT_LABEL) control.info = wm:CreateControl(nil, control, CT_LABEL)
local info = control.info local info = control.info
info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin") info:SetFont(LAM.util.L["PANEL_INFO_FONT"])
info:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, -2) 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)) local output = {}
elseif panelData.author then if panelData.author then
info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author)) output[#output + 1] = zo_strformat(LAM.util.L["AUTHOR"], LAM.util.GetStringFromValue(panelData.author))
else
info:SetText("Version: "..panelData.version)
end 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.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 end
control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer") control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer")
@ -103,30 +113,14 @@ function LAMCreateControl.panel(parent, panelData, controlName)
control.scroll = GetControl(control.container, "ScrollChild") control.scroll = GetControl(control.container, "ScrollChild")
control.scroll:SetResizeToFitPadding(0, 20) control.scroll:SetResizeToFitPadding(0, 20)
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.registerForRefresh and not callbackRegistered then --don't want to register our callback more than once if panelData.registerForRefresh and not callbackRegistered then --don't want to register our callback more than once
cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel) cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel)
callbackRegistered = true callbackRegistered = true
end end
control.ForceDefaults = ForceDefaults
control.data = panelData control.data = panelData
control.controlsToRefresh = {} control.controlsToRefresh = {}
return control return control
end end
-- vi: noexpandtab

View File

@ -1,29 +1,34 @@
--[[sliderData = { --[[sliderData = {
type = "slider", type = "slider",
name = "My Slider", name = "My Slider", -- or string id or function returning a string
tooltip = "Slider's tooltip text.", getFunc = function() return db.var end,
setFunc = function(value) db.var = value doStuff() end,
min = 0, min = 0,
max = 20, max = 20,
step = 1, --(optional) step = 1, --(optional)
getFunc = function() return db.var end, clampInput = true, -- boolean, if set to false the input won't clamp to min and max and allow any number instead (optional)
setFunc = function(value) db.var = value doStuff() end, 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) width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional) disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional) warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
default = defaults.var, --(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)
reference = "MyAddonSlider" --(optional) unique global reference to control default = defaults.var, -- default value or function that returns the default value (optional)
reference = "MyAddonSlider" -- unique global reference to control (optional)
} ]] } ]]
local widgetVersion = 12
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("slider", widgetVersion) then return end if not LAM:RegisterWidget("slider", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local round = zo_round
local strformat = string.format 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 function UpdateDisabled(control)
local disable local disable
@ -50,14 +55,18 @@ end
local function UpdateValue(control, forceDefault, value) local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults if forceDefault then --if we are forcing defaults
value = control.data.default value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value) control.data.setFunc(value)
elseif value and value >= control.data.min and value <= control.data.max then 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) 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 --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 LAM.util.RequestRefreshIfNeeded(control)
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else else
value = control.data.getFunc() value = control.data.getFunc()
end end
@ -66,16 +75,20 @@ local function UpdateValue(control, forceDefault, value)
control.slidervalue:SetText(value) control.slidervalue:SetText(value)
end end
function LAMCreateControl.slider(parent, sliderData, controlName) 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? --skipping creating the backdrop... Is this the actual slider texture?
control.slider = wm:CreateControl(nil, control.container, CT_SLIDER) control.slider = wm:CreateControl(nil, control.container, CT_SLIDER)
local slider = control.slider local slider = control.slider
slider:SetAnchor(TOPLEFT) slider:SetAnchor(TOPLEFT)
slider:SetAnchor(TOPRIGHT)
slider:SetHeight(14) slider:SetHeight(14)
if(isInputOnRight) then
slider:SetAnchor(TOPRIGHT, nil, nil, -60)
else
slider:SetAnchor(TOPRIGHT)
end
slider:SetMouseEnabled(true) slider:SetMouseEnabled(true)
slider:SetOrientation(ORIENTATION_HORIZONTAL) slider:SetOrientation(ORIENTATION_HORIZONTAL)
--put nil for highlighted texture file path, and what look to be texture coords --put nil for highlighted texture file path, and what look to be texture coords
@ -84,7 +97,7 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
local maxValue = sliderData.max local maxValue = sliderData.max
slider:SetMinMax(minValue, maxValue) slider:SetMinMax(minValue, maxValue)
slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end) slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseExit(control) end) slider:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP) slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP)
local bg = slider.bg local bg = slider.bg
@ -106,52 +119,94 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
maxText:SetText(sliderData.max) maxText:SetText(sliderData.max)
control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop") 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:SetDimensions(50, 16)
control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0) control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0)
end
control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop") control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop")
local slidervalue = control.slidervalue local slidervalue = control.slidervalue
slidervalue:ClearAnchors() slidervalue:ClearAnchors()
slidervalue:SetAnchor(TOPLEFT, control.slidervalueBG, TOPLEFT, 3, 1) slidervalue:SetAnchor(TOPLEFT, control.slidervalueBG, TOPLEFT, 3, 1)
slidervalue:SetAnchor(BOTTOMRIGHT, control.slidervalueBG, BOTTOMRIGHT, -3, -1) slidervalue:SetAnchor(BOTTOMRIGHT, control.slidervalueBG, BOTTOMRIGHT, -3, -1)
slidervalue:SetTextType(TEXT_TYPE_NUMERIC) slidervalue:SetTextType(TEXT_TYPE_NUMERIC)
if(isInputOnRight) then
slidervalue:SetFont("ZoFontGameLarge")
else
slidervalue:SetFont("ZoFontGameSmall") slidervalue:SetFont("ZoFontGameSmall")
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
slidervalue:SetHandler("OnEscape", function(self) slidervalue:SetHandler("OnEscape", function(self)
HandleValueChanged(sliderData.getFunc())
self:LoseFocus() self:LoseFocus()
control:UpdateValue()
end) end)
slidervalue:SetHandler("OnEnter", function(self) slidervalue:SetHandler("OnEnter", function(self)
self:LoseFocus() self:LoseFocus()
control:UpdateValue(false, tonumber(self:GetText()))
end) 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
local range = maxValue - minValue local range = maxValue - minValue
slider:SetValueStep(sliderData.step or 1) slider:SetValueStep(sliderData.step or 1)
slider:SetHandler("OnValueChanged", function(self, value, eventReason) slider:SetHandler("OnValueChanged", function(self, value, eventReason)
if eventReason == EVENT_REASON_SOFTWARE then return end if eventReason == EVENT_REASON_SOFTWARE then return end
self:SetValue(value) --do we actually need this line? HandleValueChanged(value)
slidervalue:SetText(value)
end) end)
slider:SetHandler("OnSliderReleased", function(self, value) slider:SetHandler("OnSliderReleased", function(self, value)
--sliderData.setFunc(value) control:UpdateValue(false, value)
control:UpdateValue(false, value) --does this work here instead? 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) end)
if sliderData.warning then if sliderData.warning ~= nil or sliderData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0) control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0)
control.warning.data = {tooltipText = sliderData.warning} control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end end
if sliderData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateValue = UpdateValue control.UpdateValue = UpdateValue
control:UpdateValue() control: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 if sliderData.disabled ~= nil then
tinsert(control.panel.controlsToRefresh, control) control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control return control
end end

View File

@ -1,24 +1,22 @@
--[[submenuData = { --[[submenuData = {
type = "submenu", type = "submenu",
name = "Submenu Title", name = "Submenu Title", -- or string id or function returning a string
tooltip = "My submenu tooltip", --(optional) tooltip = "My submenu tooltip", -- -- or string id or function returning a string (optional)
controls = {sliderData, buttonData} --(optional) used by LAM controls = {sliderData, buttonData} --(optional) used by LAM
reference = "MyAddonSubmenu" --(optional) unique global reference to control reference = "MyAddonSubmenu" --(optional) unique global reference to control
} ]] } ]]
local widgetVersion = 9 local widgetVersion = 11
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("submenu", widgetVersion) then return end if not LAM:RegisterWidget("submenu", widgetVersion) then return end
local wm = WINDOW_MANAGER local wm = WINDOW_MANAGER
local am = ANIMATION_MANAGER local am = ANIMATION_MANAGER
local tinsert = table.insert
local function UpdateValue(control) local function UpdateValue(control)
control.label:SetText(control.data.name) control.label:SetText(LAM.util.GetStringFromValue(control.data.name))
if control.data.tooltip then if control.data.tooltip then
control.label.data.tooltipText = LAM.util.GetTooltipText(control.data.tooltip) control.label.data.tooltipText = LAM.util.GetStringFromValue(control.data.tooltip)
end end
end end
@ -44,10 +42,10 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5) label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
label:SetDimensions(width, 30) label:SetDimensions(width, 30)
label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS) label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
label:SetText(submenuData.name) label:SetText(LAM.util.GetStringFromValue(submenuData.name))
label:SetMouseEnabled(true) label:SetMouseEnabled(true)
if submenuData.tooltip then if submenuData.tooltip then
label.data = {tooltipText = LAM.util.GetTooltipText(submenuData.tooltip)} label.data = {tooltipText = LAM.util.GetStringFromValue(submenuData.tooltip)}
label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
end end
@ -56,7 +54,7 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
local scroll = control.scroll local scroll = control.scroll
scroll:SetParent(control) scroll:SetParent(control)
scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10) scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10)
scroll:SetDimensionConstraints(width + 5, 0, width + 5, 2500) scroll:SetDimensionConstraints(width + 5, 0, width + 5, 0)
control.bg = wm:CreateControl(nil, label, CT_BACKDROP) control.bg = wm:CreateControl(nil, label, CT_BACKDROP)
local bg = control.bg local bg = control.bg
@ -104,9 +102,7 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
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 LAM.util.RegisterForRefreshIfNeeded(control)
tinsert(control.panel.controlsToRefresh, control)
end
return control return control
end end

View File

@ -3,14 +3,14 @@
image = "file/path.dds", image = "file/path.dds",
imageWidth = 64, --max of 250 for half width, 510 for full imageWidth = 64, --max of 250 for half width, 510 for full
imageHeight = 32, --max of 100 imageHeight = 32, --max of 100
tooltip = "Image's tooltip text.", --(optional) tooltip = "Image's tooltip text.", -- or string id or function returning a string (optional)
width = "full", --or "half" (optional) width = "full", --or "half" (optional)
reference = "MyAddonTexture" --(optional) unique global reference to control reference = "MyAddonTexture" --(optional) unique global reference to control
} ]] } ]]
--add texture coords support? --add texture coords support?
local widgetVersion = 7 local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0") local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("texture", widgetVersion) then return end if not LAM:RegisterWidget("texture", widgetVersion) then return end
@ -36,9 +36,9 @@ function LAMCreateControl.texture(parent, textureData, controlName)
if textureData.tooltip then if textureData.tooltip then
texture:SetMouseEnabled(true) texture:SetMouseEnabled(true)
texture.data = {tooltipText = LAM.util.GetTooltipText(textureData.tooltip)} texture.data = {tooltipText = LAM.util.GetStringFromValue(textureData.tooltip)}
texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit) texture:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
end end
return control return control

View File

@ -3,7 +3,7 @@
-- LibStub developed for World of Warcraft by above members of the WowAce community. -- LibStub developed for World of Warcraft by above members of the WowAce community.
-- Ported to Elder Scrolls Online by Seerah -- 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 LibStub = _G[LIBSTUB_MAJOR]
local strformat = string.format 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 function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary }) setmetatable(LibStub, { __call = LibStub.GetLibrary })
end end
LibStub.SILENT = true