mirror of https://codeberg.org/topola/topola.git
feat(autorouter): use recorded edit applying for undo/redo
This commit is contained in:
parent
d17a34c0f6
commit
c2daf9fbfe
|
|
@ -10,7 +10,7 @@ use thiserror::Error;
|
||||||
use crate::{
|
use crate::{
|
||||||
board::mesadata::AccessMesadata,
|
board::mesadata::AccessMesadata,
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape},
|
||||||
router::{navcord::NavcordStepper, navmesh::Navmesh},
|
router::{navcord::NavcordStepper, navmesh::Navmesh},
|
||||||
stepper::Step,
|
stepper::Step,
|
||||||
};
|
};
|
||||||
|
|
@ -172,20 +172,10 @@ impl<M: AccessMesadata> Invoker<M> {
|
||||||
#[debug_requires(self.ongoing_command.is_none())]
|
#[debug_requires(self.ongoing_command.is_none())]
|
||||||
/// Undo last command
|
/// Undo last command
|
||||||
pub fn undo(&mut self) -> Result<(), InvokerError> {
|
pub fn undo(&mut self) -> Result<(), InvokerError> {
|
||||||
let command = self.history.last_done()?.command();
|
let last_done = self.history.last_done()?;
|
||||||
|
|
||||||
match command {
|
if let Some(edit) = last_done.edit() {
|
||||||
Command::Autoroute(ref selection, ..) => {
|
self.autorouter.board.apply(edit.reverse());
|
||||||
self.autorouter.undo_autoroute(selection)?;
|
|
||||||
}
|
|
||||||
Command::PlaceVia(weight) => {
|
|
||||||
self.autorouter.undo_place_via(*weight);
|
|
||||||
}
|
|
||||||
Command::RemoveBands(ref selection) => {
|
|
||||||
self.autorouter.undo_remove_bands(selection);
|
|
||||||
}
|
|
||||||
Command::CompareDetours(..) => {}
|
|
||||||
Command::MeasureLength(..) => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.history.undo()?)
|
Ok(self.history.undo()?)
|
||||||
|
|
@ -194,19 +184,13 @@ impl<M: AccessMesadata> Invoker<M> {
|
||||||
//#[debug_requires(self.ongoing_command.is_none())]
|
//#[debug_requires(self.ongoing_command.is_none())]
|
||||||
/// Redo last command
|
/// Redo last command
|
||||||
pub fn redo(&mut self) -> Result<(), InvokerError> {
|
pub fn redo(&mut self) -> Result<(), InvokerError> {
|
||||||
let command = self.history.last_undone()?.command().clone();
|
let last_undone = self.history.last_undone()?;
|
||||||
let mut execute = self.execute_stepper(command)?;
|
|
||||||
|
|
||||||
loop {
|
if let Some(edit) = last_undone.edit() {
|
||||||
let status = match execute.step(self) {
|
self.autorouter.board.apply(edit.clone());
|
||||||
Ok(status) => status,
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let ControlFlow::Break(..) = status {
|
|
||||||
return Ok(self.history.redo()?);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(self.history.redo()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_requires(self.ongoing_command.is_none())]
|
#[debug_requires(self.ongoing_command.is_none())]
|
||||||
|
|
|
||||||
|
|
@ -62,4 +62,34 @@ impl<
|
||||||
primitive_weight_marker: PhantomData,
|
primitive_weight_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reverse(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
dots: self
|
||||||
|
.dots
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k, (v.1, v.0)))
|
||||||
|
.collect(),
|
||||||
|
segs: self
|
||||||
|
.segs
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k, (v.1, v.0)))
|
||||||
|
.collect(),
|
||||||
|
bends: self
|
||||||
|
.bends
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k, (v.1, v.0)))
|
||||||
|
.collect(),
|
||||||
|
compounds: self
|
||||||
|
.compounds
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k, (v.1, v.0)))
|
||||||
|
.collect(),
|
||||||
|
primitive_weight_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -396,44 +396,52 @@ impl<
|
||||||
for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>
|
for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>
|
||||||
{
|
{
|
||||||
fn apply(&mut self, edit: GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>) {
|
fn apply(&mut self, edit: GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>) {
|
||||||
for (compound, ..) in &edit.compounds {
|
for (compound, (maybe_old_data, ..)) in &edit.compounds {
|
||||||
self.geometry_with_rtree.remove_compound(*compound);
|
if maybe_old_data.is_some() {
|
||||||
|
self.geometry_with_rtree.remove_compound(*compound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bend, ..) in &edit.bends {
|
for (bend, (maybe_old_data, ..)) in &edit.bends {
|
||||||
self.geometry_with_rtree.remove_bend(*bend);
|
if maybe_old_data.is_some() {
|
||||||
|
self.geometry_with_rtree.remove_bend(*bend);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (seg, ..) in &edit.segs {
|
for (seg, (maybe_old_data, ..)) in &edit.segs {
|
||||||
self.geometry_with_rtree.remove_seg(*seg);
|
if maybe_old_data.is_some() {
|
||||||
|
self.geometry_with_rtree.remove_seg(*seg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dot, ..) in &edit.dots {
|
for (dot, (maybe_old_data, ..)) in &edit.dots {
|
||||||
self.geometry_with_rtree.remove_dot(*dot);
|
if maybe_old_data.is_some() {
|
||||||
|
self.geometry_with_rtree.remove_dot(*dot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dot, (.., maybe_weight)) in &edit.dots {
|
for (dot, (.., maybe_new_data)) in &edit.dots {
|
||||||
if let Some(weight) = maybe_weight {
|
if let Some(weight) = maybe_new_data {
|
||||||
self.geometry_with_rtree.add_dot_at_index(*dot, *weight);
|
self.geometry_with_rtree.add_dot_at_index(*dot, *weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (seg, (.., maybe_data)) in &edit.segs {
|
for (seg, (.., maybe_new_data)) in &edit.segs {
|
||||||
if let Some(((from, to), weight)) = maybe_data {
|
if let Some(((from, to), weight)) = maybe_new_data {
|
||||||
self.geometry_with_rtree
|
self.geometry_with_rtree
|
||||||
.add_seg_at_index(*seg, *from, *to, *weight);
|
.add_seg_at_index(*seg, *from, *to, *weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bend, (.., maybe_data)) in &edit.bends {
|
for (bend, (.., maybe_new_data)) in &edit.bends {
|
||||||
if let Some(((from, to, core), weight)) = maybe_data {
|
if let Some(((from, to, core), weight)) = maybe_new_data {
|
||||||
self.geometry_with_rtree
|
self.geometry_with_rtree
|
||||||
.add_bend_at_index(*bend, *from, *to, *core, *weight);
|
.add_bend_at_index(*bend, *from, *to, *core, *weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (compound, (.., maybe_data)) in &edit.compounds {
|
for (compound, (.., maybe_new_data)) in &edit.compounds {
|
||||||
if let Some((members, weight)) = maybe_data {
|
if let Some((members, weight)) = maybe_new_data {
|
||||||
self.geometry_with_rtree
|
self.geometry_with_rtree
|
||||||
.add_compound_at_index(*compound, *weight);
|
.add_compound_at_index(*compound, *weight);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue