Files
ElvUI_CoA/Modules/LayerPicker.lua
T
Narcasung 083cbcbf9c Group frame skins under their own settings tab
The CoA options were a flat row of tabs, one per feature, which doesn't
survive the number of frame skins now landing. Skins get their own tab,
first in the row, laid out as a vertical tree so each skinned frame is one
entry rather than one more horizontal tab. Extra Action Button and Instance
Swap move under it.

Each skin also gets a master enable toggle. Skinning is one-way -- the
native art is stripped and replaced in place -- so turning one off can only
take effect on the next load, hence the reload prompt and the gate in
CoA:Initialize rather than an attempt to undo the skin live. Existing users
see no change: both default to on.

LayerPicker's UIDropDownMenu_AddButton wrapper is hooked at file scope,
outside that gate, so it checks the toggle itself. That one does respect
the switch immediately.
2026-08-17 22:19:39 +02:00

141 lines
3.9 KiB
Lua

local E, L, V, P, G = unpack(ElvUI)
local LSM = E.Libs.LSM
local CoA = E:GetModule("CoA")
local BUTTON_NAME = "LayerPickerFrame"
local MIN_WIDTH, MIN_HEIGHT = 66, 14
local PAD_X, PAD_Y = 10, 10
local function UpdateFont(button)
button = button or _G[BUTTON_NAME]
local text = button and _G[button:GetName().."Text"]
if not text then return end
text:FontTemplate(LSM:Fetch("font", CoA.db.profile.instanceButtonFont), CoA.db.profile.instanceButtonFontSize, CoA.db.profile.instanceButtonFontOutline)
button:SetSize(
math.max(MIN_WIDTH, text:GetStringWidth() + PAD_X),
math.max(MIN_HEIGHT, text:GetStringHeight() + PAD_Y)
)
end
function CoA:UpdateInstanceButtonFont()
UpdateFont()
end
-- Hooked at file scope, so unlike the rest of the skin it stays live even when
-- the skin is off -- check the toggle here instead. Reset Position only makes
-- sense while the frame is where the server put it; once we've handed it to a
-- mover the entry does nothing useful.
do
local orig_AddButton = UIDropDownMenu_AddButton
UIDropDownMenu_AddButton = function(info, level)
if CoA.db and CoA.db.profile.skins.instanceSwap
and info and info.text == "Reset Position" and UIDROPDOWNMENU_INIT_MENU == LayerPickerFrameDropDown then
return
end
return orig_AddButton(info, level)
end
end
-- A single nil-out isn't enough: native dragging ends with the engine
-- calling SetPoint directly on the frame, severing the live anchor to our
-- mover holder. So we don't just clear drag once, we permanently intercept
-- any future attempt to turn it back on. The CoAClearing* guards stop our
-- own corrective calls from re-triggering these same hooks.
local function DisableDrag(button)
if button.CoADragDisabled then return end
button.CoADragDisabled = true
button:SetScript("OnDragStart", nil)
button:SetScript("OnDragStop", nil)
button:RegisterForDrag()
hooksecurefunc(button, "SetScript", function(self, script, handler)
if handler and (script == "OnDragStart" or script == "OnDragStop") and not self.CoAClearingDragScript then
self.CoAClearingDragScript = true
self:SetScript(script, nil)
self.CoAClearingDragScript = false
end
end)
hooksecurefunc(button, "RegisterForDrag", function(self, ...)
if select("#", ...) > 0 and not self.CoAClearingDrag then
self.CoAClearingDrag = true
self:RegisterForDrag()
self.CoAClearingDrag = false
end
end)
end
local function SetupMover(button)
if CoA.layerPickerMoverCreated then return true end
local width, height = button:GetSize()
if width == 0 or height == 0 then return false end
local left, bottom = button:GetLeft(), button:GetBottom()
if not left or not bottom then return false end
CoA.layerPickerMoverCreated = true
local holder = CreateFrame("Frame", "CoA_LayerPickerHolder", E.UIParent)
holder:Size(width, height)
holder:Point("BOTTOMLEFT", E.UIParent, "BOTTOMLEFT", left, bottom)
E:CreateMover(holder, "CoA_LayerPickerMover", "Instance", nil, nil, nil, "ALL,COA", nil, "CoA,skin,instance")
holder:SetAllPoints(_G["CoA_LayerPickerMover"])
_G["CoA_LayerPickerMover"]:SetFrameStrata("FULLSCREEN")
local function Anchor()
button:ClearAllPoints()
button:SetPoint("CENTER", holder, "CENTER")
end
if InCombatLockdown() then
CoA:RegisterEvent("PLAYER_REGEN_ENABLED", function()
Anchor()
CoA:UnregisterEvent("PLAYER_REGEN_ENABLED")
end)
else
Anchor()
end
return true
end
local function SkinButton(button)
if button.CoASkinned then return end
button.CoASkinned = true
button:StripTextures(true)
button:CreateBackdrop("Default")
button:StyleButton()
UpdateFont(button)
end
local function TryHook()
local button = _G[BUTTON_NAME]
if button then
DisableDrag(button)
SkinButton(button)
return SetupMover(button)
end
return false
end
function CoA:InitializeLayerPicker()
if TryHook() then return end
self.layerPickerTimer = self:ScheduleRepeatingTimer(function()
if TryHook() then
self:CancelTimer(self.layerPickerTimer)
self.layerPickerTimer = nil
end
end, 0.5)
end