mirror of https://codeberg.org/topola/topola.git
stepper: refactoring
* put `Error` as an associated type into separate trait
* make `Step::finish` generic over O instead of Step
* introduce `PollStep` trait including `finish` method
* use `PollStep` in GUI, fix infinitely repeating errors
* replace {Activity,Invoker,Interaction}Status with Poll<String>
* `PollStep` provides `Step<_, Poll<_>>`
Fixes #78.
This commit is contained in:
parent
f02b7be878
commit
4171443c45
|
|
@ -9,7 +9,7 @@ use crate::{
|
||||||
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
|
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navmesh::Navmesh, route::RouteStepper, trace::TraceStepper, Router, RouterStatus},
|
router::{navmesh::Navmesh, route::RouteStepper, trace::TraceStepper, Router, RouterStatus},
|
||||||
stepper::Step,
|
stepper::{Step, StepError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -86,9 +86,11 @@ impl AutorouteExecutionStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus, AutorouterError, ()>
|
impl StepError for AutorouteExecutionStepper {
|
||||||
for AutorouteExecutionStepper
|
type Error = AutorouterError;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus> for AutorouteExecutionStepper {
|
||||||
fn step(&mut self, autorouter: &mut Autorouter<M>) -> Result<AutorouteStatus, AutorouterError> {
|
fn step(&mut self, autorouter: &mut Autorouter<M>) -> Result<AutorouteStatus, AutorouterError> {
|
||||||
let Some(curr_ratline) = self.curr_ratline else {
|
let Some(curr_ratline) = self.curr_ratline else {
|
||||||
return Ok(AutorouteStatus::Finished);
|
return Ok(AutorouteStatus::Finished);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
geometry::{primitive::PrimitiveShape, shape::MeasureLength},
|
geometry::{primitive::PrimitiveShape, shape::MeasureLength},
|
||||||
graph::MakeRef,
|
graph::MakeRef,
|
||||||
router::{navmesh::Navmesh, trace::TraceStepper},
|
router::{navmesh::Navmesh, trace::TraceStepper},
|
||||||
stepper::Step,
|
stepper::{Step, StepError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -66,9 +66,13 @@ impl CompareDetoursExecutionStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StepError for CompareDetoursExecutionStepper {
|
||||||
|
type Error = AutorouterError;
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions
|
// XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions
|
||||||
// aren't steppable either. It may be useful for debugging later on tho.
|
// aren't steppable either. It may be useful for debugging later on tho.
|
||||||
impl<M: AccessMesadata> Step<Autorouter<M>, CompareDetoursStatus, AutorouterError, (f64, f64)>
|
impl<M: AccessMesadata> Step<Autorouter<M>, CompareDetoursStatus>
|
||||||
for CompareDetoursExecutionStepper
|
for CompareDetoursExecutionStepper
|
||||||
{
|
{
|
||||||
fn step(
|
fn step(
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
|
use core::task::Poll;
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, stepper::Step};
|
use crate::{
|
||||||
|
board::mesadata::AccessMesadata,
|
||||||
|
layout::via::ViaWeight,
|
||||||
|
stepper::{PollStep, Step, StepError},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::{AutorouteExecutionStepper, AutorouteStatus},
|
autoroute::{AutorouteExecutionStepper, AutorouteStatus},
|
||||||
compare_detours::{CompareDetoursExecutionStepper, CompareDetoursStatus},
|
compare_detours::{CompareDetoursExecutionStepper, CompareDetoursStatus},
|
||||||
invoker::{Invoker, InvokerError, InvokerStatus},
|
invoker::{Invoker, InvokerError},
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
place_via::PlaceViaExecutionStepper,
|
place_via::PlaceViaExecutionStepper,
|
||||||
remove_bands::RemoveBandsExecutionStepper,
|
remove_bands::RemoveBandsExecutionStepper,
|
||||||
|
|
@ -38,30 +43,28 @@ impl ExecutionStepper {
|
||||||
fn step_catch_err<M: AccessMesadata>(
|
fn step_catch_err<M: AccessMesadata>(
|
||||||
&mut self,
|
&mut self,
|
||||||
invoker: &mut Invoker<M>,
|
invoker: &mut Invoker<M>,
|
||||||
) -> Result<InvokerStatus, InvokerError> {
|
) -> Poll<Result<String, InvokerError>> {
|
||||||
Ok(match self {
|
match self {
|
||||||
ExecutionStepper::Autoroute(autoroute) => {
|
ExecutionStepper::Autoroute(autoroute) => {
|
||||||
match autoroute.step(&mut invoker.autorouter)? {
|
match autoroute.step(&mut invoker.autorouter)? {
|
||||||
AutorouteStatus::Running => InvokerStatus::Running,
|
AutorouteStatus::Running => Poll::Pending,
|
||||||
AutorouteStatus::Routed(..) => InvokerStatus::Running,
|
AutorouteStatus::Routed(..) => Poll::Pending,
|
||||||
AutorouteStatus::Finished => {
|
AutorouteStatus::Finished => Poll::Ready("finished autorouting".to_string()),
|
||||||
InvokerStatus::Finished("finished autorouting".to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExecutionStepper::PlaceVia(place_via) => {
|
ExecutionStepper::PlaceVia(place_via) => {
|
||||||
place_via.doit(&mut invoker.autorouter)?;
|
place_via.doit(&mut invoker.autorouter)?;
|
||||||
InvokerStatus::Finished("finished placing via".to_string())
|
Poll::Ready("finished placing via".to_string())
|
||||||
}
|
}
|
||||||
ExecutionStepper::RemoveBands(remove_bands) => {
|
ExecutionStepper::RemoveBands(remove_bands) => {
|
||||||
remove_bands.doit(&mut invoker.autorouter)?;
|
remove_bands.doit(&mut invoker.autorouter)?;
|
||||||
InvokerStatus::Finished("finished removing bands".to_string())
|
Poll::Ready("finished removing bands".to_string())
|
||||||
}
|
}
|
||||||
ExecutionStepper::CompareDetours(compare_detours) => {
|
ExecutionStepper::CompareDetours(compare_detours) => {
|
||||||
match compare_detours.step(&mut invoker.autorouter)? {
|
match compare_detours.step(&mut invoker.autorouter)? {
|
||||||
CompareDetoursStatus::Running => InvokerStatus::Running,
|
CompareDetoursStatus::Running => Poll::Pending,
|
||||||
CompareDetoursStatus::Finished(total_length1, total_length2) => {
|
CompareDetoursStatus::Finished(total_length1, total_length2) => {
|
||||||
InvokerStatus::Finished(format!(
|
Poll::Ready(format!(
|
||||||
"total detour lengths are {} and {}",
|
"total detour lengths are {} and {}",
|
||||||
total_length1, total_length2
|
total_length1, total_length2
|
||||||
))
|
))
|
||||||
|
|
@ -70,27 +73,30 @@ impl ExecutionStepper {
|
||||||
}
|
}
|
||||||
ExecutionStepper::MeasureLength(measure_length) => {
|
ExecutionStepper::MeasureLength(measure_length) => {
|
||||||
let length = measure_length.doit(&mut invoker.autorouter)?;
|
let length = measure_length.doit(&mut invoker.autorouter)?;
|
||||||
InvokerStatus::Finished(format!("Total length of selected bands: {}", length))
|
Poll::Ready(format!("Total length of selected bands: {}", length))
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
.map(Ok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<Invoker<M>, InvokerStatus, InvokerError, ()> for ExecutionStepper {
|
impl StepError for ExecutionStepper {
|
||||||
fn step(&mut self, invoker: &mut Invoker<M>) -> Result<InvokerStatus, InvokerError> {
|
type Error = InvokerError;
|
||||||
match self.step_catch_err(invoker) {
|
}
|
||||||
Ok(InvokerStatus::Running) => Ok(InvokerStatus::Running),
|
|
||||||
Ok(InvokerStatus::Finished(msg)) => {
|
impl<M: AccessMesadata> PollStep<Invoker<M>, String> for ExecutionStepper {
|
||||||
|
fn poll_step(&mut self, invoker: &mut Invoker<M>) -> Poll<Result<String, InvokerError>> {
|
||||||
|
self.step_catch_err(invoker).map(|x| match x {
|
||||||
|
Ok(msg) => {
|
||||||
if let Some(command) = invoker.ongoing_command.take() {
|
if let Some(command) = invoker.ongoing_command.take() {
|
||||||
invoker.history.do_(command);
|
invoker.history.do_(command);
|
||||||
}
|
}
|
||||||
|
Ok(msg)
|
||||||
Ok(InvokerStatus::Finished(msg))
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
invoker.ongoing_command = None;
|
invoker.ongoing_command = None;
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
//! Manages the execution of routing commands within the autorouting system.
|
//! Manages the execution of routing commands within the autorouting system.
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
|
|
||||||
use contracts_try::debug_requires;
|
use contracts_try::debug_requires;
|
||||||
|
use core::cmp::Ordering;
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|
@ -11,7 +10,7 @@ use crate::{
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navmesh::Navmesh, trace::TraceStepper},
|
router::{navmesh::Navmesh, trace::TraceStepper},
|
||||||
stepper::Step,
|
stepper::{PollStep, Step},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -59,16 +58,6 @@ pub enum InvokerError {
|
||||||
Autorouter(#[from] AutorouterError),
|
Autorouter(#[from] AutorouterError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryInto<()> for InvokerStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
InvokerStatus::Running => Err(()),
|
|
||||||
InvokerStatus::Finished(..) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Invoker<M: AccessMesadata> {
|
pub struct Invoker<M: AccessMesadata> {
|
||||||
pub(super) autorouter: Autorouter<M>,
|
pub(super) autorouter: Autorouter<M>,
|
||||||
pub(super) history: History,
|
pub(super) history: History,
|
||||||
|
|
@ -93,20 +82,11 @@ impl<M: AccessMesadata> Invoker<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[debug_requires(self.ongoing_command.is_none())]
|
//#[debug_requires(self.ongoing_command.is_none())]
|
||||||
pub fn execute(&mut self, command: Command) -> Result<(), InvokerError> {
|
pub fn execute(&mut self, command: Command) -> Result<String, InvokerError> {
|
||||||
let mut execute = self.execute_stepper(command)?;
|
let mut execute = self.execute_stepper(command)?;
|
||||||
|
let res = PollStep::finish(&mut execute, self)?;
|
||||||
loop {
|
self.history.set_undone(std::iter::empty());
|
||||||
let status = match execute.step(self) {
|
Ok(res)
|
||||||
Ok(status) => status,
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let InvokerStatus::Finished(..) = status {
|
|
||||||
self.history.set_undone(std::iter::empty());
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_requires(self.ongoing_command.is_none())]
|
#[debug_requires(self.ongoing_command.is_none())]
|
||||||
|
|
@ -178,17 +158,8 @@ impl<M: AccessMesadata> Invoker<M> {
|
||||||
pub fn redo(&mut self) -> Result<(), InvokerError> {
|
pub fn redo(&mut self) -> Result<(), InvokerError> {
|
||||||
let command = self.history.last_undone()?.clone();
|
let command = self.history.last_undone()?.clone();
|
||||||
let mut execute = self.execute_stepper(command)?;
|
let mut execute = self.execute_stepper(command)?;
|
||||||
|
PollStep::finish(&mut execute, self)?;
|
||||||
loop {
|
Ok(self.history.redo()?)
|
||||||
let status = match execute.step(self) {
|
|
||||||
Ok(status) => status,
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let InvokerStatus::Finished(..) = status {
|
|
||||||
return Ok(self.history.redo()?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_requires(self.ongoing_command.is_none())]
|
#[debug_requires(self.ongoing_command.is_none())]
|
||||||
|
|
|
||||||
|
|
@ -1,63 +1,25 @@
|
||||||
|
use core::task::Poll;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
execution::ExecutionStepper,
|
execution::ExecutionStepper,
|
||||||
invoker::{
|
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker, InvokerError},
|
||||||
GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker, InvokerError,
|
|
||||||
InvokerStatus,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
board::mesadata::AccessMesadata,
|
board::mesadata::AccessMesadata,
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navmesh::Navmesh, trace::TraceStepper},
|
router::{navmesh::Navmesh, trace::TraceStepper},
|
||||||
specctra::mesadata::SpecctraMesadata,
|
specctra::mesadata::SpecctraMesadata,
|
||||||
stepper::{Abort, Step},
|
stepper::{Abort, PollStep, StepError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::interaction::{
|
use crate::interaction::{InteractionContext, InteractionError, InteractionStepper};
|
||||||
InteractionContext, InteractionError, InteractionStatus, InteractionStepper,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ActivityContext<'a> {
|
pub struct ActivityContext<'a> {
|
||||||
pub interaction: InteractionContext,
|
pub interaction: InteractionContext,
|
||||||
pub invoker: &'a mut Invoker<SpecctraMesadata>,
|
pub invoker: &'a mut Invoker<SpecctraMesadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ActivityStatus {
|
|
||||||
Running,
|
|
||||||
Finished(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<InteractionStatus> for ActivityStatus {
|
|
||||||
fn from(status: InteractionStatus) -> Self {
|
|
||||||
match status {
|
|
||||||
InteractionStatus::Running => ActivityStatus::Running,
|
|
||||||
InteractionStatus::Finished(msg) => ActivityStatus::Finished(msg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<InvokerStatus> for ActivityStatus {
|
|
||||||
fn from(status: InvokerStatus) -> Self {
|
|
||||||
match status {
|
|
||||||
InvokerStatus::Running => ActivityStatus::Running,
|
|
||||||
InvokerStatus::Finished(msg) => ActivityStatus::Finished(msg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<()> for ActivityStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
ActivityStatus::Running => Err(()),
|
|
||||||
ActivityStatus::Finished(..) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum ActivityError {
|
pub enum ActivityError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -71,13 +33,22 @@ pub enum ActivityStepper {
|
||||||
Execution(ExecutionStepper),
|
Execution(ExecutionStepper),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Step<ActivityContext<'_>, ActivityStatus, ActivityError, ()> for ActivityStepper {
|
impl StepError for ActivityStepper {
|
||||||
fn step(&mut self, context: &mut ActivityContext) -> Result<ActivityStatus, ActivityError> {
|
type Error = ActivityError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PollStep<ActivityContext<'_>, String> for ActivityStepper {
|
||||||
|
fn poll_step(
|
||||||
|
&mut self,
|
||||||
|
context: &mut ActivityContext<'_>,
|
||||||
|
) -> Poll<Result<String, ActivityError>> {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(interaction) => {
|
ActivityStepper::Interaction(interaction) => interaction
|
||||||
Ok(interaction.step(&mut context.interaction)?.into())
|
.poll_step(&mut context.interaction)
|
||||||
}
|
.map(|x| x.map_err(Into::into)),
|
||||||
ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?.into()),
|
ActivityStepper::Execution(execution) => execution
|
||||||
|
.poll_step(context.invoker)
|
||||||
|
.map(|x| x.map_err(Into::into)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,9 +57,11 @@ impl Abort<ActivityContext<'_>> for ActivityStepper {
|
||||||
fn abort(&mut self, context: &mut ActivityContext) {
|
fn abort(&mut self, context: &mut ActivityContext) {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(interaction) => {
|
ActivityStepper::Interaction(interaction) => {
|
||||||
Ok(interaction.abort(&mut context.interaction))
|
interaction.abort(&mut context.interaction);
|
||||||
|
}
|
||||||
|
ActivityStepper::Execution(execution) => {
|
||||||
|
PollStep::finish(execution, context.invoker); // TODO.
|
||||||
}
|
}
|
||||||
ActivityStepper::Execution(execution) => execution.finish(context.invoker), // TODO.
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +108,7 @@ impl GetObstacles for ActivityStepper {
|
||||||
|
|
||||||
pub struct ActivityStepperWithStatus {
|
pub struct ActivityStepperWithStatus {
|
||||||
activity: ActivityStepper,
|
activity: ActivityStepper,
|
||||||
maybe_status: Option<ActivityStatus>,
|
maybe_status: Option<Poll<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActivityStepperWithStatus {
|
impl ActivityStepperWithStatus {
|
||||||
|
|
@ -146,22 +119,33 @@ impl ActivityStepperWithStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_status(&self) -> Option<ActivityStatus> {
|
pub fn maybe_status(&self) -> Option<Poll<String>> {
|
||||||
self.maybe_status.clone()
|
self.maybe_status.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Step<ActivityContext<'_>, ActivityStatus, ActivityError, ()> for ActivityStepperWithStatus {
|
impl StepError for ActivityStepperWithStatus {
|
||||||
fn step(&mut self, context: &mut ActivityContext) -> Result<ActivityStatus, ActivityError> {
|
type Error = ActivityError;
|
||||||
let status = self.activity.step(context)?;
|
}
|
||||||
self.maybe_status = Some(status.clone());
|
|
||||||
Ok(status.into())
|
impl PollStep<ActivityContext<'_>, String> for ActivityStepperWithStatus {
|
||||||
|
fn poll_step(
|
||||||
|
&mut self,
|
||||||
|
context: &mut ActivityContext<'_>,
|
||||||
|
) -> Poll<Result<String, ActivityError>> {
|
||||||
|
let res = self.activity.poll_step(context);
|
||||||
|
self.maybe_status = match &res {
|
||||||
|
Poll::Pending => Some(Poll::Pending),
|
||||||
|
Poll::Ready(Ok(msg)) => Some(Poll::Ready(msg.clone())),
|
||||||
|
Poll::Ready(Err(_)) => None,
|
||||||
|
};
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Abort<ActivityContext<'_>> for ActivityStepperWithStatus {
|
impl Abort<ActivityContext<'_>> for ActivityStepperWithStatus {
|
||||||
fn abort(&mut self, context: &mut ActivityContext) {
|
fn abort(&mut self, context: &mut ActivityContext<'_>) {
|
||||||
self.maybe_status = Some(ActivityStatus::Finished(String::from("aborted")));
|
self.maybe_status = Some(Poll::Ready("aborted".to_string()));
|
||||||
self.activity.abort(context);
|
self.activity.abort(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
mpsc::{channel, Receiver, Sender},
|
mpsc::{channel, Receiver, Sender},
|
||||||
Arc, Mutex,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
|
task::Poll,
|
||||||
};
|
};
|
||||||
use unic_langid::{langid, LanguageIdentifier};
|
use unic_langid::{langid, LanguageIdentifier};
|
||||||
|
|
||||||
|
|
@ -15,11 +16,11 @@ use topola::{
|
||||||
design::{LoadingError as SpecctraLoadingError, SpecctraDesign},
|
design::{LoadingError as SpecctraLoadingError, SpecctraDesign},
|
||||||
mesadata::SpecctraMesadata,
|
mesadata::SpecctraMesadata,
|
||||||
},
|
},
|
||||||
stepper::Step,
|
stepper::PollStep,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activity::{ActivityContext, ActivityStatus, ActivityStepperWithStatus},
|
activity::{ActivityContext, ActivityStepperWithStatus},
|
||||||
config::Config,
|
config::Config,
|
||||||
error_dialog::ErrorDialog,
|
error_dialog::ErrorDialog,
|
||||||
interaction::InteractionContext,
|
interaction::InteractionContext,
|
||||||
|
|
@ -171,15 +172,17 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut activity) = self.maybe_activity {
|
if let Some(ref mut activity) = self.maybe_activity {
|
||||||
return match activity.step(&mut ActivityContext {
|
return match activity.poll_step(&mut ActivityContext {
|
||||||
interaction: InteractionContext {},
|
interaction: InteractionContext {},
|
||||||
invoker,
|
invoker,
|
||||||
}) {
|
}) {
|
||||||
Ok(ActivityStatus::Running) => true,
|
Poll::Pending => true,
|
||||||
Ok(ActivityStatus::Finished(..)) => false,
|
Poll::Ready(res) => {
|
||||||
Err(err) => {
|
if let Err(err) = res {
|
||||||
self.error_dialog
|
self.error_dialog
|
||||||
.push_error("tr-module-invoker", format!("{}", err));
|
.push_error("tr-module-invoker", format!("{}", err));
|
||||||
|
}
|
||||||
|
self.maybe_activity = None;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
use core::task::Poll;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
|
autorouter::invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navmesh::Navmesh, trace::TraceStepper},
|
router::{navmesh::Navmesh, trace::TraceStepper},
|
||||||
stepper::{Abort, Step},
|
stepper::{Abort, PollStep, StepError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::activity::ActivityStepperWithStatus;
|
use crate::activity::ActivityStepperWithStatus;
|
||||||
|
|
@ -15,22 +16,6 @@ pub struct InteractionContext {
|
||||||
// (we will need an additional struct to hold a reference to a `Board<...>`)
|
// (we will need an additional struct to hold a reference to a `Board<...>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum InteractionStatus {
|
|
||||||
Running,
|
|
||||||
Finished(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<()> for InteractionStatus {
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
InteractionStatus::Running => Err(()),
|
|
||||||
InteractionStatus::Finished(..) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum InteractionError {
|
pub enum InteractionError {
|
||||||
#[error("nothing to interact with")]
|
#[error("nothing to interact with")]
|
||||||
|
|
@ -44,12 +29,16 @@ pub enum InteractionStepper {
|
||||||
// - interactively moving a footprint.
|
// - interactively moving a footprint.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Step<InteractionContext, InteractionStatus, InteractionError, ()> for InteractionStepper {
|
impl StepError for InteractionStepper {
|
||||||
fn step(
|
type Error = InteractionError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PollStep<InteractionContext, String> for InteractionStepper {
|
||||||
|
fn poll_step(
|
||||||
&mut self,
|
&mut self,
|
||||||
invoker: &mut InteractionContext,
|
invoker: &mut InteractionContext,
|
||||||
) -> Result<InteractionStatus, InteractionError> {
|
) -> Poll<Result<String, InteractionError>> {
|
||||||
Ok(InteractionStatus::Finished(String::from("")))
|
Poll::Ready(Ok(String::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{mpsc::Sender, Arc, Mutex},
|
sync::{mpsc::Sender, Arc, Mutex},
|
||||||
|
task::Poll,
|
||||||
};
|
};
|
||||||
|
|
||||||
use topola::{
|
use topola::{
|
||||||
|
|
@ -20,7 +21,7 @@ use topola::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{Action, Switch, Trigger},
|
action::{Action, Switch, Trigger},
|
||||||
activity::{ActivityContext, ActivityStatus, ActivityStepperWithStatus},
|
activity::{ActivityContext, ActivityStepperWithStatus},
|
||||||
app::{execute, handle_file},
|
app::{execute, handle_file},
|
||||||
interaction::InteractionContext,
|
interaction::InteractionContext,
|
||||||
overlay::Overlay,
|
overlay::Overlay,
|
||||||
|
|
@ -340,7 +341,7 @@ impl MenuBar {
|
||||||
}
|
}
|
||||||
} else if remove_bands.consume_key_triggered(ctx, ui) {
|
} else if remove_bands.consume_key_triggered(ctx, ui) {
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
if maybe_activity.as_mut().map_or(true, |activity| {
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
matches!(activity.maybe_status(), Some(Poll::Ready(..)))
|
||||||
}) {
|
}) {
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
if let (Some(invoker), Some(ref mut overlay)) = (
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
||||||
|
|
@ -357,7 +358,7 @@ impl MenuBar {
|
||||||
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) {
|
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) {
|
||||||
} else if autoroute.consume_key_triggered(ctx, ui) {
|
} else if autoroute.consume_key_triggered(ctx, ui) {
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
if maybe_activity.as_mut().map_or(true, |activity| {
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
matches!(activity.maybe_status(), Some(Poll::Ready(..)))
|
||||||
}) {
|
}) {
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
if let (Some(invoker), Some(ref mut overlay)) = (
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
||||||
|
|
@ -374,7 +375,7 @@ impl MenuBar {
|
||||||
}
|
}
|
||||||
} else if compare_detours.consume_key_triggered(ctx, ui) {
|
} else if compare_detours.consume_key_triggered(ctx, ui) {
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
if maybe_activity.as_mut().map_or(true, |activity| {
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
matches!(activity.maybe_status(), Some(Poll::Ready(..)))
|
||||||
}) {
|
}) {
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
if let (Some(invoker), Some(ref mut overlay)) = (
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
||||||
|
|
@ -391,7 +392,7 @@ impl MenuBar {
|
||||||
}
|
}
|
||||||
} else if measure_length.consume_key_triggered(ctx, ui) {
|
} else if measure_length.consume_key_triggered(ctx, ui) {
|
||||||
if maybe_activity.as_mut().map_or(true, |activity| {
|
if maybe_activity.as_mut().map_or(true, |activity| {
|
||||||
matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
|
matches!(activity.maybe_status(), Some(Poll::Ready(..)))
|
||||||
}) {
|
}) {
|
||||||
if let (Some(invoker), Some(ref mut overlay)) = (
|
if let (Some(invoker), Some(ref mut overlay)) = (
|
||||||
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::{
|
use crate::{activity::ActivityStepperWithStatus, translator::Translator, viewport::Viewport};
|
||||||
activity::{ActivityStatus, ActivityStepperWithStatus},
|
use core::task::Poll;
|
||||||
translator::Translator,
|
|
||||||
viewport::Viewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct StatusBar {}
|
pub struct StatusBar {}
|
||||||
|
|
||||||
|
|
@ -22,10 +19,10 @@ impl StatusBar {
|
||||||
let latest_pos = viewport.transform.inverse()
|
let latest_pos = viewport.transform.inverse()
|
||||||
* ctx.input(|i| i.pointer.latest_pos().unwrap_or_default());
|
* ctx.input(|i| i.pointer.latest_pos().unwrap_or_default());
|
||||||
|
|
||||||
let mut message = String::from("");
|
let mut message = String::new();
|
||||||
|
|
||||||
if let Some(activity) = maybe_activity {
|
if let Some(activity) = maybe_activity {
|
||||||
if let Some(ActivityStatus::Finished(msg)) = activity.maybe_status() {
|
if let Some(Poll::Ready(msg)) = activity.maybe_status() {
|
||||||
message = msg;
|
message = msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::stepper::Step;
|
use crate::stepper::{Step, StepError};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct MinScored<K, T>(pub K, pub T);
|
pub struct MinScored<K, T>(pub K, pub T);
|
||||||
|
|
@ -203,8 +203,17 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, K, R, S: AstarStrategy<G, K, R>>
|
impl<G, K> StepError for Astar<G, K>
|
||||||
Step<S, AstarStatus<G, K, R>, AstarError, (K, Vec<G::NodeId>, R)> for Astar<G, K>
|
where
|
||||||
|
G: GraphBase,
|
||||||
|
G::NodeId: Eq + Hash,
|
||||||
|
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||||
|
K: Measure + Copy,
|
||||||
|
{
|
||||||
|
type Error = AstarError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G, K, R, S: AstarStrategy<G, K, R>> Step<S, AstarStatus<G, K, R>> for Astar<G, K>
|
||||||
where
|
where
|
||||||
G: GraphBase,
|
G: GraphBase,
|
||||||
G::NodeId: Eq + Hash,
|
G::NodeId: Eq + Hash,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules},
|
||||||
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
|
|
||||||
},
|
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{
|
router::{
|
||||||
astar::{Astar, AstarError, AstarStatus},
|
astar::{Astar, AstarError, AstarStatus},
|
||||||
|
|
@ -10,7 +8,7 @@ use crate::{
|
||||||
tracer::Tracer,
|
tracer::Tracer,
|
||||||
Router, RouterAstarStrategy, RouterStatus,
|
Router, RouterAstarStrategy, RouterStatus,
|
||||||
},
|
},
|
||||||
stepper::Step,
|
stepper::{Step, StepError},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RouteStepper {
|
pub struct RouteStepper {
|
||||||
|
|
@ -73,9 +71,11 @@ impl RouteStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, AstarError, BandTermsegIndex>
|
impl StepError for RouteStepper {
|
||||||
for RouteStepper
|
type Error = AstarError;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus> for RouteStepper {
|
||||||
fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, AstarError> {
|
fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, AstarError> {
|
||||||
let tracer = Tracer::new(router.layout_mut());
|
let tracer = Tracer::new(router.layout_mut());
|
||||||
let target = self.astar.graph.destination();
|
let target = self.astar.graph.destination();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,16 @@
|
||||||
pub trait Step<C, S: TryInto<O>, E, O> {
|
use core::task::Poll;
|
||||||
fn step(&mut self, context: &mut C) -> Result<S, E>;
|
|
||||||
|
|
||||||
fn finish(&mut self, context: &mut C) -> Result<O, E> {
|
pub trait StepError {
|
||||||
|
type Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Step<C, S>: StepError {
|
||||||
|
fn step(&mut self, context: &mut C) -> Result<S, Self::Error>;
|
||||||
|
|
||||||
|
fn finish<O>(&mut self, context: &mut C) -> Result<O, Self::Error>
|
||||||
|
where
|
||||||
|
S: TryInto<O>,
|
||||||
|
{
|
||||||
loop {
|
loop {
|
||||||
if let Ok(outcome) = self.step(context)?.try_into() {
|
if let Ok(outcome) = self.step(context)?.try_into() {
|
||||||
return Ok(outcome);
|
return Ok(outcome);
|
||||||
|
|
@ -10,8 +19,40 @@ pub trait Step<C, S: TryInto<O>, E, O> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StepBack<C, S, E> {
|
// Note that PollStep's `S` is usually not the same as Step's `S`.
|
||||||
fn step_back(&mut self, context: &mut C) -> Result<S, E>;
|
pub trait PollStep<C, S>: StepError {
|
||||||
|
fn poll_step(&mut self, context: &mut C) -> Poll<Result<S, Self::Error>>;
|
||||||
|
|
||||||
|
fn finish(&mut self, context: &mut C) -> Result<S, Self::Error> {
|
||||||
|
loop {
|
||||||
|
if let Poll::Ready(outcome) = self.poll_step(context) {
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl<C, S, Stepper: Step<C, Poll<S>>> PollStep<C, S> for Stepper {
|
||||||
|
#[inline]
|
||||||
|
fn poll_step(&mut self, context: &mut C) -> Poll<Result<S, Self::Error>> {
|
||||||
|
self.step(context)?.map(Ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl<C, S, Stepper: PollStep<C, S>> Step<C, Poll<S>> for Stepper {
|
||||||
|
#[inline]
|
||||||
|
fn step(&mut self, context: &mut C) -> Result<Poll<S>, Self::Error> {
|
||||||
|
Ok(match self.poll_step(context) {
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
|
Poll::Ready(x) => Poll::Ready(x?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait StepBack<C, S>: StepError {
|
||||||
|
fn step_back(&mut self, context: &mut C) -> Result<S, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Abort<C> {
|
pub trait Abort<C> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue