Head the groups of the inspector with bands that fold (#290)
The groups of the inspector had a small grey label as their title, in the same grid as a property row, so with many rows one group hardly stood apart from the next. Now every group has a band as its head, from edge to edge of the panel, and a click on it folds the group. - A band runs across the padding of its column in the header colour, with the title and a mark that says whether the group is open. The titles stay as they are, as answered in the issue. - A click on a band folds its group: the rows go, the band stays and the next band moves up against it. A control in the band (Open, + Variable, + Property) does its own job and folds nothing. - A placed object has a group SWITCHES under its name, asset and parent: Enabled, Keep on scene load and the switches of a behavior. An asset has SWITCHES and PROPERTIES, and a group without rows is left out. - The same bands head the tilemap panel, the Variables tab, the side of the Pixel art tab and the shape list of vector art. A list with a title (Layers, Frames, Shapes) folds with a click on its header, clear of its plus. - ui/sections.ts holds the rules as pure functions, SectionStack is the column and SectionHeader the band. Every title of the inspector goes through addTitle or sectionHeader in inspector/host.ts. Decided here: - A fold is kept for good, in localStorage of this browser. The issue asked whether for the session or for good and the answer left it open. - A fold is remembered by title, per panel. PROPERTIES folded once is folded on every object, asset and node. A number in a title does not count. - A behavior asset has all its rows under SWITCHES. A Variables asset and a state machine get a group SCOPE. - A greyed out control in a band takes the click too. Without that the click fell through to the band and folded the group. - The Curve tab has no column of this kind and is unchanged. Found on the way: - The inspector of a sprite is taller than the 800 pixel window of the checks now. The hooks that hand out a row scroll it into view first, and module 28 scrolls before it looks for a row by its text. Tests: - Gate: 202 files, 3008 tests (2982 + 26), exit 0 - e2e: no complete run for this state. Modules 28 to 61 passed alone (749 checks). A full run was cut off in the accounts module at 1492 passes without a failure, the modules after it and the smokes are missing. The sum of 1639 (1635 + 4) is reckoned, CI measures it. - 26 unit tests in tests/editor/sections.test.ts - Four e2e checks with a real mouse, three in module 02 and one in module 48 - 25 unit counter-probes all fail tests, run on stein2 - Screenshots of the bands looked at before the last build, none after it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c5ba21533d
commit
393caadc9d
22 files changed
+1072
-53
No files matched your search
@@ -1,5 +1,15 @@
|
||||
import type { AssetType } from '../../core/model/AssetTypes';
|
||||
import { Button, Label, Panel, TextField, Widget, activeDrag, currentMenu, ui } from '../../ui';
|
||||
import {
|
||||
Button,
|
||||
Label,
|
||||
Panel,
|
||||
SectionHeader,
|
||||
TextField,
|
||||
Widget,
|
||||
activeDrag,
|
||||
currentMenu,
|
||||
ui,
|
||||
} from '../../ui';
|
||||
import { Theme } from '../../ui/Theme';
|
||||
import { currentFontPicker } from '../font/FontPicker';
|
||||
import { currentGroupDialog } from '../panels/GroupNameDialog';
|
||||
@@ -59,7 +69,10 @@ export function uiHooks({ app, state, editor }: HookContext) {
|
||||
const row = owner?.parent;
|
||||
if (!row || !owner) return null;
|
||||
const control = row.children[row.children.indexOf(owner) + 1];
|
||||
return control instanceof Widget ? control : null;
|
||||
if (!(control instanceof Widget)) return null;
|
||||
// Taller than the window since its groups have bands (#290): the row is scrolled into view.
|
||||
inspector.reveal(control);
|
||||
return control;
|
||||
};
|
||||
/**
|
||||
* The visible text of the overlay layer, in drawing order – everything an open popup shows.
|
||||
@@ -169,6 +182,7 @@ export function uiHooks({ app, state, editor }: HookContext) {
|
||||
walk(inspector);
|
||||
const label = found as Label | null;
|
||||
if (!label) return null;
|
||||
inspector.reveal(label);
|
||||
const shown = label.children.find((child): child is Text => child instanceof Text);
|
||||
const row = label.parent;
|
||||
const next = row?.children[row.children.indexOf(label) + 1];
|
||||
@@ -180,6 +194,23 @@ export function uiHooks({ app, state, editor }: HookContext) {
|
||||
pressable: label.eventMode === 'static',
|
||||
};
|
||||
},
|
||||
/**
|
||||
* The band of a group of rows (#290), by its title: where to click it clear of its controls, its
|
||||
* rectangle and whether the group is folded. The first one showing, or the last with `last`.
|
||||
*/
|
||||
section: (title: string, last = false) => {
|
||||
const found: SectionHeader[] = [];
|
||||
const walk = (node: Container): void => {
|
||||
if (!node.visible) return;
|
||||
if (node instanceof SectionHeader && node.title === title) found.push(node);
|
||||
for (const child of node.children) walk(child);
|
||||
};
|
||||
walk(app.stage);
|
||||
const header = last ? found.at(-1) : found[0];
|
||||
if (!header) return null;
|
||||
const rect = rectOf(header);
|
||||
return { x: rect.x + 60, y: rect.y + rect.h / 2, rect, collapsed: header.sectionCollapsed };
|
||||
},
|
||||
/** The inspector panel on screen – what tells whether a row of it can be clicked at all. */
|
||||
inspectorRect: () => rectOf(inspector),
|
||||
/** Where the focused widget sits on screen, or `null` – for checks on its focus border. */
|
||||
|
||||
Reference in new issue
Block a user