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:
1 parent
c8da3b78f3
commit
bdc15d2204
9 files changed
+1003
-12
No files matched your search
@@ -18,7 +18,9 @@ pub mod dialogs_assembly;
|
||||
pub mod dialogs_plastic;
|
||||
pub mod dialogs_sheet;
|
||||
pub mod dim_view;
|
||||
pub mod documents;
|
||||
pub mod gpu;
|
||||
pub mod home;
|
||||
pub mod icons;
|
||||
pub mod inference;
|
||||
#[cfg(test)]
|
||||
@@ -164,6 +166,10 @@ pub struct SolveApp {
|
||||
shot_token: u64,
|
||||
styled: bool,
|
||||
fitted: bool,
|
||||
/// The start page.
|
||||
pub home: home::HomeState,
|
||||
/// The other open designs (tabs).
|
||||
pub docs: documents::Documents,
|
||||
}
|
||||
|
||||
impl SolveApp {
|
||||
@@ -199,6 +205,8 @@ impl SolveApp {
|
||||
shot_token: 0,
|
||||
styled: false,
|
||||
fitted: false,
|
||||
home: home::HomeState::default(),
|
||||
docs: documents::Documents::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +227,7 @@ impl SolveApp {
|
||||
"visual_style": self.ui.visual_style,
|
||||
"browser_collapsed": self.tree.collapsed,
|
||||
"browser_expanded": self.tree.expanded,
|
||||
"recent": self.home.recent,
|
||||
})
|
||||
.to_string()
|
||||
}
|
||||
@@ -254,6 +263,11 @@ impl SolveApp {
|
||||
};
|
||||
self.tree.collapsed = keys("browser_collapsed");
|
||||
self.tree.expanded = keys("browser_expanded");
|
||||
self.home.recent = v
|
||||
.get("recent")
|
||||
.and_then(Value::as_array)
|
||||
.map(|a| a.iter().filter_map(Value::as_str).take(home::MAX_RECENT).map(str::to_string).collect())
|
||||
.unwrap_or_default();
|
||||
}
|
||||
|
||||
pub fn with_control(mut self, rx: Receiver<ControlRequest>) -> Self {
|
||||
@@ -271,6 +285,11 @@ impl SolveApp {
|
||||
self.cam = Camera::default();
|
||||
self.fit_view();
|
||||
}
|
||||
if matches!(id, "doc.open" | "SaveDocumentCommand" | "SaveDocumentAsCommand")
|
||||
&& let Some(p) = self.session.path.clone()
|
||||
{
|
||||
self.home.add_recent(&p);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
self.session.echo(format!("{id}: {e}"));
|
||||
@@ -290,6 +309,7 @@ impl SolveApp {
|
||||
/// that have them, otherwise run it with defaults.
|
||||
pub fn start(&mut self, id: &str) {
|
||||
self.tool = None;
|
||||
self.home.open = false;
|
||||
if matches!(id, "FusionImportCommandFromToolbar" | "ParaMeshInsertAlignCommand") {
|
||||
if let Some(p) = self.services.pick_open.as_ref().and_then(|f| f()) {
|
||||
self.insert_path(&p);
|
||||
@@ -455,6 +475,8 @@ impl SolveApp {
|
||||
}
|
||||
|
||||
pub fn open_path(&mut self, path: &str) {
|
||||
self.home.open = false;
|
||||
documents::prepare_open(self);
|
||||
if self.run("doc.open", json!({ "path": path })).is_ok() {
|
||||
self.fit_view();
|
||||
}
|
||||
@@ -599,6 +621,14 @@ impl SolveApp {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let t0 = now_ms();
|
||||
toolbar::app_bar(self, ui);
|
||||
documents::prompt(self, ui.ctx());
|
||||
if self.home.open {
|
||||
home::show(self, ui);
|
||||
if self.home.open {
|
||||
self.frame_ms = now_ms() - t0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
toolbar::toolbar(self, ui);
|
||||
if self.ui.show_timeline {
|
||||
timeline::timeline(self, ui);
|
||||
|
||||
Reference in new issue
Block a user