Skip to content

feat(api): LineBuilder.fill() — line stretches to its available width#234

Merged
DemchaAV merged 1 commit into
developfrom
feat/line-fill
Jun 25, 2026
Merged

feat(api): LineBuilder.fill() — line stretches to its available width#234
DemchaAV merged 1 commit into
developfrom
feat/line-fill

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Why

A line always drew at its authored width(...). To run a rule across the page, or a dotted leader from a label to a page number, you had to compute that width by hand — and recompute it whenever the layout changed.

fill() makes a horizontal line stretch to the width available where it is placed — its column inside a row, or the content width at flow level. It's the flex line behind a dotted table-of-contents leader, drawn without measuring the gap.

What changed

  • LineBuilder.fill() → a boolean fillWidth on LineNode (threaded like lineCap, with the back-compat constructor chain preserved).
  • LineDefinition resolves it: a fill line measures to constraints.availableWidth() and draws to the box's right edge. It is a no-op on a vertical or diagonal line — stretching the end point would change the slope — so fill() is documented and guarded as horizontal-only.
  • A non-fill line is untouched (fillWidth=false → both the measure and emit branches are unchanged), so existing line output is byte-identical.

Lane: canonical DSL (LineBuilder/LineNode) + shared-engine definition (LineDefinition). Additive at the signature level → japicmp-safe.

This is the first half of the row-layout work for a native table of contents: the dot leader. A follow-up adds RowColumnWidth (auto/fixed/weight columns) so the label and page-number columns size to their content; the TOC then sits on both.

Verification

  • ./mvnw test -pl .green, 0 visual baselines changed.
  • LineFillTest: a fill line resolves to its row slot and to the content width at flow level, a non-fill line keeps its authored width, and fill is a no-op on a vertical line.
  • Runnable LineFillExample (full-width rule, full-width dotted leader, and a weighted leader→p. 12 row) with a committed preview and an examples README row.

A line drew at its authored width; there was no way to make it span its
column or the content width without computing that width by hand. fill()
stretches a horizontal line to the width available where it is placed —
its row column, or the content width at flow level — so a dotted leader
runs from one column to the next on its own. It is the flex line behind a
table-of-contents row.

Resolved in LineDefinition: a fill line measures to the available width
and draws to the box's right edge; fill is a no-op on a vertical or
diagonal line, where stretching the end point would change the slope. A
non-fill line is unchanged, so existing line output is byte-identical.

Tests: LineFillTest covers a fill line resolving to its row slot and to
the content width at flow level, a non-fill line keeping its authored
width, and fill as a no-op on a vertical line. Example: LineFillExample
(full-width rule, dotted leader, weighted leader-to-number row). Full
suite green, no visual baselines changed.
.margin(DocumentInsets.of(20))
.create()) {
session.pageFlow(page -> page.addRow(r -> {
r.gap(0).weights(1, 1);
Sign up for free to 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