Start page and document tabs

Start page (shown on launch without a file, and from the house button in the application bar):
New Design, Open, recent designs (kept in the preferences, newest first) and built-in samples,
each card with a picture rendered from the design in the background. Samples are scripts of
engine commands: the sample plate plus a sheet metal bracket, a hinge assembly with a revolute
joint, a plastic enclosure (lip, bosses, rest, snap fit), a bolted flange with a parametric
circular pattern and a vent plate with a parametric rectangular pattern (test: all build
without a failing feature).

Several open designs as tabs in the application bar: each keeps its own session (undo,
selection), camera and hidden/shown items; + and Ctrl+N open a new design, opening a file or a
sample uses a new tab unless the current design is blank, closing a tab with unsaved changes
asks Save / Don't Save / Cancel. Control channel: ui.documents and ui.home (docs/control-protocol.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 09:23:46 +00:00
1 parent c8da3b78f3
commit bdc15d2204
9 files changed
+1003 -12

No files matched your search

+17
View File
@@ -104,7 +104,24 @@ pub fn handle(app: &mut SolveApp, ctx: &egui::Context, req: &ControlRequest) ->
"frame_ms": app.frame_ms,
"build_ms": app.viewport.build_ms,
"preview": {"active": app.preview.active, "busy": app.preview.busy, "error": app.preview.error, "ms": app.preview.ms, "replaced": app.preview.replaced},
"home": app.home.open,
"documents": app.docs.count(),
})),
"ui.documents" => ok(crate::documents::control(app, p)),
"ui.home" => {
match p.get("open").and_then(Value::as_bool) {
Some(true) => {
let rev = app.session.revision;
app.home.show(rev);
}
Some(false) => app.home.open = false,
None => {}
}
if let Some(i) = p.get("sample").and_then(Value::as_u64) {
crate::home::open_sample(app, i as usize);
}
ok(json!({"open": app.home.open, "recent": app.home.recent}))
}
"ui.set" => {
let mut cur = serde_json::to_value(&app.ui).unwrap_or(json!({}));
if let (Some(o), Some(src)) = (cur.as_object_mut(), p.as_object()) {