use crate::{
BatchModel, EditorModel, GuideModel, LibraryModel, MainWindow, PreferencesModel,
SolidPreviewModel,
};
use slint::ComponentHandle;
use std::collections::HashSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GuideGroup {
NewDesign,
TierForm,
TierTable,
DesignSettings,
Solve,
PreformTab,
Advanced,
ViewTabs,
FileOps,
History,
ConcaveTier,
}
impl GuideGroup {
pub const ALL: [Self; 11] = [
Self::NewDesign,
Self::TierForm,
Self::TierTable,
Self::DesignSettings,
Self::Solve,
Self::PreformTab,
Self::Advanced,
Self::ViewTabs,
Self::FileOps,
Self::History,
Self::ConcaveTier,
];
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Fact {
Editor,
Design,
TierSelected,
CanUndo,
CanRedo,
Busy,
SolveRunning,
DeepSolveRunning,
OptimizeRunning,
DeepSolveAvailable,
OptimizeAvailable,
HasSnapshot,
HasLastSaved,
LibrarySelected,
PreviewBatchRunning,
TiltBatchRunning,
SimpleInterface,
EditView,
DiagramView,
Allows(GuideGroup),
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CommandState {
facts: HashSet<Fact>,
}
impl CommandState {
#[must_use]
pub fn has(&self, fact: Fact) -> bool {
self.facts.contains(&fact)
}
pub fn set(&mut self, fact: Fact, on: bool) {
if on {
self.facts.insert(fact);
} else {
self.facts.remove(&fact);
}
}
#[must_use]
pub fn without_guide_locks(mut self) -> Self {
for group in GuideGroup::ALL {
self.set(Fact::Allows(group), true);
}
self
}
#[must_use]
pub fn capture(ui: &MainWindow) -> Self {
let editor = ui.global::<EditorModel>();
let guide = ui.global::<GuideModel>();
let batch = ui.global::<BatchModel>();
let busy = !editor.get_busy_action().is_empty();
let mut state = Self::default();
state.set(Fact::Editor, editor.get_enabled());
state.set(Fact::Design, editor.get_has_design());
state.set(Fact::TierSelected, editor.get_selected_tier_index() >= 0);
state.set(Fact::CanUndo, editor.get_can_undo());
state.set(Fact::CanRedo, editor.get_can_redo());
state.set(Fact::Busy, busy);
state.set(Fact::SolveRunning, editor.get_solve_running());
state.set(Fact::DeepSolveRunning, editor.get_deep_solve_running());
state.set(Fact::OptimizeRunning, editor.get_optimize_running());
state.set(Fact::DeepSolveAvailable, editor.get_deep_solve_available());
state.set(Fact::OptimizeAvailable, editor.get_optimize_available());
state.set(Fact::HasSnapshot, editor.get_has_snapshot());
state.set(Fact::HasLastSaved, !editor.get_last_saved_path().is_empty());
state.set(
Fact::LibrarySelected,
ui.global::<LibraryModel>().get_selected_entry_id() >= 0,
);
state.set(Fact::PreviewBatchRunning, batch.get_preview_batch_running());
state.set(Fact::TiltBatchRunning, batch.get_tilt_batch_running());
state.set(
Fact::SimpleInterface,
ui.global::<PreferencesModel>().get_simple_mode(),
);
state.set(
Fact::EditView,
ui.get_active_tab() == 0 && ui.get_render_view_tab() == 1,
);
state.set(
Fact::DiagramView,
ui.global::<SolidPreviewModel>().get_view_mode() == 3,
);
for (group, allowed) in [
(GuideGroup::NewDesign, guide.invoke_allows_new_design()),
(GuideGroup::TierForm, guide.invoke_allows_tier_form()),
(GuideGroup::TierTable, guide.invoke_allows_tier_table()),
(
GuideGroup::DesignSettings,
guide.invoke_allows_design_settings(),
),
(GuideGroup::Solve, guide.invoke_allows_solve()),
(GuideGroup::PreformTab, guide.invoke_allows_preform_tab()),
(GuideGroup::Advanced, guide.invoke_allows_advanced()),
(GuideGroup::ViewTabs, guide.invoke_allows_view_tabs()),
(GuideGroup::FileOps, guide.invoke_allows_file_ops()),
(GuideGroup::History, guide.invoke_allows_history()),
(GuideGroup::ConcaveTier, guide.invoke_allows_concave_tier()),
] {
state.set(Fact::Allows(group), allowed);
}
state
}
}
#[cfg(test)]
impl CommandState {
#[must_use]
pub fn ready() -> Self {
let mut state = Self::default();
for fact in [
Fact::Editor,
Fact::Design,
Fact::TierSelected,
Fact::CanUndo,
Fact::CanRedo,
Fact::SolveRunning,
Fact::DeepSolveRunning,
Fact::OptimizeRunning,
Fact::DeepSolveAvailable,
Fact::OptimizeAvailable,
Fact::HasSnapshot,
Fact::HasLastSaved,
Fact::LibrarySelected,
Fact::EditView,
] {
state.set(fact, true);
}
for group in GuideGroup::ALL {
state.set(Fact::Allows(group), true);
}
state
}
#[must_use]
pub fn with(mut self, fact: Fact, on: bool) -> Self {
self.set(fact, on);
self
}
}