// SPDX-FileCopyrightText: 2024 Topola contributors // // SPDX-License-Identifier: MIT use std::ops::ControlFlow; use spade::InsertionError; use crate::{ autorouter::{ execution::Command, history::History, invoker::{Invoker, InvokerError}, Autorouter, }, board::{AccessMesadata, Board}, interactor::activity::{ ActivityContext, ActivityError, ActivityStepperWithStatus, InteractiveInput, }, stepper::{Abort, Step}, }; /// Structure that manages the invoker and activities pub struct Interactor { invoker: Invoker, activity: Option, } impl Interactor { /// Create a new instance of Interactor with the given Board instance pub fn new(board: Board) -> Result { Ok(Self { invoker: Invoker::new(Autorouter::new(board)?), activity: None, }) } /// Execute a command pub fn execute(&mut self, command: Command) -> Result<(), InvokerError> { self.invoker.execute(command) } /// Start executing an activity pub fn schedule(&mut self, command: Command) -> Result<(), InvokerError> { self.activity = Some(ActivityStepperWithStatus::new_execution( self.invoker.execute_stepper(command)?, )); Ok(()) } /// Undo last command pub fn undo(&mut self) -> Result<(), InvokerError> { self.invoker.undo() } /// Redo last command pub fn redo(&mut self) -> Result<(), InvokerError> { self.invoker.redo() } /// Abort the currently running execution or activity pub fn abort(&mut self) { if let Some(ref mut activity) = self.activity { activity.abort(&mut ActivityContext:: { interactive_input: &InteractiveInput { pointer_pos: [0.0, 0.0].into(), dt: 0.0, }, invoker: &mut self.invoker, }); } } /// Replay last command pub fn replay(&mut self, history: History) { self.invoker.replay(history); } /// Update the currently running execution or activity pub fn update( &mut self, interactive_input: &InteractiveInput, ) -> ControlFlow> { if let Some(ref mut activity) = self.activity { return match activity.step(&mut ActivityContext { interactive_input, invoker: &mut self.invoker, }) { Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()), Ok(ControlFlow::Break(_msg)) => ControlFlow::Break(Ok(())), Err(err) => { self.activity = None; ControlFlow::Break(Err(err)) } }; } ControlFlow::Break(Ok(())) } /// Returns the invoker pub fn invoker(&self) -> &Invoker { &self.invoker } /// Returns the currently running activity pub fn maybe_activity(&self) -> &Option { &self.activity } }