The scene view and the animation preview share one camera, the three form dialogs one base, and keys are found through one set of helpers (#85)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf02c9e8b3
commit
2a390e52ff
22 files changed
+418
-452
No files matched your search
@@ -0,0 +1,62 @@
|
||||
import { Button, type ButtonOptions, HStack, Label, Popup, Spacer, Theme, type Widget } from '../ui';
|
||||
|
||||
/** Matches the inspector's label column. */
|
||||
const LABEL_WIDTH = 76;
|
||||
|
||||
/**
|
||||
* A small modal form – the texture's Slice dialog, the timeline's row and frames dialogs: a bold
|
||||
* title, rows led by a label in the inspector's label column, Cancel and a confirming button last.
|
||||
*/
|
||||
export abstract class FormDialog extends Popup {
|
||||
protected constructor(minWidth: number, title: string) {
|
||||
super({ modal: true, padding: Theme.padding * 2, gap: Theme.gap });
|
||||
this.minWidth = minWidth;
|
||||
this.content.add(new Label(title, { style: 'bodyBold' }));
|
||||
}
|
||||
|
||||
protected fieldLabel(text: string): Label {
|
||||
const label = new Label(text, { style: 'muted' });
|
||||
label.minWidth = LABEL_WIDTH;
|
||||
return label;
|
||||
}
|
||||
|
||||
/** A row of `widgets`, left-aligned at the height of an inspector row. */
|
||||
protected formRow(...widgets: Widget[]): HStack {
|
||||
const row = new HStack({ gap: Theme.gap, align: 'center' });
|
||||
row.minHeight = Theme.rowHeight;
|
||||
for (const widget of widgets) row.add(widget);
|
||||
row.add(new Spacer(), 1);
|
||||
return row;
|
||||
}
|
||||
|
||||
/** Cancel and the confirming button, right-aligned; the dialog closes before `onConfirm` runs. */
|
||||
protected addButtons(text: string, variant: ButtonOptions['variant'], onConfirm: () => void): Button {
|
||||
const buttons = new HStack({ gap: Theme.gap, align: 'center' });
|
||||
buttons.add(new Spacer(), 1);
|
||||
const cancel = new Button('Cancel');
|
||||
cancel.onClick = this.closeThen();
|
||||
buttons.add(cancel);
|
||||
const confirm = new Button(text, { variant });
|
||||
confirm.onClick = this.closeThen(onConfirm);
|
||||
buttons.add(confirm);
|
||||
this.content.add(buttons);
|
||||
return confirm;
|
||||
}
|
||||
}
|
||||
|
||||
/** One open dialog of a kind at a time: opening the next closes the last. `current` is for the check scripts. */
|
||||
export function dialogSlot<T extends Popup>(): { current(): T | null; open(dialog: T): T } {
|
||||
let current: T | null = null;
|
||||
return {
|
||||
current: () => current,
|
||||
open(dialog) {
|
||||
current?.close();
|
||||
current = dialog;
|
||||
dialog.onClose = () => {
|
||||
if (current === dialog) current = null;
|
||||
};
|
||||
dialog.openCentered();
|
||||
return dialog;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user