Unify go-back-one-step processing for drawing tools (and router).

Also warps mouse on all go-back-one-step operations for better feedback.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14981

Fixes https://gitlab.com/kicad/code/kicad/-/issues/9985
This commit is contained in:
Jeff Young 2023-06-19 17:09:03 +01:00
parent 252769d53e
commit 30336b2fe3
14 changed files with 93 additions and 53 deletions

View File

@ -129,10 +129,15 @@ bool POLYGON_GEOM_MANAGER::NewPointClosesOutline( const VECTOR2I& aPt ) const
} }
void POLYGON_GEOM_MANAGER::DeleteLastCorner() std::optional<VECTOR2I> POLYGON_GEOM_MANAGER::DeleteLastCorner()
{ {
std::optional<VECTOR2I> last;
if( m_lockedPoints.PointCount() > 0 ) if( m_lockedPoints.PointCount() > 0 )
{
last = m_lockedPoints.GetPoint( m_lockedPoints.PointCount() - 1 );
m_lockedPoints.Remove( m_lockedPoints.PointCount() - 1 ); m_lockedPoints.Remove( m_lockedPoints.PointCount() - 1 );
}
// update the new last segment (was previously // update the new last segment (was previously
// locked in), reusing last constraints // locked in), reusing last constraints
@ -140,6 +145,7 @@ void POLYGON_GEOM_MANAGER::DeleteLastCorner()
updateTemporaryLines( m_leaderPts.CLastPoint() ); updateTemporaryLines( m_leaderPts.CLastPoint() );
m_client.OnGeometryChange( *this ); m_client.OnGeometryChange( *this );
return last;
} }

View File

@ -1428,8 +1428,6 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
m_frame->DeleteJunction( &commit, junction ); m_frame->DeleteJunction( &commit, junction );
} }
// m_frame->TestDanglingEnds();
m_frame->GetCanvas()->Refresh(); m_frame->GetCanvas()->Refresh();
commit.Push( _( "Delete" ) ); commit.Push( _( "Delete" ) );

View File

@ -892,7 +892,9 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
m_view->AddToPreview( wire->Clone() ); m_view->AddToPreview( wire->Clone() );
} }
} }
else if( evt->IsAction( &EE_ACTIONS::undoLastSegment ) || evt->IsAction( &ACTIONS::undo ) ) else if( evt->IsAction( &EE_ACTIONS::undoLastSegment )
|| evt->IsAction( &ACTIONS::doDelete )
|| evt->IsAction( &ACTIONS::undo ) )
{ {
if( ( currentMode == LINE_MODE::LINE_MODE_FREE && m_wires.size() > 1 ) if( ( currentMode == LINE_MODE::LINE_MODE_FREE && m_wires.size() > 1 )
|| ( LINE_MODE::LINE_MODE_90 && m_wires.size() > 2 ) ) || ( LINE_MODE::LINE_MODE_90 && m_wires.size() > 2 ) )
@ -904,7 +906,8 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
delete segment; delete segment;
segment = m_wires.back(); segment = m_wires.back();
segment->SetEndPoint( cursorPos ); cursorPos = segment->GetEndPoint();
getViewControls()->WarpMouseCursor( cursorPos, true );
// Find new bend point for current mode // Find new bend point for current mode
if( twoSegments && m_wires.size() >= 2 ) if( twoSegments && m_wires.size() >= 2 )
@ -1001,10 +1004,6 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
wxBell(); wxBell();
} }
} }
else if( evt->IsAction( &ACTIONS::doDelete ) && ( segment || m_busUnfold.in_progress ) )
{
cleanup();
}
else if( evt->IsAction( &ACTIONS::redo ) ) else if( evt->IsAction( &ACTIONS::redo ) )
{ {
wxBell(); wxBell();

View File

@ -151,7 +151,7 @@ public:
/** /**
* Remove the last-added point from the polygon * Remove the last-added point from the polygon
*/ */
void DeleteLastCorner(); std::optional<VECTOR2I> DeleteLastCorner();
/* ================================================================= /* =================================================================
* Interfaces for users of the geometry * Interfaces for users of the geometry

View File

@ -689,6 +689,11 @@ void PCB_EDIT_FRAME::setupUIConditions()
if( drawingTool && drawingTool->GetDrawingMode() != DRAWING_TOOL::MODE::NONE ) if( drawingTool && drawingTool->GetDrawingMode() != DRAWING_TOOL::MODE::NONE )
return true; return true;
ROUTER_TOOL* routerTool = m_toolManager->GetTool<ROUTER_TOOL>();
if( routerTool && routerTool->RoutingInProgress() )
return true;
return GetUndoCommandCount() > 0; return GetUndoCommandCount() > 0;
}; };

View File

@ -1701,14 +1701,16 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
} }
bool LINE_PLACER::UnfixRoute() std::optional<VECTOR2I> LINE_PLACER::UnfixRoute()
{ {
FIXED_TAIL::STAGE st; FIXED_TAIL::STAGE st;
std::optional<VECTOR2I> ret;
if ( !m_fixedTail.PopStage( st ) ) if ( !m_fixedTail.PopStage( st ) )
{ return ret;
return false;
} if( m_head.Line().PointCount() )
ret = m_head.Line().CPoint( 0 );
m_head.Line().Clear(); m_head.Line().Clear();
m_tail.Line().Clear(); m_tail.Line().Clear();
@ -1740,7 +1742,7 @@ bool LINE_PLACER::UnfixRoute()
m_lastNode = m_currentNode->Branch(); m_lastNode = m_currentNode->Branch();
return true; return ret;
} }

View File

@ -108,7 +108,7 @@ public:
*/ */
bool FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish ) override; bool FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish ) override;
bool UnfixRoute() override; std::optional<VECTOR2I> UnfixRoute() override;
bool CommitPlacement() override; bool CommitPlacement() override;

View File

@ -78,7 +78,7 @@ public:
*/ */
virtual bool FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish = false ) = 0; virtual bool FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish = false ) = 0;
virtual bool UnfixRoute() { return false; }; virtual std::optional<VECTOR2I> UnfixRoute() { return std::nullopt; };
virtual bool CommitPlacement() { return false; }; virtual bool CommitPlacement() { return false; };

View File

@ -893,13 +893,13 @@ bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
} }
void ROUTER::UndoLastSegment() std::optional<VECTOR2I> ROUTER::UndoLastSegment()
{ {
if( !RoutingInProgress() ) if( !RoutingInProgress() )
return; return std::nullopt;
m_logger->Log( LOGGER::EVT_UNFIX ); m_logger->Log( LOGGER::EVT_UNFIX );
m_placer->UnfixRoute(); return m_placer->UnfixRoute();
} }

View File

@ -149,7 +149,7 @@ public:
bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false ); bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false );
void BreakSegment( ITEM *aItem, const VECTOR2I& aP ); void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
void UndoLastSegment(); std::optional<VECTOR2I> UndoLastSegment();
void CommitRouting(); void CommitRouting();
void GetUpdatedItems( std::vector<PNS::ITEM*>& aRemoved, std::vector<PNS::ITEM*>& aAdded, void GetUpdatedItems( std::vector<PNS::ITEM*>& aRemoved, std::vector<PNS::ITEM*>& aAdded,

View File

@ -1362,9 +1362,16 @@ void ROUTER_TOOL::performRouting()
updateEndItem( *evt ); updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
} }
else if( evt->IsAction( &PCB_ACTIONS::routerUndoLastSegment ) ) else if( evt->IsAction( &PCB_ACTIONS::routerUndoLastSegment )
|| evt->IsAction( &ACTIONS::doDelete )
|| evt->IsAction( &ACTIONS::undo ) )
{ {
m_router->UndoLastSegment(); if( std::optional<VECTOR2I> last = m_router->UndoLastSegment() )
{
getViewControls()->WarpMouseCursor( last.value(), true );
evt->SetMousePosition( last.value() );
}
updateEndItem( *evt ); updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
} }

View File

@ -328,6 +328,7 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE );
std::optional<VECTOR2D> startingPoint; std::optional<VECTOR2D> startingPoint;
std::stack<PCB_SHAPE*> committedLines;
line->SetShape( SHAPE_T::SEGMENT ); line->SetShape( SHAPE_T::SEGMENT );
line->SetFlags( IS_NEW ); line->SetFlags( IS_NEW );
@ -338,13 +339,14 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent ); m_frame->PushTool( aEvent );
Activate(); Activate();
while( drawShape( aEvent, &line, startingPoint ) ) while( drawShape( aEvent, &line, startingPoint, &committedLines ) )
{ {
if( line ) if( line )
{ {
commit.Add( line ); commit.Add( line );
commit.Push( _( "Draw a line segment" ) ); commit.Push( _( "Draw a line segment" ) );
startingPoint = VECTOR2D( line->GetEnd() ); startingPoint = VECTOR2D( line->GetEnd() );
committedLines.push( line );
} }
else else
{ {
@ -388,7 +390,7 @@ int DRAWING_TOOL::DrawRectangle( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent ); m_frame->PushTool( aEvent );
Activate(); Activate();
while( drawShape( aEvent, &rect, startingPoint ) ) while( drawShape( aEvent, &rect, startingPoint, nullptr ) )
{ {
if( rect ) if( rect )
{ {
@ -449,7 +451,7 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent ); m_frame->PushTool( aEvent );
Activate(); Activate();
while( drawShape( aEvent, &circle, startingPoint ) ) while( drawShape( aEvent, &circle, startingPoint, nullptr ) )
{ {
if( circle ) if( circle )
{ {
@ -1773,7 +1775,8 @@ static void updateSegmentFromGeometryMgr( const KIGFX::PREVIEW::TWO_POINT_GEOMET
bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic, bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
std::optional<VECTOR2D> aStartingPoint ) std::optional<VECTOR2D> aStartingPoint,
std::stack<PCB_SHAPE*>* aCommittedGraphics )
{ {
SHAPE_T shape = ( *aGraphic )->GetShape(); SHAPE_T shape = ( *aGraphic )->GetShape();
@ -1863,7 +1866,7 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
COORDS_PADDING ); COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos ); m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) ) if( evt->IsCancelInteractive() )
{ {
cleanup(); cleanup();
@ -2071,6 +2074,34 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &preview ); m_view->Update( &preview );
m_view->Update( &twoPointAsst ); m_view->Update( &twoPointAsst );
} }
else if( evt->IsAction( &ACTIONS::undo )
|| evt->IsAction( &PCB_ACTIONS::doDelete )
|| evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) )
{
if( graphic && !aCommittedGraphics->empty() )
{
twoPointManager.SetOrigin( aCommittedGraphics->top()->GetStart() );
twoPointManager.SetEnd( aCommittedGraphics->top()->GetEnd() );
aCommittedGraphics->pop();
getViewControls()->WarpMouseCursor( twoPointManager.GetEnd(), true );
if( PICKED_ITEMS_LIST* undo = m_frame->PopCommandFromUndoList() )
{
m_frame->PutDataInPreviousState( undo );
m_frame->ClearListAndDeleteItems( undo );
delete undo;
}
updateSegmentFromGeometryMgr( twoPointManager, graphic );
m_view->Update( &preview );
m_view->Update( &twoPointAsst );
}
else if( graphic )
{
cleanup();
}
}
else if( graphic && evt->IsAction( &PCB_ACTIONS::incWidth ) ) else if( graphic && evt->IsAction( &PCB_ACTIONS::incWidth ) )
{ {
m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP ); m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
@ -2568,13 +2599,9 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
polyGeomMgr.SetLeaderMode( Is45Limited() ? POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45 polyGeomMgr.SetLeaderMode( Is45Limited() ? POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45
: POLYGON_GEOM_MANAGER::LEADER_MODE::DIRECT ); : POLYGON_GEOM_MANAGER::LEADER_MODE::DIRECT );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) ) if( evt->IsCancelInteractive() )
{ {
if( polyGeomMgr.PolygonPointCount() >= 2 && evt->IsAction( &ACTIONS::undo ) ) if( polyGeomMgr.IsPolygonInProgress() )
{
polyGeomMgr.DeleteLastCorner();
}
else if( polyGeomMgr.IsPolygonInProgress() )
{ {
cleanup(); cleanup();
} }
@ -2658,19 +2685,20 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
} }
} }
} }
else if( evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) ) else if( evt->IsAction( &PCB_ACTIONS::deleteLastPoint )
|| evt->IsAction( &ACTIONS::doDelete )
|| evt->IsAction( &ACTIONS::undo ) )
{ {
polyGeomMgr.DeleteLastCorner(); if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
if( !polyGeomMgr.IsPolygonInProgress() )
{ {
// report finished as an empty shape cursorPos = last.value();
polyGeomMgr.SetFinished(); getViewControls()->WarpMouseCursor( cursorPos, true );
m_controls->ForceCursorPosition( true, cursorPos );
// start again polyGeomMgr.SetCursorPosition( cursorPos );
started = false; }
m_controls->SetAutoPan( false ); else if( polyGeomMgr.IsPolygonInProgress() )
m_controls->CaptureCursor( false ); {
cleanup();
} }
} }
else if( polyGeomMgr.IsPolygonInProgress() else if( polyGeomMgr.IsPolygonInProgress()

View File

@ -230,7 +230,8 @@ private:
* the same point. * the same point.
*/ */
bool drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic, bool drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
std::optional<VECTOR2D> aStartingPoint ); std::optional<VECTOR2D> aStartingPoint,
std::stack<PCB_SHAPE*>* aCommittedGraphics );
/** /**
* Start drawing an arc. * Start drawing an arc.

View File

@ -1960,12 +1960,6 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
{ {
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
if( isRouterActive() )
{
m_toolMgr->RunAction( PCB_ACTIONS::routerUndoLastSegment, true );
return 0;
}
editFrame->PushTool( aEvent ); editFrame->PushTool( aEvent );
std::vector<BOARD_ITEM*> lockedItems; std::vector<BOARD_ITEM*> lockedItems;