Wrap node descriptions and notes in the inspector
A node's description and every note in the inspector were one line cut with an ellipsis. Stop pattern says what it does with no pattern picked, but only past the cut, so nobody could read it. - Label takes a wrap option. It breaks its text at the width it gets and keeps the margin a single line has, above and below all lines. - Widget.heightFor(width) gives the height at a width. It is measure().h everywhere except where text wraps. - VStack and SectionStack lay a column out with it, at the width each row will get. - ScrollContainer measures again at the narrower width when its scrollbar shows, because the text then takes more lines. - addNote and the empty inspector's hint wrap. - The file list's own heightFor(count) is now heightOfRows, so the layout does not hand it a width as a row count. Tests: - Unit scroll-container: 7 green, 2 new (height for width, again beside the scrollbar) - Unit ui + inspector: 17 files, 336 green (before the 2 new ones) - e2e 02 (stein2, atx busy with suite 545): ALL PASSED, 29 checks - Screenshot: Stop pattern shows its description in six lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5fde3e975e
commit
32051b5097
11 files changed
+133
-22
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { ScrollContainer, Spacer, Theme, VStack } from '../../src/ui';
|
||||
import { ScrollContainer, Spacer, Theme, VStack, Widget } from '../../src/ui';
|
||||
|
||||
/** Row tops after a layout; an unlaid-out stack leaves every child at 0. */
|
||||
const tops = (stack: VStack) => stack.children.map((c) => c.y);
|
||||
@@ -61,3 +61,40 @@ describe('a scroll container and its scrollbar', () => {
|
||||
expect(rows.w).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
/** Stands in for wrapped text: 20 px per line, a line per 100 px of text. */
|
||||
class Wrapping extends Widget {
|
||||
constructor(private readonly textWidth: number) {
|
||||
super();
|
||||
}
|
||||
|
||||
override heightFor(width: number): number {
|
||||
return Math.ceil(this.textWidth / width) * 20;
|
||||
}
|
||||
}
|
||||
|
||||
describe('a scroll container with content that wraps', () => {
|
||||
it('gives a row the height it needs at the width it gets', () => {
|
||||
const scroll = new ScrollContainer();
|
||||
scroll.resize(200, 300);
|
||||
const rows = new VStack();
|
||||
const text = rows.add(new Wrapping(500));
|
||||
rows.add(new Spacer(20));
|
||||
scroll.setContent(rows);
|
||||
expect(text.h).toBe(60);
|
||||
expect(tops(rows)).toEqual([0, 60]);
|
||||
});
|
||||
|
||||
it('measures again once the scrollbar narrows the content', () => {
|
||||
const scroll = new ScrollContainer();
|
||||
scroll.resize(200, 100);
|
||||
const rows = new VStack();
|
||||
// 400 px of text is two lines at 200 px, but three beside the bar.
|
||||
const text = rows.add(new Wrapping(400));
|
||||
rows.add(new Spacer(70));
|
||||
scroll.setContent(rows);
|
||||
expect(rows.w).toBe(200 - Theme.scrollbarWidth);
|
||||
expect(text.h).toBe(60);
|
||||
expect(scroll.maxScroll).toBe(30);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user