use std::{
cell::RefCell,
collections::BTreeSet,
rc::Rc,
sync::{Arc, Mutex},
};
use indicatrix::geometry::meet_solver::MeetConstraint;
use indicatrix_cut_core::Edit;
use slint::ComponentHandle;
use crate::{
EditorModel, MainWindow,
bridge::render_thread::RenderContext,
gui::{
editor::{
stall_guard::stall_guard,
state::EditorState,
view::{
SolidLastSolved, refresh_all_now, refresh_editor_panel_stale, submit_preview_replan,
},
},
show_toast,
solid_preview::preview_state::SolidPreviewState,
},
};
pub(super) fn setup_adopt_all_callback(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
) {
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();
ui.global::<EditorModel>().on_adopt_all(move || {
stall_guard("on_adopt_all", || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let mut st = state.borrow_mut();
match st.adopt_all_imported_meets() {
Ok(0) => {}
Ok(count) => {
drop(st);
refresh_all_now(
&ui,
&render_ctx,
&preview_state,
&solid_last_solved,
&state,
false,
);
let plural = if count == 1 { "" } else { "s" };
show_toast(
&ui,
&format!("Adopted {count} imported meet{plural}"),
"info",
);
}
Err(e) => show_toast(&ui, &e.to_string(), "error"),
}
});
});
}
pub(super) fn setup_adopt_selected_callback(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
) {
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();
ui.global::<EditorModel>().on_adopt_selected(move || {
stall_guard("on_adopt_selected", || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let mut st = state.borrow_mut();
match st.adopt_selected_imported_meets() {
Ok(0) => {}
Ok(count) => {
drop(st);
refresh_all_now(
&ui,
&render_ctx,
&preview_state,
&solid_last_solved,
&state,
false,
);
let plural = if count == 1 { "" } else { "s" };
show_toast(
&ui,
&format!("Adopted {count} imported meet{plural} from the selection"),
"info",
);
}
Err(e) => show_toast(&ui, &e.to_string(), "error"),
}
});
});
}
pub(super) fn setup_pin_to_mast_callback(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
) {
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();
ui.global::<EditorModel>()
.on_pin_to_mast(move |index: i32| {
stall_guard("on_pin_to_mast", || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let Ok(index) = usize::try_from(index) else {
return;
};
let Some(mast) = solid_last_solved
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.as_ref()
.and_then(|(_, solved)| solved.get(index))
.map(|tier| tier.mast)
else {
return;
};
let mut st = state.borrow_mut();
match st.apply(Edit::SetConstraint {
index,
constraint: MeetConstraint::ScaleReference(mast),
}) {
Ok(()) => {
let dirty: BTreeSet<usize> = std::iter::once(index).collect();
refresh_editor_panel_stale(&ui, &render_ctx, &st, &dirty);
submit_preview_replan(
&ui,
&render_ctx,
&preview_state,
&solid_last_solved,
&st,
dirty,
false,
);
show_toast(
&ui,
&format!("Pinned tier {} at {mast:.4}", index + 1),
"info",
);
}
Err(e) => show_toast(&ui, &e.to_string(), "error"),
}
});
});
}