egui: further make an `Activity` enum with error and status types

This commit is contained in:
Mikolaj Wielgus 2024-09-30 03:40:53 +02:00
parent c8a40860af
commit 169e843736
5 changed files with 123 additions and 40 deletions

View File

@ -1,22 +1,12 @@
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, step::Step};
board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape,
layout::via::ViaWeight,
router::{navmesh::Navmesh, trace::Trace},
step::Step,
};
use super::{ use super::{
autoroute::{Autoroute, AutorouteStatus}, autoroute::{Autoroute, AutorouteStatus},
compare_detours::{CompareDetours, CompareDetoursStatus}, compare_detours::{CompareDetours, CompareDetoursStatus},
invoker::{ invoker::{Invoker, InvokerError, InvokerStatus},
GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker, InvokerError,
InvokerStatus,
},
measure_length::MeasureLength, measure_length::MeasureLength,
place_via::PlaceVia, place_via::PlaceVia,
remove_bands::RemoveBands, remove_bands::RemoveBands,

View File

@ -1,3 +1,4 @@
use thiserror::Error;
use topola::{ use topola::{
autorouter::{ autorouter::{
execute::Execute, execute::Execute,
@ -10,56 +11,140 @@ use topola::{
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::Trace}, router::{navmesh::Navmesh, trace::Trace},
specctra::mesadata::SpecctraMesadata,
step::Step, step::Step,
}; };
#[derive(Error, Debug, Clone)]
pub enum ActivityError {
#[error(transparent)]
Invoker(#[from] InvokerError),
}
#[derive(Debug, Clone)]
pub enum ActivityStatus {
Running,
Finished(String),
}
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(()),
}
}
}
pub enum Activity {
// There will be another variant for interactive activities here soon. (TODO)
Execute(Execute),
}
impl Step<Invoker<SpecctraMesadata>, ActivityStatus, ActivityError, ()> for Activity {
fn step(
&mut self,
invoker: &mut Invoker<SpecctraMesadata>,
) -> Result<ActivityStatus, ActivityError> {
match self {
Activity::Execute(execute) => Ok(execute.step(invoker)?.into()),
}
}
}
impl GetMaybeNavmesh for Activity {
/// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates.
fn maybe_navmesh(&self) -> Option<&Navmesh> {
match self {
Activity::Execute(execute) => execute.maybe_navmesh(),
}
}
}
impl GetMaybeTrace for Activity {
/// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates.
fn maybe_trace(&self) -> Option<&Trace> {
match self {
Activity::Execute(execute) => execute.maybe_trace(),
}
}
}
impl GetGhosts for Activity {
/// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates.
fn ghosts(&self) -> &[PrimitiveShape] {
match self {
Activity::Execute(execute) => execute.ghosts(),
}
}
}
impl GetObstacles for Activity {
/// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates.
fn obstacles(&self) -> &[PrimitiveIndex] {
match self {
Activity::Execute(execute) => execute.obstacles(),
}
}
}
pub struct ActivityWithStatus { pub struct ActivityWithStatus {
execute: Execute, activity: Activity,
maybe_status: Option<InvokerStatus>, maybe_status: Option<ActivityStatus>,
} }
impl ActivityWithStatus { impl ActivityWithStatus {
pub fn new_execute(execute: Execute) -> ActivityWithStatus { pub fn new_execute(execute: Execute) -> ActivityWithStatus {
Self { Self {
execute, activity: Activity::Execute(execute),
maybe_status: None, maybe_status: None,
} }
} }
pub fn step<M: AccessMesadata>( pub fn step(
&mut self, &mut self,
invoker: &mut Invoker<M>, invoker: &mut Invoker<SpecctraMesadata>,
) -> Result<InvokerStatus, InvokerError> { ) -> Result<ActivityStatus, ActivityError> {
let status = self.execute.step(invoker)?; let status = self.activity.step(invoker)?;
self.maybe_status = Some(status.clone()); self.maybe_status = Some(status.clone());
Ok(status) Ok(status.into())
} }
pub fn maybe_status(&self) -> Option<InvokerStatus> { pub fn maybe_status(&self) -> Option<ActivityStatus> {
self.maybe_status.clone() self.maybe_status.clone()
} }
} }
impl GetMaybeNavmesh for ActivityWithStatus { impl GetMaybeNavmesh for ActivityWithStatus {
fn maybe_navmesh(&self) -> Option<&Navmesh> { fn maybe_navmesh(&self) -> Option<&Navmesh> {
self.execute.maybe_navmesh() self.activity.maybe_navmesh()
} }
} }
impl GetMaybeTrace for ActivityWithStatus { impl GetMaybeTrace for ActivityWithStatus {
fn maybe_trace(&self) -> Option<&Trace> { fn maybe_trace(&self) -> Option<&Trace> {
self.execute.maybe_trace() self.activity.maybe_trace()
} }
} }
impl GetGhosts for ActivityWithStatus { impl GetGhosts for ActivityWithStatus {
fn ghosts(&self) -> &[PrimitiveShape] { fn ghosts(&self) -> &[PrimitiveShape] {
self.execute.ghosts() self.activity.ghosts()
} }
} }
impl GetObstacles for ActivityWithStatus { impl GetObstacles for ActivityWithStatus {
fn obstacles(&self) -> &[PrimitiveIndex] { fn obstacles(&self) -> &[PrimitiveIndex] {
self.execute.obstacles() self.activity.obstacles()
} }
} }

View File

@ -13,10 +13,7 @@ use std::{
use unic_langid::{langid, LanguageIdentifier}; use unic_langid::{langid, LanguageIdentifier};
use topola::{ use topola::{
autorouter::{ autorouter::{invoker::Invoker, Autorouter},
invoker::{Invoker, InvokerStatus},
Autorouter,
},
drawing::{ drawing::{
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{MakePrimitive, PrimitiveIndex}, graph::{MakePrimitive, PrimitiveIndex},
@ -42,8 +39,15 @@ use topola::{
}; };
use crate::{ use crate::{
activity::ActivityWithStatus, bottom::Bottom, file_receiver::FileReceiver, layers::Layers, activity::{ActivityStatus, ActivityWithStatus},
overlay::Overlay, painter::Painter, top::Top, translator::Translator, viewport::Viewport, bottom::Bottom,
file_receiver::FileReceiver,
layers::Layers,
overlay::Overlay,
painter::Painter,
top::Top,
translator::Translator,
viewport::Viewport,
}; };
/// Deserialize/Serialize is needed to persist app state between restarts. /// Deserialize/Serialize is needed to persist app state between restarts.
@ -159,8 +163,8 @@ impl App {
if let Some(ref mut activity) = self.maybe_activity { if let Some(ref mut activity) = self.maybe_activity {
match activity.step(invoker) { match activity.step(invoker) {
Ok(InvokerStatus::Running) => return true, Ok(ActivityStatus::Running) => return true,
Ok(InvokerStatus::Finished(..)) => return false, Ok(ActivityStatus::Finished(..)) => return false,
Err(err) => return false, Err(err) => return false,
} }
} }

View File

@ -1,6 +1,10 @@
use topola::autorouter::invoker::InvokerStatus; use topola::autorouter::invoker::InvokerStatus;
use crate::{activity::ActivityWithStatus, translator::Translator, viewport::Viewport}; use crate::{
activity::{ActivityStatus, ActivityWithStatus},
translator::Translator,
viewport::Viewport,
};
pub struct Bottom {} pub struct Bottom {}
@ -23,7 +27,7 @@ impl Bottom {
let mut message = String::from(""); let mut message = String::from("");
if let Some(activity) = maybe_activity { if let Some(activity) = maybe_activity {
if let Some(InvokerStatus::Finished(msg)) = activity.maybe_status() { if let Some(ActivityStatus::Finished(msg)) = activity.maybe_status() {
message = msg; message = msg;
} }
} }

View File

@ -16,7 +16,7 @@ use topola::{
use crate::{ use crate::{
action::{Action, Switch, Trigger}, action::{Action, Switch, Trigger},
activity::ActivityWithStatus, activity::{ActivityStatus, ActivityWithStatus},
app::execute, app::execute,
file_sender::FileSender, file_sender::FileSender,
overlay::Overlay, overlay::Overlay,
@ -292,7 +292,7 @@ impl Top {
ctx.send_viewport_cmd(egui::ViewportCommand::Close); ctx.send_viewport_cmd(egui::ViewportCommand::Close);
} 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(InvokerStatus::Finished(..))) matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
}) { }) {
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(),
@ -311,7 +311,7 @@ impl Top {
} 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 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(InvokerStatus::Finished(..))) matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
}) { }) {
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(),
@ -328,7 +328,7 @@ impl Top {
} }
} 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(InvokerStatus::Finished(..))) matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
}) { }) {
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(),
@ -353,7 +353,7 @@ impl Top {
} }
} 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(InvokerStatus::Finished(..))) matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..)))
}) { }) {
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(),