use std::{
cell::RefCell,
rc::Rc,
sync::{Arc, Mutex},
};
use indicatrix_cut_core::FreshDesignSpec;
use slint::{ComponentHandle, SharedString};
use super::{FIXED_CYLINDER_PREFORM_SIDES, misc::bump_form_reset_pulse};
use crate::{
EditorModel, MainWindow,
bridge::render_thread::RenderContext,
gui::{
editor::{
callbacks::solve_actions::clear_analysis_results,
guide, loading,
stall_guard::stall_guard,
state::{EditorState, PendingUnsavedAction, gear_choice_to_teeth},
view::{SolidLastSolved, push_has_design, refresh_all_now},
},
show_toast,
solid_preview::preview_state::SolidPreviewState,
},
};
pub(in crate::gui::editor) fn setup_new_design_create_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_new_design_create(
move |shape_index: i32,
half_width: SharedString,
length_over_width: SharedString,
depth: SharedString,
gear_preset_index: i32,
gear_custom_text: SharedString,
symmetry_order_text: SharedString,
mirror: bool,
material_index: i32,
template_index: i32| {
stall_guard("on_new_design_create", || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let gear_teeth = match gear_choice_to_teeth(gear_preset_index, &gear_custom_text) {
Ok(t) => t,
Err(e) => {
show_toast(&ui, &e, "error");
return;
}
};
let preform = match loading::parse_preform_form(
shape_index,
&half_width,
&length_over_width,
&depth,
FIXED_CYLINDER_PREFORM_SIDES,
) {
Ok(p) => p,
Err(e) => {
show_toast(&ui, &e, "error");
return;
}
};
match loading::parse_new_design_form(
gear_teeth,
preform,
&symmetry_order_text,
mirror,
material_index,
) {
Ok(spec) => {
if state.borrow().is_dirty() {
state.borrow_mut().pending_unsaved_action =
Some(PendingUnsavedAction::New {
spec,
template_index,
});
ui.global::<EditorModel>().set_unsaved_dialog_message(
"Starting a new design will discard the current one's unsaved \
changes."
.into(),
);
ui.global::<EditorModel>().set_unsaved_dialog_open(true);
} else {
do_new_design_create(
&ui,
&state,
&render_ctx,
&preview_state,
&solid_last_solved,
spec,
template_index,
);
}
}
Err(e) => show_toast(&ui, &e, "error"),
}
});
},
);
}
pub(super) fn do_new_design_create(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
spec: FreshDesignSpec,
template_index: i32,
) {
install_new_design(&mut state.borrow_mut(), spec, template_index);
clear_analysis_results(ui);
ui.global::<EditorModel>()
.set_material_suggestion_name("".into());
ui.global::<EditorModel>()
.set_material_suggestion_text("".into());
refresh_all_now(
ui,
render_ctx,
preview_state,
solid_last_solved,
state,
true,
);
ui.global::<EditorModel>().set_selected_tier_index(-1);
bump_form_reset_pulse(ui);
ui.global::<EditorModel>().set_new_dialog_open(false);
ui.global::<EditorModel>().set_is_dirty(false);
ui.set_loaded_design_name(SharedString::new());
push_has_design(ui, &state.borrow());
guide::notify(ui, guide::NEW_DESIGN_CREATED);
}
pub(super) fn install_new_design(st: &mut EditorState, spec: FreshDesignSpec, template_index: i32) {
st.replace_wholesale(EditorState::fresh_from_template(spec, template_index));
st.has_design = true;
}