elderscrolls-addon-achievem.../Libs/LibAddonMenu-2.0/controls/iconpicker.lua

437 lines
16 KiB
Lua

--[[iconpickerData = {
type = "iconpicker",
name = "My Icon Picker", -- or string id or function returning a string
choices = {"texture path 1", "texture path 2", "texture path 3"},
getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() end,
tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional)
choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, -- or array of string ids or array of functions returning a string (optional)
maxColumns = 5, -- number of icons in one row (optional)
visibleRows = 4.5, -- number of visible rows (optional)
iconSize = 28, -- size of the icons (optional)
defaultColor = ZO_ColorDef:New("FFFFFF"), -- default color of the icons (optional)
width = "full", --or "half" (optional)
beforeShow = function(control, iconPicker) return preventShow end, --(optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = defaults.var, -- default value or function that returns the default value (optional)
reference = "MyAddonIconPicker" -- unique global reference to control (optional)
} ]]
local widgetVersion = 8
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("iconpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER
local IconPickerMenu = ZO_Object:Subclass()
local iconPicker
LAM.util.GetIconPickerMenu = function()
if not iconPicker then
iconPicker = IconPickerMenu:New("LAMIconPicker")
local sceneFragment = LAM:GetAddonSettingsFragment()
ZO_PreHook(sceneFragment, "OnHidden", function()
if not iconPicker.control:IsHidden() then
iconPicker:Clear()
end
end)
end
return iconPicker
end
function IconPickerMenu:New(...)
local object = ZO_Object.New(self)
object:Initialize(...)
return object
end
function IconPickerMenu:Initialize(name)
local control = wm:CreateTopLevelWindow(name)
control:SetDrawTier(DT_HIGH)
control:SetHidden(true)
self.control = control
local scrollContainer = wm:CreateControlFromVirtual(name .. "ScrollContainer", control, "ZO_ScrollContainer")
-- control:SetDimensions(control.container:GetWidth(), height) -- adjust to icon size / col count
scrollContainer:SetAnchorFill()
ZO_Scroll_SetUseFadeGradient(scrollContainer, false)
ZO_Scroll_SetHideScrollbarOnDisable(scrollContainer, false)
ZO_VerticalScrollbarBase_OnMouseExit(scrollContainer:GetNamedChild("ScrollBar")) -- scrollbar initialization seems to be broken so we force it to update the correct alpha value
local scroll = GetControl(scrollContainer, "ScrollChild")
self.scroll = scroll
self.scrollContainer = scrollContainer
local bg = wm:CreateControl(nil, scrollContainer, CT_BACKDROP)
bg:SetAnchor(TOPLEFT, scrollContainer, TOPLEFT, 0, -3)
bg:SetAnchor(BOTTOMRIGHT, scrollContainer, BOTTOMRIGHT, 2, 5)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE)
mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds")
mungeOverlay:SetDrawLevel(1)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill()
local mouseOver = wm:CreateControl(nil, scrollContainer, CT_TEXTURE)
mouseOver:SetDrawLevel(2)
mouseOver:SetTexture("EsoUI/Art/Buttons/minmax_mouseover.dds")
mouseOver:SetHidden(true)
local function IconFactory(pool)
local icon = wm:CreateControl(name .. "Entry" .. pool:GetNextControlId(), scroll, CT_TEXTURE)
icon:SetMouseEnabled(true)
icon:SetDrawLevel(3)
icon:SetHandler("OnMouseEnter", function()
mouseOver:SetAnchor(TOPLEFT, icon, TOPLEFT, 0, 0)
mouseOver:SetAnchor(BOTTOMRIGHT, icon, BOTTOMRIGHT, 0, 0)
mouseOver:SetHidden(false)
if self.customOnMouseEnter then
self.customOnMouseEnter(icon)
else
self:OnMouseEnter(icon)
end
end)
icon:SetHandler("OnMouseExit", function()
mouseOver:ClearAnchors()
mouseOver:SetHidden(true)
if self.customOnMouseExit then
self.customOnMouseExit(icon)
else
self:OnMouseExit(icon)
end
end)
icon:SetHandler("OnMouseUp", function(control, ...)
PlaySound("Click")
icon.OnSelect(icon, icon.texture)
self:Clear()
end)
return icon
end
local function ResetFunction(icon)
icon:ClearAnchors()
end
self.iconPool = ZO_ObjectPool:New(IconFactory, ResetFunction)
self:SetMaxColumns(1)
self.icons = {}
self.color = ZO_DEFAULT_ENABLED_COLOR
EVENT_MANAGER:RegisterForEvent(name .. "_OnGlobalMouseUp", EVENT_GLOBAL_MOUSE_UP, function()
if self.refCount ~= nil then
local moc = wm:GetMouseOverControl()
if(moc:GetOwningWindow() ~= control) then
self.refCount = self.refCount - 1
if self.refCount <= 0 then
self:Clear()
end
end
end
end)
end
function IconPickerMenu:OnMouseEnter(icon)
InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT)
SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(icon.tooltip))
InformationTooltipTopLevel:BringWindowToTop()
end
function IconPickerMenu:OnMouseExit(icon)
ClearTooltip(InformationTooltip)
end
function IconPickerMenu:SetMaxColumns(value)
self.maxCols = value ~= nil and value or 5
end
local DEFAULT_SIZE = 28
function IconPickerMenu:SetIconSize(value)
local iconSize = DEFAULT_SIZE
if value ~= nil then iconSize = math.max(iconSize, value) end
self.iconSize = iconSize
end
function IconPickerMenu:SetVisibleRows(value)
self.visibleRows = value ~= nil and value or 4.5
end
function IconPickerMenu:SetMouseHandlers(onEnter, onExit)
self.customOnMouseEnter = onEnter
self.customOnMouseExit = onExit
end
function IconPickerMenu:UpdateDimensions()
local iconSize = self.iconSize
local width = iconSize * self.maxCols + 20
local height = iconSize * self.visibleRows
self.control:SetDimensions(width, height)
local icons = self.icons
for i = 1, #icons do
local icon = icons[i]
icon:SetDimensions(iconSize, iconSize)
end
end
function IconPickerMenu:UpdateAnchors()
local iconSize = self.iconSize
local col, maxCols = 1, self.maxCols
local previousCol, previousRow
local scroll = self.scroll
local icons = self.icons
for i = 1, #icons do
local icon = icons[i]
icon:ClearAnchors()
if i == 1 then
icon:SetAnchor(TOPLEFT, scroll, TOPLEFT, 0, 0)
previousRow = icon
elseif col == 1 then
icon:SetAnchor(TOPLEFT, previousRow, BOTTOMLEFT, 0, 0)
previousRow = icon
else
icon:SetAnchor(TOPLEFT, previousCol, TOPRIGHT, 0, 0)
end
previousCol = icon
col = col >= maxCols and 1 or col + 1
end
end
function IconPickerMenu:Clear()
self.icons = {}
self.iconPool:ReleaseAllObjects()
self.control:SetHidden(true)
self.color = ZO_DEFAULT_ENABLED_COLOR
self.refCount = nil
self.parent = nil
self.customOnMouseEnter = nil
self.customOnMouseExit = nil
end
function IconPickerMenu:AddIcon(texturePath, callback, tooltip)
local icon, key = self.iconPool:AcquireObject()
icon:SetTexture(texturePath)
icon:SetColor(self.color:UnpackRGBA())
icon.texture = texturePath
icon.tooltip = tooltip
icon.OnSelect = callback
self.icons[#self.icons + 1] = icon
end
function IconPickerMenu:Show(parent)
if #self.icons == 0 then return false end
if not self.control:IsHidden() then self:Clear() return false end
self:UpdateDimensions()
self:UpdateAnchors()
local control = self.control
control:ClearAnchors()
control:SetAnchor(TOPLEFT, parent, BOTTOMLEFT, 0, 8)
control:SetHidden(false)
control:BringWindowToTop()
self.parent = parent
self.refCount = 2
return true
end
function IconPickerMenu:SetColor(color)
local icons = self.icons
self.color = color
for i = 1, #icons do
local icon = icons[i]
icon:SetColor(color:UnpackRGBA())
end
end
-------------------------------------------------------------
local function UpdateChoices(control, choices, choicesTooltips)
local data = control.data
if not choices then
choices, choicesTooltips = data.choices, data.choicesTooltips or {}
end
local addedChoices = {}
local iconPicker = LAM.util.GetIconPickerMenu()
iconPicker:Clear()
for i = 1, #choices do
local texture = choices[i]
if not addedChoices[texture] then -- remove duplicates
iconPicker:AddIcon(choices[i], function(self, texture)
control.icon:SetTexture(texture)
data.setFunc(texture)
LAM.util.RequestRefreshIfNeeded(control)
end, LAM.util.GetStringFromValue(choicesTooltips[i]))
addedChoices[texture] = true
end
end
end
local function IsDisabled(control)
if type(control.data.disabled) == "function" then
return control.data.disabled()
else
return control.data.disabled
end
end
local function SetColor(control, color)
local icon = control.icon
if IsDisabled(control) then
icon:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
icon.color = color or control.data.defaultColor or ZO_DEFAULT_ENABLED_COLOR
icon:SetColor(icon.color:UnpackRGBA())
end
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:SetColor(icon.color)
end
end
local function UpdateDisabled(control)
local disable = IsDisabled(control)
control.dropdown:SetMouseEnabled(not disable)
control.dropdownButton:SetEnabled(not disable)
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:Clear()
end
SetColor(control, control.icon.color)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value)
control.icon:SetTexture(value)
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
value = control.data.getFunc()
control.icon:SetTexture(value)
end
end
local MIN_HEIGHT = 26
local HALF_WIDTH_LINE_SPACING = 2
local function SetIconSize(control, size)
local icon = control.icon
icon.size = size
icon:SetDimensions(size, size)
local height = size + 4
control.dropdown:SetDimensions(size + 20, height)
height = math.max(height, MIN_HEIGHT)
control.container:SetHeight(height)
if control.lineControl then
control.lineControl:SetHeight(MIN_HEIGHT + size + HALF_WIDTH_LINE_SPACING)
else
control:SetHeight(height)
end
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:SetIconSize(size)
iconPicker:UpdateDimensions()
iconPicker:UpdateAnchors()
end
end
function LAMCreateControl.iconpicker(parent, iconpickerData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, iconpickerData, controlName)
local function ShowIconPicker()
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container then
iconPicker:Clear()
else
iconPicker:SetMaxColumns(iconpickerData.maxColumns)
iconPicker:SetVisibleRows(iconpickerData.visibleRows)
iconPicker:SetIconSize(control.icon.size)
UpdateChoices(control)
iconPicker:SetColor(control.icon.color)
if iconpickerData.beforeShow then
if iconpickerData.beforeShow(control, iconPicker) then
iconPicker:Clear()
return
end
end
iconPicker:Show(control.container)
end
end
local iconSize = iconpickerData.iconSize ~= nil and iconpickerData.iconSize or DEFAULT_SIZE
control.dropdown = wm:CreateControl(nil, control.container, CT_CONTROL)
local dropdown = control.dropdown
dropdown:SetAnchor(LEFT, control.container, LEFT, 0, 0)
dropdown:SetMouseEnabled(true)
dropdown:SetHandler("OnMouseUp", ShowIconPicker)
dropdown:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
dropdown:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
control.icon = wm:CreateControl(nil, dropdown, CT_TEXTURE)
local icon = control.icon
icon:SetAnchor(LEFT, dropdown, LEFT, 3, 0)
icon:SetDrawLevel(2)
local dropdownButton = wm:CreateControlFromVirtual(nil, dropdown, "ZO_DropdownButton")
dropdownButton:SetDimensions(16, 16)
dropdownButton:SetHandler("OnClicked", ShowIconPicker)
dropdownButton:SetAnchor(RIGHT, dropdown, RIGHT, -3, 0)
control.dropdownButton = dropdownButton
control.bg = wm:CreateControl(nil, dropdown, CT_BACKDROP)
local bg = control.bg
bg:SetAnchor(TOPLEFT, dropdown, TOPLEFT, 0, -3)
bg:SetAnchor(BOTTOMRIGHT, dropdown, BOTTOMRIGHT, 2, 5)
bg:SetEdgeTexture("EsoUI/Art/Tooltips/UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI/Art/Tooltips/UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE)
mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds")
mungeOverlay:SetDrawLevel(1)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill()
if iconpickerData.warning ~= nil or iconpickerData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.UpdateChoices = UpdateChoices
control.UpdateValue = UpdateValue
control:UpdateValue()
control.SetColor = SetColor
control:SetColor()
control.SetIconSize = SetIconSize
control:SetIconSize(iconSize)
if iconpickerData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end