Files
ARCADIA-Studio/crates/oa-desktop/src/app/scenario_spacing.rs
T

89 lines
3.7 KiB
Rust

//! Admit spacing packets before ordinary navigation can retire a newer reveal.
use super::*;
use behavior::scenario::spacing::{Event, controller::Finish};
#[cfg(test)]
mod tests;
impl App {
pub(super) fn spacing_enabled(&self) -> bool {
self.pending_diagram_reveal.is_none()
&& !self.behavior.has_pending()
&& !self.draft_dirty()
&& !self.source_dirty()
&& !self.source_rename.open()
&& behavior::canvas_workspace::keyboard_enabled(self)
}
pub(super) fn scenario_spacing(&mut self, event: Event) -> Task<Message> {
let stamp = event.stamp();
if self.scenario_context() != Some(stamp.context) || self.camera_epoch != stamp.camera_epoch
{
return Task::none();
}
let state = &self.behavior.scenario;
let matches =
state.spacing_token() == Some(event.token()) && state.spacing_stamp() == Some(stamp);
if match event {
Event::Begin { token, .. } => token.is_nil() || state.spacing_token().is_some(),
_ => !matches,
} {
return Task::none();
}
if matches!(event, Event::Cancel { .. }) || !self.spacing_enabled() {
if self.behavior.scenario.cancel_spacing() {
self.canvas_epoch = self.canvas_epoch.wrapping_add(1);
}
return Task::none();
}
match event {
Event::Begin { .. } => {
let mut state = std::mem::take(&mut self.behavior.scenario);
let result = state.begin_spacing(self.project(), event);
self.behavior.scenario = state;
if result.is_err() {
self.status = "The drag could not start in this view. Try again.".into();
}
}
Event::Move { screen, .. } => self.behavior.scenario.move_spacing(screen),
Event::Finish { screen, .. } => {
let finished = self.behavior.scenario.finish_spacing(screen);
// Retire queued packets even for zero motion or a refused finish.
self.canvas_epoch = self.canvas_epoch.wrapping_add(1);
match finished {
Ok(Finish::Click(target)) => self.select(target),
Ok(Finish::Noop) => {}
Ok(Finish::Commit {
command,
selected,
scale,
pan,
}) => {
// Document prepares and writes the source candidate before
// committing its snapshot. Failure leaves camera/selection
// and source/history at their accepted values.
match self.document.execute(*command) {
Ok(_) => {
self.selected = selected;
self.selected_node = None;
self.diagram_navigation_focus = None;
self.behavior.scenario.accept_spacing_camera(scale, pan);
self.sync();
self.status = "Scenario spacing updated.".into();
}
Err(error) => self.status = format!("Spacing was not applied: {error}"),
}
}
Err(_) => {
self.status =
"That position cannot be applied. The saved arrangement is unchanged."
.into()
}
}
}
Event::Cancel { .. } => unreachable!(),
}
Task::none()
}
}