Commit Graph

4 Commits

Author SHA1 Message Date
Narcasung 013fe665ab Skin the Challenges frame's Gamemodes tab
The Trials shape a third time, and again suffix for suffix: the search
box and list container are named off the tab exactly as Trials names
its own, the list's only region is the same store divider, and the
scroll arrows hang off the scroll frame rather than off the bar. So the
divider constant is shared rather than copied and the three calls go in
unchanged.

The one difference is the filter, which this tab does not have. Its two
children are the search box and the list and neither is a menu, so
there is nothing for a Dropdown call to be handed. That is written into
the comment rather than left implicit: with the same function sitting
three times over in the file, a missing fourth line otherwise reads as
an oversight.

The tab owns no regions of its own at all, so nothing here needs the
keepTextures care the Rewards tab's PageText took. Both children exist
on a cold reload, before the tab has ever been opened, and the counts
are unchanged after a click, so it rides SkinContents with the rest
rather than needing a hook on its own OnShow.

Everything reuses an existing helper, so the shared layer is unchanged.
2026-08-22 16:50:05 +02:00
Narcasung d9476af220 Skin the Challenges frame's Challenges tab
The tab is the Trials tab again in every detail that matters: the same
three children under the same suffixes, the same store divider as its
list container's only region, the same silver-button filter, and its
scroll arrows named off the scroll frame rather than off the bar. So it
takes the same four calls, sharing the divider constant rather than
copying it.

Everything exists before the tab has ever been opened, so it goes
through SkinContents with the rest and needs no hook of its own.
2026-08-22 16:47:04 +02:00
Narcasung cafc3ce28f Skin the Challenges frame's Rewards tab
The tab's twenty-nine children all exist on a cold reload, before it has
ever been opened, so this goes through SkinContents with the rest of the
window rather than needing a hook on the tab's own OnShow -- which a tab
switch would have wanted, since switching tabs fires nothing.

None of the Trials tab's naming carries over. Its search box is
TrialsTabSearch and its filter a FilterDropDown, where these are
StoreTabSearchBox and Filter, so every suffix was confirmed rather than
copied and the divergence is written down for the four tabs still to do.

The Filter is the one widget that had to be read twice. Structurally it
is a plain Button -- no Middle texture, no Button child, no Text
fontstring -- so the test the Interface Options sweep settled on says it
is not a dropdown. By art it plainly is: the same nine Silver-Button
slices and ChatFrameExpandArrow caret the Trials filter wears. Dropdown
matches on the art rather than on the naming, so it takes it unchanged;
the structural test is only ever a shortcut to that question and here it
answers it wrongly.

The grid is a fixed pool of twenty-one cards built up front, not one
built per page, so a single pass covers every card the tab will ever
show and nothing hangs off a page-change hook. The icon crop is the
exception and is re-applied from a hook on the texture's SetTexture: the
store refills the pool in place on every search, filter and page change,
and SetTexture resets a texture's coords, so a one-shot crop survives
exactly until the first page turn and then the native icon borders come
back on every card at once. The slot plate underneath needs no such
watch -- StripArtByFile noops its SetTexture, so a refill that re-arts it
writes nothing.

Cards take HandleButton's useCreateBackdrop path rather than its default
SetTemplate one, which is what makes their padding possible: a template
is drawn as regions of the button and can only ever match its rect, and
the rect is tight -- 140x32 around a 32px icon, so the icon met the top
and bottom edges and the name ran to the right one. A backdrop is a
child frame that can be set outside it. Same reasoning as the window
panel's, one level down. The hover colouring follows either way, since
it resolves button.backdrop before the button itself.

The two headings above the grid are Buttons by type but captions by
function, so their atlas art comes off and nothing goes back: a backdrop
would draw a box around a caption, and the HIGHLIGHT layer would light
it up under a cursor with nothing behind it. They are walked off the
layout rather than named, the set being one per reward vendor.

Left alone deliberately: the Currency button, which carries the trophy
icon and its counter as its only two regions and no frame art at all,
and PageText, which is a region of the tab itself -- the same trap as
the vanity store's counters. Nothing here blind-strips the tab. No
scroll bar is wired either; the grid pages rather than scrolls and has
no scroll frame to hang one off.

Everything reuses an existing helper, so the shared layer is unchanged.
2026-08-22 16:43:00 +02:00
Narcasung a8541fa1ee Skin the Challenges window, its tab row and the Trials tab
ChallengesFrame is a HIGH-strata window parented straight to UIParent and
mouse-enabled itself, not one of the three that hang off the Collections
container -- so it gets its own module and its own enable switch rather
than joining the collections group, and it deliberately skips
ApplyWindowScale and CollectionTabs: the first scales Collections, which
would resize the other three windows and not this one, and the second
skins the tab row those three share.

The panel is built as a backdrop instead of through SetTemplate. A
template's backdrop is drawn as regions of the frame and can only match
its rect, and the title sits above that rect -- the native art carries a
banner up there -- so a panel sized to the frame left the title floating
over the open world. A backdrop has points of its own, so its top edge is
pushed up over the title, measured live rather than hardcoded, with the
hit rect and the close button following it. The nine-slice is stripped
rather than run through HideArt for a related reason: the title is one of
its regions, and Hide() would take it down with the border.

The tab row is the first stock Blizzard flavour the plugin skins, so the
shared layer grows to cover it. TAB_TEXTURES picks up the Middle pieces
those name their body after, and the OnUpdate art re-check watches the
Disabled set as well -- that pair is how a stock tab draws its selected
state, so watching only the inactive half missed art returning on
whichever tab was open. Native panel tabs also interlock, each anchored
16px back into the one before it so the ornate end caps overlap, which
reads as one merged bar once the art is gone; the overlap is absorbed by
narrowing each tab rather than by spacing the row out, which would have
grown it 80px past a frame with 16px of slack. The row is pulled up flush
against the panel it belongs to, since the native tops that spanned that
gap went with the art.

Inside the Trials tab: the search box, the filter dropdown and the scroll
bar. The dropdown is the same widget as the vanity and wardrobe ones and
takes the existing handler unchanged. The search box needs its border
cleared by file, not stripped -- an EditBox draws its caret and selection
highlight as plain textures of its own, and a blind strip leaves a box
you can type in with no cursor in it.

The scroll bar needed a handler of its own. HandleScrollBar reaches for
the thumb through GetThumbTexture and then calls SetTexture on it, but
these bars are hand-built: the thumb is a Button with art of its own, and
the arrows are named off the scroll frame rather than off the bar, so it
finds neither. Both pieces are also arted lazily -- at skin time their
textures read back nil, which is why clearing them, noop'ing their
SetTexture and alpha'ing them all failed in turn -- so the art is
suppressed from OnUpdate, the same answer the tab art needed. Colours
follow ElvUI's own proportional scroll bars, and the track is left empty
rather than given a backdrop.
2026-08-22 16:32:37 +02:00