feat(api): RowBuilder.columns() — fixed / auto / weight row columns#235
Merged
Conversation
|
|
||
| @Test | ||
| void fixedColumnTakesItsPointWidthAndWeightTakesTheRemainder() { | ||
| render(page -> page.addRow(r -> r.gap(0).columns(fixed(40), weight(1)) |
|
|
||
| @Test | ||
| void weightOnlyColumnsResolveLikePlainWeights() { | ||
| render(page -> page.addRow(r -> r.gap(0).columns(weight(1), weight(3)) |
|
|
||
| @Test | ||
| void intrinsicColumnSizesToContentAndWeightTakesRemainder() { | ||
| render(page -> page.addRow(r -> r.gap(0).columns(auto(), weight(1)) |
| @Test | ||
| void overConstrainedFixedColumnsThrow() { | ||
| try (DocumentSession session = smallPage()) { | ||
| session.pageFlow(page -> page.addRow(r -> r.gap(0).columns(fixed(150), fixed(150)) |
| @Test | ||
| void dotLeaderRowFillsBetweenTheLabelAndTheNumber() { | ||
| double gap = 4; | ||
| render(page -> page.addRow(r -> r.gap(gap).columns(auto(), weight(1), auto()) |
|
|
||
| @Test | ||
| void weightColumnsAreByteIdenticalToPlainWeights() { | ||
| double[] viaWeights = twoFillWidths(r -> r.gap(0).weights(1, 3)); |
| @Test | ||
| void weightColumnsAreByteIdenticalToPlainWeights() { | ||
| double[] viaWeights = twoFillWidths(r -> r.gap(0).weights(1, 3)); | ||
| double[] viaColumns = twoFillWidths(r -> r.gap(0).columns(weight(1), weight(3))); |
| // An auto column whose content is wider than the row clamps to the row | ||
| // width (the content wraps) instead of overflowing or throwing. | ||
| try (DocumentSession session = smallPage()) { | ||
| session.pageFlow(page -> page.addRow(r -> r.gap(0).columns(auto()) |
A row split its width by weights or evenly; there was no way to size a column to its content or to a fixed width, so a table-of-contents row (label, dotted leader, page number) was not expressible. columns(...) sizes each column as DocumentRowColumn.fixed(pt), auto() (content width), or weight(w) (a share of the remainder), resolved fixed -> auto -> weight. With line().fill() it draws a dot leader that fills the gap. The explicit-column distribution lives in a shared RowSlots helper called by both the compile and measure phases, so the two stay in lockstep; the existing weight / even path is untouched and a weight-only column list resolves to exactly the same widths, so existing rows are byte-identical. weights(...) stays as sugar; columns and weights are mutually exclusive. Tests: RowColumnsTest covers the fixed/auto/weight mix, weight-only columns byte-identical to plain weights, content sizing plus the weight remainder, over-constrained columns throwing, a long auto label clamping to the row, and the dot-leader table-of-contents row. Example: RowColumnsExample (a table-of-contents block). Full suite green, no visual baselines changed.
4ca8670 to
1ff3aa2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A row could split its width only by
weights(...)or evenly. There was no way to size a column to its content or to a fixed width — so a table-of-contents row (a label, a dotted leader, a right-aligned page number) couldn't be expressed without measuring the gap by hand.What changed
RowBuilder.columns(DocumentRowColumn...)sizes each column asfixed(pt),auto()(intrinsic content width, capped at the row — content still wraps, it never overflows), orweight(w)(a share of the space left after the fixed and auto columns). Resolution order: fixed → auto → weight-remainder. Over-constrained (fixed + auto exceed the row) throws a clearIllegalArgumentException.DocumentRowColumn(new public value type indocument.style) — the row peer ofDocumentTableColumn, sameauto()/fixed()vocabulary, plusweight().line().fill()(PR feat(api): LineBuilder.fill() — line stretches to its available width #234) it draws a dot-leader row:columns(auto(), weight(1), auto())with a fill line in the middle. The label and page number size to their content; the leader fills between them.weights(...)/evenWeights()stay as sugar;columns(...)andweights(...)are mutually exclusive (setting one clears the other; the node rejects both).Engine: the explicit-column distribution lives in a shared
RowSlotshelper called by both the compile and measure phases, so the two stay in lockstep by construction. The existing weight / even path is untouched — empty-columns rows take the original code, and a weight-only column list resolves to exactly the same widths. So existing rows are byte-identical.Lane: canonical DSL + node + style, shared-engine layout.
DocumentRowColumnis a new type and theRowNodecomponent is additive (back-compat ctors preserved) → japicmp-safe.Verification
./mvnw test -pl .— green, 0 visual baselines changed.RowColumnsTest: fixed+weight (40/160), weight-only columns byte-identical to plain weights (exact A/B), content sizing + weight remainder, over-constrained throws, a long auto label clamps to the row, the node rejects both weights+columns, and the dot-leader TOC row fills exactly between label and number.RowColumnsExample(a table-of-contents block) with a committed preview and an examples README row.This is the second half of the table-of-contents groundwork (after
pageIndex()#231 andline().fill()#234); the native TOC builds on it next.