use std::{cell::RefCell, rc::Rc};
use slint::{ComponentHandle, SharedString};
use crate::{
EditorModel, MainWindow,
gui::editor::state::{
EditorState, representative_crown_and_pavilion_angles_deg, tier_matches_filter,
},
};
pub(in crate::gui::editor) fn setup_tier_filter_callback(ui: &MainWindow) {
ui.global::<EditorModel>().on_tier_matches_filter(
|haystack: SharedString, filter: SharedString| tier_matches_filter(&haystack, &filter),
);
}
pub(in crate::gui::editor) fn setup_angle_live_preview_callback(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
) {
let state = Rc::clone(state);
let ui_weak = ui.as_weak();
ui.global::<EditorModel>()
.on_angle_live_preview(move |text: SharedString| {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let model = ui.global::<EditorModel>();
let clear = || {
model.set_angle_live_margin_text(SharedString::new());
model.set_angle_live_margin_level(-1);
model.set_angle_live_margin_is_estimate(false);
};
let Ok(angle_deg) = text.trim().parse::<f64>() else {
clear();
return;
};
let st = state.borrow();
let n_d = st.design.effective_refractive_index();
if angle_deg < 0.0 {
let margin = indicatrix_cut_core::tier_margin_deg(angle_deg, n_d);
let level = match indicatrix_cut_core::windowing_risk(angle_deg, n_d) {
indicatrix_cut_core::Risk::Safe => 0,
indicatrix_cut_core::Risk::Marginal => 1,
indicatrix_cut_core::Risk::Windows => 2,
};
model.set_angle_live_margin_text(format!("{margin:+.1}\u{b0}").into());
model.set_angle_live_margin_level(level);
model.set_angle_live_margin_is_estimate(false);
} else if angle_deg > 0.0 {
let (_, pavilion_deg) = representative_crown_and_pavilion_angles_deg(&st.design);
let Some(pavilion_deg) = pavilion_deg else {
clear();
return;
};
let margin =
indicatrix_cut_core::crown_window_margin_deg(pavilion_deg, angle_deg, n_d);
let level =
match indicatrix_cut_core::crown_windowing_risk(pavilion_deg, angle_deg, n_d) {
indicatrix_cut_core::Risk::Safe => 0,
indicatrix_cut_core::Risk::Marginal => 1,
indicatrix_cut_core::Risk::Windows => 2,
};
model.set_angle_live_margin_text(format!("{margin:+.1}\u{b0}").into());
model.set_angle_live_margin_level(level);
model.set_angle_live_margin_is_estimate(true);
} else {
clear();
}
});
}
pub(in crate::gui::editor) fn setup_anchor_explainer_dismiss_callback(ui: &MainWindow) {
let ui_weak = ui.as_weak();
ui.global::<EditorModel>()
.on_anchor_explainer_dismiss(move |dont_show_again: bool| {
let Some(ui) = ui_weak.upgrade() else {
return;
};
ui.global::<EditorModel>().set_anchor_explainer_open(false);
if dont_show_again {
crate::gui::editor::state::anchor_explainer_suppress_permanently();
}
});
}
pub(super) fn bump_form_reset_pulse(ui: &MainWindow) {
let pulse = ui.global::<EditorModel>().get_form_reset_pulse();
ui.global::<EditorModel>()
.set_form_reset_pulse(pulse.wrapping_add(1));
}
pub(super) fn adjust_selection_after_remove(ui: &MainWindow, removed_index: i32) {
let selected = ui.global::<EditorModel>().get_selected_tier_index();
if selected == removed_index {
ui.global::<EditorModel>().set_selected_tier_index(-1);
bump_form_reset_pulse(ui);
} else if selected > removed_index {
ui.global::<EditorModel>()
.set_selected_tier_index(selected - 1);
}
}
pub(super) fn clamp_selection_to_tier_count(ui: &MainWindow, tier_count: usize) {
let selected = ui.global::<EditorModel>().get_selected_tier_index();
let out_of_range = usize::try_from(selected).is_ok_and(|index| index >= tier_count);
if out_of_range {
ui.global::<EditorModel>().set_selected_tier_index(-1);
bump_form_reset_pulse(ui);
}
}