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.
This commit is contained in:
2026-08-17 22:19:39 +02:00
parent dc263a2419
commit 083cbcbf9c
2 changed files with 151 additions and 98 deletions
+6 -1
View File
@@ -23,10 +23,15 @@ function CoA:UpdateInstanceButtonFont()
UpdateFont() UpdateFont()
end 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 do
local orig_AddButton = UIDropDownMenu_AddButton local orig_AddButton = UIDropDownMenu_AddButton
UIDropDownMenu_AddButton = function(info, level) UIDropDownMenu_AddButton = function(info, level)
if info and info.text == "Reset Position" and UIDROPDOWNMENU_INIT_MENU == LayerPickerFrameDropDown then if CoA.db and CoA.db.profile.skins.instanceSwap
and info and info.text == "Reset Position" and UIDROPDOWNMENU_INIT_MENU == LayerPickerFrameDropDown then
return return
end end
+145 -97
View File
@@ -8,11 +8,17 @@ local AddOnName = ...
BINDING_HEADER_COA = "Conquest of Azeroth" BINDING_HEADER_COA = "Conquest of Azeroth"
-- TODO: hook up server restart frame (RestartTimerFrame)
local CoA = E:NewModule("CoA", "AceEvent-3.0", "AceTimer-3.0") local CoA = E:NewModule("CoA", "AceEvent-3.0", "AceTimer-3.0")
E.CoA = CoA E.CoA = CoA
local defaults = { local defaults = {
profile = { profile = {
skins = {
extraActionButton = true,
instanceSwap = true,
},
extraActionButtonSize = 52, extraActionButtonSize = 52,
instanceButtonFont = "PT Sans Narrow", instanceButtonFont = "PT Sans Narrow",
instanceButtonFontSize = 12, instanceButtonFontSize = 12,
@@ -70,9 +76,140 @@ local function getOptions()
childGroups = "tab", childGroups = "tab",
name = string.format("|cff1784d1%s|r", "Conquest of Azeroth"), name = string.format("|cff1784d1%s|r", "Conquest of Azeroth"),
args = { args = {
classResources = { -- Frame skins live under their own tab, laid out as a vertical tree
-- rather than more horizontal tabs: one entry per skinned frame, and
-- there are a lot more of those coming.
skins = {
order = 1, order = 1,
type = "group", type = "group",
childGroups = "tree",
name = "Skins",
args = {
extraActionButton = {
order = 1,
type = "group",
name = "Extra Action Button",
args = {
header = {
order = 1,
type = "header",
name = "Extra Action Button",
},
-- Skinning is one-way: the native art is stripped and
-- replaced in place, so turning a skin off can only take
-- effect on the next load. Hence the reload prompt.
enable = {
order = 2,
type = "toggle",
name = "Enable",
desc = "Skin the Extra Action Button. Requires a UI reload.",
get = function() return CoA.db.profile.skins.extraActionButton end,
set = function(_, value)
CoA.db.profile.skins.extraActionButton = value
E:StaticPopup_Show("CONFIG_RL")
end,
},
desc = {
order = 3,
type = "description",
name = "You can move this element with Toggle Anchors.\n",
},
size = {
order = 4,
disabled = function() return not CoA.db.profile.skins.extraActionButton end,
type = "range",
name = "Size",
desc = "Adjust the width/height of the Extra Action Button, in pixels.",
min = 30,
max = 100,
step = 1,
get = function() return CoA.db.profile.extraActionButtonSize end,
set = function(_, value)
CoA.db.profile.extraActionButtonSize = value
if CoA.UpdateExtraActionButtonSize then
CoA:UpdateExtraActionButtonSize()
end
end,
},
},
},
instanceSwap = {
order = 2,
type = "group",
name = "Instance Swap",
args = {
header = {
order = 1,
type = "header",
name = "Instance Swap",
},
enable = {
order = 2,
type = "toggle",
name = "Enable",
desc = "Skin the Instance Swap button. Requires a UI reload.",
get = function() return CoA.db.profile.skins.instanceSwap end,
set = function(_, value)
CoA.db.profile.skins.instanceSwap = value
E:StaticPopup_Show("CONFIG_RL")
end,
},
desc = {
order = 3,
type = "description",
name = "You can move this element with Toggle Anchors.\n",
},
instanceFont = {
order = 4,
disabled = function() return not CoA.db.profile.skins.instanceSwap end,
type = "group",
inline = true,
name = "Instance Font",
args = {
font = ACH:SharedMediaFont("Font", nil, 1, nil,
function() return CoA.db.profile.instanceButtonFont end,
function(_, value)
CoA.db.profile.instanceButtonFont = value
if CoA.UpdateInstanceButtonFont then
CoA:UpdateInstanceButtonFont()
end
end),
fontSize = {
order = 2,
type = "range",
name = "Font Size",
min = 8,
max = 32,
step = 1,
get = function() return CoA.db.profile.instanceButtonFontSize end,
set = function(_, value)
CoA.db.profile.instanceButtonFontSize = value
if CoA.UpdateInstanceButtonFont then
CoA:UpdateInstanceButtonFont()
end
end,
},
fontOutline = ACH:FontFlags("Font Outline", nil, 3, nil,
function() return CoA.db.profile.instanceButtonFontOutline end,
function(_, value)
CoA.db.profile.instanceButtonFontOutline = value
if CoA.UpdateInstanceButtonFont then
CoA:UpdateInstanceButtonFont()
end
end),
},
},
},
},
},
},
classResources = {
order = 2,
type = "group",
name = "Class Resources", name = "Class Resources",
args = { args = {
header = { header = {
@@ -173,101 +310,8 @@ local function getOptions()
}, },
}, },
}, },
extraActionButton = {
order = 2,
type = "group",
name = "Extra Action Button",
args = {
header = {
order = 1,
type = "header",
name = "Extra Action Button",
},
desc = {
order = 2,
type = "description",
name = "You can move this element with Toggle Anchors.\n",
},
size = {
order = 3,
type = "range",
name = "Size",
desc = "Adjust the width/height of the Extra Action Button, in pixels.",
min = 30,
max = 100,
step = 1,
get = function() return CoA.db.profile.extraActionButtonSize end,
set = function(_, value)
CoA.db.profile.extraActionButtonSize = value
if CoA.UpdateExtraActionButtonSize then
CoA:UpdateExtraActionButtonSize()
end
end,
},
},
},
instanceSwap = {
order = 3,
type = "group",
name = "Instance Swap",
args = {
header = {
order = 1,
type = "header",
name = "Instance Swap",
},
desc = {
order = 2,
type = "description",
name = "You can move this element with Toggle Anchors.\n",
},
instanceFont = {
order = 3,
type = "group",
inline = true,
name = "Instance Font",
args = {
font = ACH:SharedMediaFont("Font", nil, 1, nil,
function() return CoA.db.profile.instanceButtonFont end,
function(_, value)
CoA.db.profile.instanceButtonFont = value
if CoA.UpdateInstanceButtonFont then
CoA:UpdateInstanceButtonFont()
end
end),
fontSize = {
order = 2,
type = "range",
name = "Font Size",
min = 8,
max = 32,
step = 1,
get = function() return CoA.db.profile.instanceButtonFontSize end,
set = function(_, value)
CoA.db.profile.instanceButtonFontSize = value
if CoA.UpdateInstanceButtonFont then
CoA:UpdateInstanceButtonFont()
end
end,
},
fontOutline = ACH:FontFlags("Font Outline", nil, 3, nil,
function() return CoA.db.profile.instanceButtonFontOutline end,
function(_, value)
CoA.db.profile.instanceButtonFontOutline = value
if CoA.UpdateInstanceButtonFont then
CoA:UpdateInstanceButtonFont()
end
end),
},
},
},
},
dispelHighlight = { dispelHighlight = {
order = 4, order = 3,
type = "group", type = "group",
name = "Debuff Highlighting", name = "Debuff Highlighting",
args = { args = {
@@ -363,11 +407,15 @@ function CoA:Initialize()
EP:RegisterPlugin(AddOnName, getOptions) EP:RegisterPlugin(AddOnName, getOptions)
if self.InitializeExtraActionBar then -- ADDON_LOADED normally beats module init, but fall back to the defaults
-- rather than error out if a skin gets initialized before the DB exists.
local skins = self.db and self.db.profile.skins or defaults.profile.skins
if self.InitializeExtraActionBar and skins.extraActionButton then
self:InitializeExtraActionBar() self:InitializeExtraActionBar()
end end
if self.InitializeLayerPicker then if self.InitializeLayerPicker and skins.instanceSwap then
self:InitializeLayerPicker() self:InitializeLayerPicker()
end end