mod logic;
pub(in crate::gui::editor) use logic::{
DRIVEN_ANGLE_HINT, is_relation_text, plan_tier_save, relation_cleared_sentence,
relation_placeholder_angle_deg, save_error_text_and_field, split_driven_targets,
with_followers,
};
use std::{
cell::RefCell,
rc::Rc,
sync::{Arc, Mutex},
};
use indicatrix_cut_core::EditError;
use slint::ComponentHandle;
use super::{
state::EditorState,
view::{SolidLastSolved, refresh_editor_panel_stale, submit_preview_replan},
};
use crate::{
MainWindow, RelationModel,
bridge::render_thread::RenderContext,
gui::{show_toast, solid_preview::preview_state::SolidPreviewState},
};
pub(in crate::gui::editor) fn refresh_with_followers(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
st: &EditorState,
dirty: impl IntoIterator<Item = usize>,
) {
let dirty = with_followers(&st.design, dirty);
refresh_editor_panel_stale(ui, render_ctx, st, &dirty);
submit_preview_replan(
ui,
render_ctx,
preview_state,
solid_last_solved,
st,
dirty,
false,
);
}
pub(in crate::gui::editor) fn edit_error_text(st: &mut EditorState, error: &EditError) -> String {
st.take_refusal()
.map_or_else(|| error.to_string(), |refusal| refusal.to_string())
}
pub(in crate::gui::editor) fn take_cleared_relations_sentence(
st: &mut EditorState,
) -> Option<String> {
st.take_relation_notice()
.as_ref()
.and_then(relation_cleared_sentence)
}
pub(in crate::gui::editor) fn setup_relation_callbacks(
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::<RelationModel>()
.on_remove_relation(move |index: i32| {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let Ok(index) = usize::try_from(index) else {
return;
};
let mut st = state.borrow_mut();
let label = st.design.relation_label(index);
match st.clear_tier_relation(index) {
Ok(None) => {}
Ok(Some(_)) => {
refresh_with_followers(
&ui,
&render_ctx,
&preview_state,
&solid_last_solved,
&st,
[index],
);
drop(st);
show_toast(
&ui,
&format!("{label} no longer follows a relation. It keeps its angle."),
"info",
);
}
Err(error) => {
drop(st);
show_toast(&ui, &error.to_string(), "error");
}
}
});
let ui_weak = ui.as_weak();
ui.global::<RelationModel>()
.on_explain_driven_angle(move || {
if let Some(ui) = ui_weak.upgrade() {
show_toast(&ui, DRIVEN_ANGLE_HINT, "info");
}
});
}