Skip to content

Fold the style groups away, and join a divider's parts into one figure - #18

Merged
ZombieHDGaming merged 3 commits into
masterfrom
claude/credit-designer-properties-headers-7nwjfa
Aug 25, 2026
Merged

Fold the style groups away, and join a divider's parts into one figure#18
ZombieHDGaming merged 3 commits into
masterfrom
claude/credit-designer-properties-headers-7nwjfa

Conversation

@ZombieHDGaming

@ZombieHDGamingZombieHDGaming commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Two things in the Credit Designer, plus a formatting fix the CI asked for.


1. The style groups fold away

A StyleEditor is the tallest thing in the section editor — a font, a size, a fill with its stops, an outline, a shadow, an alignment — and a bridged row with subtitles stacks five of them between the placement rows and the entry table. That is exactly the scroll the folding groups were added to end; the style groups were simply left out of that first pass.

All five now fold:

groupwasnow
Text StyleQGroupBoxCollapsibleGroup
Separate Style For The Right Column / Subtitlecheckable QGroupBoxcheckable CollapsibleGroup
Separate Colour For The Bridge / Artworkcheckable QGroupBoxcheckable CollapsibleGroup
Style For The Left SubtitleQGroupBoxCollapsibleGroup
Style For The Right SubtitleQGroupBoxCollapsibleGroup

Entries and Divider Pieces are deliberately untouched: they are the tables that already take the pane's leftover height, and folding the thing you came to the pane to edit is not a convenience.

The checkbox CollapsibleGroup was written to avoid

Its original note argued a checkbox on a group reads as switching the group off, which is what the checkable groups in this editor already mean — so it offered only a disclosure triangle. Two of the style groups need both readings at once, so the class now carries both, side by side rather than one standing in for the other:

  • the checkbox says whether the style applies — unchanged document semantics, unchanged useSecondaryStyle / useBridgeStyle round trip;
  • the triangle beside it says only whether it is on screen.

Neither moves the other. Switched off, a group greys its settings where they are, exactly as the checkable QGroupBox it replaces did. Separate signals (toggled, expandedChanged) mean folding a group never marks the document dirty. setHeaderToolTip came with it: a tooltip set on the group reached only the strip of it no child covered, which on an expanded group is almost nowhere.


2. A divider's parts can be joined into one figure

Every join in a Section Divider was a gap floored at zero, so a composed divider read as a row of separate marks however carefully its shapes were picked. Two settings answer that, and they compose:

  • The gaps reach below zero.dividerGap and dividerPieceGap stop holding two parts apart and push them into each other instead. Not a second setting with a name of its own — a cap overlapping its rule by six pixels is the same edit as one clearing it by six, and one spin box running through zero says so. A join between two pieces of a stack is bounded at half the narrower of them, so pieces are pushed together but never through each other.
  • dividerConnect runs the rule the whole way through. One unbroken arm from the middle of one cap to the middle of the other, passing behind the centre rather than breaking either side of it, so a diamond sits on the line. The middle of the outermost piece rather than the stack's outer edge, because that point is inside every cap's silhouette whatever the cap is — run to the edge and the rule pokes a blunt nose out of a tapering arrowhead.

The new dividers-joined scene shows all three states: held apart, run through, and closed up by hand.

What made it cheap

No new painting machinery. Every tinted part of a divider already goes into one silhouette and is inked once, so an overlap unions seamlessly rather than showing a seam, a doubled outline or a restarted gradient — the mechanism that was already giving you one outline around the whole divider.

Two things did need care:

  • Arms are now placed before the stacks rather than after, so a piece is drawn over the rule it sits on. Invisible for tinted artwork, but a custom picture left in its own colours is painted straight to the strip, and a rule across the front of it is not the ornament anybody placed.
  • The clamped joins are computed once, in the measure pass, and carried on MeasuredStack::gaps to the place pass. Two passes working the bound out separately would be two chances to disagree about a width the section below is positioned from.

Whatever a join is set to, the arms stay inside the section's own box.

Compatibility

dividerConnect defaults off and is absent from every existing document, so every roll draws exactly as it did. The loader still tells a stored zero apart from a missing key for both gaps, and now bounds them on the negative side at kMaxDividerJoin — the same figure the designer's spin boxes offer.


3. A formatting commit, and why it is here

The third commit is nothing but clang-format output. The Check Formatting 🔍 job installs obsproject/tools/clang-format@19 and runs it over every file a pull request changes, and six of the files this branch touches were already non-conforming under 19.1.1 on master:

fileviolations on origin/masteradded by this branch
src/model/CreditsModel.cpp50
src/render/StripRenderer.cpp200
src/ui/SectionEditor.cpp250
tests/harness/Fixtures.cpp20
tests/suites/Dividers.cpp30
tests/suites/Persistence.cpp10

Because the check only looks at changed files, master never trips it — the failure appears the moment any branch touches one of these. So the drift is cleared here rather than left to fail every future PR that goes near them. Every hunk is the formatter's own output: line wrapping and argument alignment, plus one spot in SectionEditor.cpp where two statements had ended up sharing a line separated by a tab. Nothing changes what any of it does.

It is a separate commit so it can be read (or dropped) independently of the two changes above.


Testing

  • cmake -S . -B build -DENABLE_TESTS=ON && cmake --build build — plugin and test binary build clean, no new warnings.
  • ./build/tests/closing-time-tests71 suites, 4558 checks, 0 failures (was 68 / 4498 before), unchanged by the formatting commit.
  • Three new render suites and extended persistence coverage:
    • divider_connected_rule — a divider held apart has columns with no ink in them; the same divider joined has none, at the same width and height, and the end gap makes no difference once it is not consulted.
    • divider_negative_join — measured on a centre stack with no arm, where the ink is the stack's width: a positive gap opens both joins by exactly what was asked, and an unbounded overlap takes back exactly one piece width across the two joins rather than however much was typed.
    • divider_join_stays_inside — a join dragged to its far end leaves no ink outside the section's box.
    • Persistencedivider_connect round-trips, absent means off, and a hostile -1e9 gap off a file is bounded on the negative side rather than rejected for being negative.
  • clang-format 19.1.1 (the version build-aux/run-clang-format requires) reports every changed file clean.

The section editor itself has no offscreen coverage — it needs a window — so the UI behaviour in part 1 was verified by reading, not by a test. Worth a look in a real OBS build before merge.

…hidden
A StyleEditor is the tallest thing in the section editor -- a font, a size, a
fill with its stops, an outline, a shadow, an alignment -- and a bridged row
with subtitles stacks five of them between the placement rows and the entry
table. That is the scroll the folding groups were added to end; the style
groups were simply left out of that first pass.
So CollapsibleGroup grows the checkbox it was originally written to avoid, and
keeps the two readings apart by putting them side by side: the checkbox says
whether the style applies, the disclosure triangle beside it says whether the
settings are on screen, and neither moves the other. Switched off, a group
greys its settings where they are exactly as the checkable QGroupBox it
replaces did -- taking them away at the moment somebody is deciding whether
they want them is the opposite of helpful. The two have separate signals, so
tidying the pane never marks the document dirty.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014u65jyFXUpurpneq2TBTHk
… each other
Every join in a Section Divider was a gap floored at zero, so a composed
divider read as a row of separate marks however carefully its shapes were
picked -- an arrowhead here, a stub of rule there, a diamond floating in the
middle of it. Two settings answer that, and they compose.
The gaps reach below zero, where they stop holding two parts apart and push
them into each other instead. That is not a second setting with a name of its
own: a cap overlapping its rule by six pixels is the same edit as one clearing
it by six, and one spin box running through zero is what says so. A join
between two pieces of a stack is bounded at half the narrower of them --
pushed together, never through each other -- and the bound is worked out once
in the measure pass and carried to the place pass, since two passes deciding
it separately would be two chances to disagree about a width the section below
is positioned from.
`dividerConnect` runs the rule the whole way through: one unbroken arm from the
middle of one cap to the middle of the other, passing behind the centre rather
than breaking either side of it, so a diamond sits *on* the line the way an
ornamental rule is actually composed. The middle of the outermost piece rather
than the stack's outer edge, because that point is inside every cap's
silhouette whatever the cap is -- run to the edge and the rule pokes a blunt
nose out of a tapering arrowhead.
None of it needed new painting machinery, which is the point: every tinted part
of a divider already goes into one silhouette and is inked once, so an overlap
unions seamlessly rather than showing a seam, a doubled outline or a restarted
gradient. What it did need was the arms placed before the stacks rather than
after, so a piece is drawn over the rule it sits on -- invisible for tinted
artwork, but a custom picture left in its own colours is painted straight to
the strip, and a rule across the front of it is not the ornament anybody
placed. Whatever a join is set to, the arms stay inside the section's own box.
Off by default, which is the divider every existing document already draws.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014u65jyFXUpurpneq2TBTHk
@ZombieHDGamingZombieHDGaming changed the title Fold the style groups away, and let a group be both switched off and hiddenFold the style groups away, and join a divider's parts into one figureAug 25, 2026
The check runs clang-format 19.1.1 over every file a pull request changes,
and these six were already non-conforming under it on master -- so the failure
arrives the moment a branch touches one of them, while master itself stays
green because nothing changed there for the check to look at.
Every hunk is the formatter's own output: line wrapping, argument alignment,
and one place where two statements had ended up sharing a line separated by a
tab. Nothing here was written by hand and nothing changes what any of it does;
the test run is unchanged at 71 suites and 4558 checks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014u65jyFXUpurpneq2TBTHk
@ZombieHDGaming
ZombieHDGaming merged commit 9aac873 into masterAug 25, 2026
6 checks passed
@ZombieHDGaming
ZombieHDGaming deleted the claude/credit-designer-properties-headers-7nwjfa branch August 25, 2026 01:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@ZombieHDGaming@claude