Restyle CoA talent frame tabs to match ElvUI's flat tab rows
Bigger font and plate, tighter gap between tabs, taller tabs for real vertical padding around the label. Selection now relies on Blizzard's own white-text-on-checked behaviour instead of an ElvUI border/fill swap, matching the Friends/Character tab rows elsewhere in ElvUI. Growth and frame-level bump are self-healing from the tabs' OnUpdate hook rather than one-shot: the tab's native height isn't settled yet when it's first skinned, and something outside our control resets the frame level on a plain tab switch, so both need to keep correcting themselves rather than being set once behind a guard.
This commit is contained in:
+137
-20
@@ -614,23 +614,11 @@ end
|
|||||||
-- art. The unnamed ARTWORK region is the tab's icon and is left alone.
|
-- art. The unnamed ARTWORK region is the tab's icon and is left alone.
|
||||||
local TAB_TEXTURES = {"Left", "Center", "Right", "LeftDisabled", "CenterDisabled", "RightDisabled"}
|
local TAB_TEXTURES = {"Left", "Center", "Right", "LeftDisabled", "CenterDisabled", "RightDisabled"}
|
||||||
|
|
||||||
-- These are CheckButtons, and clearing the checked texture along with the
|
-- Blizzard's own tab code re-sets these textures both when the frame reopens
|
||||||
-- rest of the art leaves nothing to mark the open tab, so selection is shown
|
-- and, separately, on every tab switch -- and a switch never fires the talent
|
||||||
-- with the ElvUI value colour on the backdrop border instead.
|
-- frame's OnShow, only SetChecked. So this has to be idempotent and re-run
|
||||||
local function UpdateTabSelection(tab)
|
-- from both places rather than skinned once behind a guard.
|
||||||
if not tab.backdrop then return end
|
local function StripTab(tab)
|
||||||
|
|
||||||
if tab:GetChecked() then
|
|
||||||
tab.backdrop:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
|
|
||||||
else
|
|
||||||
tab.backdrop:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function SkinTab(tab)
|
|
||||||
if tab.CoASkinned then return end
|
|
||||||
tab.CoASkinned = true
|
|
||||||
|
|
||||||
local name = tab:GetName()
|
local name = tab:GetName()
|
||||||
if name then
|
if name then
|
||||||
for _, suffix in ipairs(TAB_TEXTURES) do
|
for _, suffix in ipairs(TAB_TEXTURES) do
|
||||||
@@ -644,25 +632,154 @@ local function SkinTab(tab)
|
|||||||
|
|
||||||
local checked = tab.GetCheckedTexture and tab:GetCheckedTexture()
|
local checked = tab.GetCheckedTexture and tab:GetCheckedTexture()
|
||||||
if checked then checked:SetTexture(nil) end
|
if checked then checked:SetTexture(nil) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Same sibling problem as the close button (see SkinCloseButton): the tabs
|
||||||
|
-- aren't children of the talent frame, so growing one taller lets its top
|
||||||
|
-- edge poke up behind the frame's own panel art instead of in front of it.
|
||||||
|
--
|
||||||
|
-- The backdrop's own level is left alone -- CreateBackdrop keeps it level
|
||||||
|
-- with the tab by default, and regions render fine on top of a same-level
|
||||||
|
-- child. Forcing the backdrop a level *above* the tab (tried here once)
|
||||||
|
-- reproduces the child-frame-covers-parent's-own-regions quirk noted in
|
||||||
|
-- StripRowArt, which is why the label vanished that time. Raising the tab is
|
||||||
|
-- enough; the backdrop, clamped to the tab's new level automatically, rises
|
||||||
|
-- with it.
|
||||||
|
local function BumpTabLevel(tab)
|
||||||
|
local frame = _G[FRAME_NAME]
|
||||||
|
if not frame then return end
|
||||||
|
|
||||||
|
tab:SetFrameStrata(frame:GetFrameStrata())
|
||||||
|
tab:SetFrameLevel(frame:GetFrameLevel() + 20)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Grown height, self-healing the same way: on a plain /reload the tab's
|
||||||
|
-- native height isn't settled yet at SkinTab time (Blizzard lays it out
|
||||||
|
-- asynchronously), so a one-shot SetHeight there caught a stale value and
|
||||||
|
-- produced a shorter tab until something (a switch, a reopen) let Blizzard's
|
||||||
|
-- own layout finish and this caught the corrected height.
|
||||||
|
--
|
||||||
|
-- Compared by equality rather than "did it shrink": Blizzard's late layout
|
||||||
|
-- can land on a height *larger* than the stale one this originally grew from,
|
||||||
|
-- and a shrink-only check would then see current > target and never regrow,
|
||||||
|
-- leaving the tab at Blizzard's native size with none of the padding added.
|
||||||
|
-- Checking for any drift away from what was last written here catches that
|
||||||
|
-- direction too, but GetHeight doesn't read back byte-exact after SetHeight
|
||||||
|
-- -- UI scale rounds it to a slightly different float -- so a strict ~=
|
||||||
|
-- compare never held and this grew every single tick without bound. Half a
|
||||||
|
-- pixel of slack absorbs that rounding while still catching a genuine
|
||||||
|
-- Blizzard-driven change, which is always a full tab's worth of height, not
|
||||||
|
-- a rounding error's worth.
|
||||||
|
local TAB_GROWTH = 8
|
||||||
|
local TAB_HEIGHT_EPSILON = 0.5
|
||||||
|
|
||||||
|
local function UpdateTabSize(tab)
|
||||||
|
local height = tab:GetHeight()
|
||||||
|
|
||||||
|
if not tab.CoAGrownHeight or math.abs(height - tab.CoAGrownHeight) > TAB_HEIGHT_EPSILON then
|
||||||
|
tab.CoAGrownHeight = height + TAB_GROWTH
|
||||||
|
tab:SetHeight(tab.CoAGrownHeight)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Only the active tab gets a SetChecked call on every switch -- the other two
|
||||||
|
-- never fire it again after the first skin, but their art still comes back,
|
||||||
|
-- so there's no event to hook for them. Checked from OnUpdate instead, same
|
||||||
|
-- as RestoreArrow/UpdateRowArt: cheap GetTexture() compare, only pays for the
|
||||||
|
-- full strip when the native art has actually reappeared.
|
||||||
|
--
|
||||||
|
-- The frame-level bump is re-applied here too, every frame rather than only
|
||||||
|
-- on OnShow/SetChecked: the earlier fix (bumping only from those two spots)
|
||||||
|
-- still left the tabs behind the panel, which means whatever resets their
|
||||||
|
-- level on a switch isn't SetChecked either. OnUpdate is the one hook proven
|
||||||
|
-- to survive every path that reverts these tabs, so it's the catch-all.
|
||||||
|
local function UpdateTabArt(tab)
|
||||||
|
BumpTabLevel(tab)
|
||||||
|
UpdateTabSize(tab)
|
||||||
|
|
||||||
|
local name = tab:GetName()
|
||||||
|
local tex = name and _G[name.."Left"]
|
||||||
|
|
||||||
|
if tex and tex:GetTexture() then
|
||||||
|
StripTab(tab)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- These are CheckButtons, but no fill or border swap is needed to mark the
|
||||||
|
-- open one -- Blizzard's own tab code already turns the label white on the
|
||||||
|
-- checked tab and leaves the rest their normal colour, same as the
|
||||||
|
-- Friends/Character tab rows. Only the art strip needs to re-run here.
|
||||||
|
local function UpdateTabSelection(tab)
|
||||||
|
StripTab(tab)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function SkinTab(tab)
|
||||||
|
if tab.CoASkinned then return end
|
||||||
|
tab.CoASkinned = true
|
||||||
|
|
||||||
|
StripTab(tab)
|
||||||
|
|
||||||
-- Default rather than Transparent: these sit below the frame over open
|
-- Default rather than Transparent: these sit below the frame over open
|
||||||
-- world, so a see-through panel reads as washed out instead of as the
|
-- world, so a see-through panel reads as washed out instead of as the
|
||||||
-- solid tabs the retail layout has.
|
-- solid tabs the retail layout has.
|
||||||
|
--
|
||||||
|
-- Insets alone only resize the plate within the tab's native bounds --
|
||||||
|
-- padding around the (now bigger) label needs the tab itself taller.
|
||||||
|
-- Height is grown by UpdateTabSize (from the OnUpdate hook below) rather
|
||||||
|
-- than here, since the native height isn't settled yet at this point.
|
||||||
tab:CreateBackdrop("Default")
|
tab:CreateBackdrop("Default")
|
||||||
tab.backdrop:Point("TOPLEFT", 6, -3)
|
tab.backdrop:Point("TOPLEFT", 3, -3)
|
||||||
tab.backdrop:Point("BOTTOMRIGHT", -6, 3)
|
tab.backdrop:Point("BOTTOMRIGHT", -3, 3)
|
||||||
tab:SetHitRectInsets(6, 6, 3, 3)
|
tab:SetHitRectInsets(3, 3, 3, 3)
|
||||||
|
|
||||||
|
-- Native size is a retail leftover -- every other ElvUI tab row in this
|
||||||
|
-- client reads bigger. Grown in place off the font's own current size
|
||||||
|
-- rather than a hardcoded number, so it still scales with the user's
|
||||||
|
-- font settings.
|
||||||
|
local fontString = tab.GetFontString and tab:GetFontString()
|
||||||
|
if fontString then
|
||||||
|
local font, size, flags = fontString:GetFont()
|
||||||
|
if font then
|
||||||
|
fontString:SetFont(font, size + 3, flags)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The label's native anchor sits right off the icon, sized for the
|
||||||
|
-- smaller native font. Grown text collides with the icon at that
|
||||||
|
-- offset, so it's nudged right off whatever point Blizzard anchored
|
||||||
|
-- it to rather than a hardcoded anchor that would fight the tab's
|
||||||
|
-- own layout.
|
||||||
|
local point, relTo, relPoint, x, y = fontString:GetPoint(1)
|
||||||
|
if point then
|
||||||
|
fontString:SetPoint(point, relTo, relPoint, x + 12, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
hooksecurefunc(tab, "SetChecked", UpdateTabSelection)
|
hooksecurefunc(tab, "SetChecked", UpdateTabSelection)
|
||||||
UpdateTabSelection(tab)
|
UpdateTabSelection(tab)
|
||||||
|
|
||||||
|
tab:HookScript("OnUpdate", UpdateTabArt)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Same sibling problem as the close button (see SkinCloseButton): the tabs
|
||||||
|
-- aren't children of the talent frame, so growing one taller lets its top
|
||||||
|
-- edge poke up behind the frame's own panel art instead of in front of it.
|
||||||
|
-- Re-applied every pass rather than once, since whatever re-raises the frame
|
||||||
|
-- doesn't carry the tabs' absolute level along with it.
|
||||||
|
--
|
||||||
|
-- The backdrop's own level is left alone -- CreateBackdrop keeps it level
|
||||||
|
-- with the tab by default, and regions render fine on top of a same-level
|
||||||
|
-- child. Forcing the backdrop a level *above* the tab (tried here once)
|
||||||
|
-- reproduces the child-frame-covers-parent's-own-regions quirk noted in
|
||||||
|
-- StripRowArt, which is why the label vanished. Raising the tab is enough;
|
||||||
|
-- the backdrop, clamped to the tab's new level automatically, rises with it.
|
||||||
local function SkinTabs()
|
local function SkinTabs()
|
||||||
for i = 1, MAX_TABS do
|
for i = 1, MAX_TABS do
|
||||||
local tab = _G[TAB_NAME:format(i)]
|
local tab = _G[TAB_NAME:format(i)]
|
||||||
if not tab then break end
|
if not tab then break end
|
||||||
|
|
||||||
SkinTab(tab)
|
SkinTab(tab)
|
||||||
|
StripTab(tab)
|
||||||
|
BumpTabLevel(tab)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user