use super::{auto_solve, edit_intent, native_io, stall_guard, state::EditorState, view};
use crate::{
MainWindow, bridge::render_thread::RenderContext,
gui::solid_preview::preview_state::SolidPreviewState,
};
use slint::{ComponentHandle as _, Model as _};
use std::{
cell::RefCell,
rc::Rc,
sync::{Arc, Mutex},
};
pub(super) fn setup_solve_cancel_callback(ui: &MainWindow) {
let ui_weak = ui.as_weak();
ui.global::<crate::EditorModel>().on_solve_cancel(move || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
auto_solve::cancel_in_flight_solve();
let model = ui.global::<crate::EditorModel>();
model.set_solve_running(false);
model.set_solve_state("stale".into());
model.set_status_text("Solve abandoned -- click Solve when you are ready.".into());
model.set_status_is_problem(true);
});
}
pub(super) fn setup_startup_restore(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &view::SolidLastSolved,
) {
if let Some(path) = crate::gui::startup_file::take_requested_open() {
open_requested_design(
ui,
state,
render_ctx,
preview_state,
solid_last_solved,
path,
);
return;
}
let model = ui.global::<crate::EditorModel>();
let autosave = native_io::find_leftover_autosave();
let offer = autosave.clone().or_else(|| {
ui.get_recent_native_files()
.iter()
.next()
.map(|path| std::path::PathBuf::from(path.as_str()))
});
let Some(offer) = offer else {
return;
};
model.set_startup_restore_is_autosave(autosave.is_some());
model.set_startup_restore_path(offer.display().to_string().into());
let state_accept = Rc::clone(state);
let render_ctx_accept = Arc::clone(render_ctx);
let preview_accept = Arc::clone(preview_state);
let solved_accept = Arc::clone(solid_last_solved);
let ui_weak = ui.as_weak();
ui.global::<crate::EditorModel>()
.on_startup_restore_accept(move || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let path = ui.global::<crate::EditorModel>().get_startup_restore_path();
ui.global::<crate::EditorModel>()
.set_startup_restore_path(String::new().into());
native_io::open_recent_native_path(
&ui,
&state_accept,
&render_ctx_accept,
&preview_accept,
&solved_accept,
std::path::PathBuf::from(path.as_str()),
);
});
let ui_weak_dismiss = ui.as_weak();
ui.global::<crate::EditorModel>()
.on_startup_restore_dismiss(move || {
let Some(ui) = ui_weak_dismiss.upgrade() else {
return;
};
ui.global::<crate::EditorModel>()
.set_startup_restore_path(String::new().into());
});
let ui_weak_delete = ui.as_weak();
ui.global::<crate::EditorModel>()
.on_startup_restore_delete(move || {
let Some(ui) = ui_weak_delete.upgrade() else {
return;
};
let path = ui.global::<crate::EditorModel>().get_startup_restore_path();
ui.global::<crate::EditorModel>()
.set_startup_restore_path(String::new().into());
native_io::delete_leftover_autosave(std::path::Path::new(path.as_str()));
});
}
fn open_requested_design(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &view::SolidLastSolved,
path: std::path::PathBuf,
) {
let ui_weak = ui.as_weak();
let state = Rc::clone(state);
let render_ctx = Arc::clone(render_ctx);
let preview_state = Arc::clone(preview_state);
let solid_last_solved = Arc::clone(solid_last_solved);
slint::Timer::single_shot(std::time::Duration::from_millis(150), move || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
native_io::open_recent_native_path(
&ui,
&state,
&render_ctx,
&preview_state,
&solid_last_solved,
path,
);
});
}
pub(super) fn setup_tier_cutoff_callback(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &view::SolidLastSolved,
) {
let intent_queue = {
let state = Rc::clone(state);
let render_ctx = Arc::clone(render_ctx);
let preview_state = Arc::clone(preview_state);
let solid_last_solved = Arc::clone(solid_last_solved);
let ui_weak = ui.as_weak();
edit_intent::EditIntentQueue::new(move |_intent| {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let Ok(st) = state.try_borrow() else {
return;
};
view::submit_preview_replan(
&ui,
&render_ctx,
&preview_state,
&solid_last_solved,
&st,
std::collections::BTreeSet::new(),
false,
);
})
};
let enlarged_queue = Rc::clone(&intent_queue);
let ui_weak_enlarged = ui.as_weak();
ui.global::<crate::SolidPreviewModel>()
.on_diagram_enlarged_panel_changed(move || {
stall_guard::stall_guard("on_diagram_enlarged_panel_changed", || {
let Some(ui) = ui_weak_enlarged.upgrade() else {
return;
};
let count = ui.global::<crate::SolidPreviewModel>().get_tier_cutoff();
enlarged_queue.post(edit_intent::EditIntent::CutOff { count });
});
});
let ui_weak = ui.as_weak();
ui.global::<crate::SolidPreviewModel>()
.on_tier_cutoff_changed(move || {
stall_guard::stall_guard("on_tier_cutoff_changed", || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let count = ui.global::<crate::SolidPreviewModel>().get_tier_cutoff();
intent_queue.post(edit_intent::EditIntent::CutOff { count });
});
});
}