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 )
{
last = m_lockedPoints.GetPoint( m_lockedPoints.PointCount() - 1 );
m_lockedPoints.Remove( m_lockedPoints.PointCount() - 1 );
}
// update the new last segment (was previously
// locked in), reusing last constraints
@ -140,6 +145,7 @@ void POLYGON_GEOM_MANAGER::DeleteLastCorner()
updateTemporaryLines( m_leaderPts.CLastPoint() );
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->TestDanglingEnds();
m_frame->GetCanvas()->Refresh();
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() );
}
}
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 )
|| ( 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;
segment = m_wires.back();
segment->SetEndPoint( cursorPos );
cursorPos = segment->GetEndPoint();
getViewControls()->WarpMouseCursor( cursorPos, true );
// Find new bend point for current mode
if( twoSegments && m_wires.size() >= 2 )
@ -1001,10 +1004,6 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
wxBell();
}
}
else if( evt->IsAction( &ACTIONS::doDelete ) && ( segment || m_busUnfold.in_progress ) )
{
cleanup();
}
else if( evt->IsAction( &ACTIONS::redo ) )
{
wxBell();

View File

@ -151,7 +151,7 @@ public:
/**
* Remove the last-added point from the polygon
*/
void DeleteLastCorner();
std::optional<VECTOR2I> DeleteLastCorner();
/* =================================================================
* 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 )
return true;
ROUTER_TOOL* routerTool = m_toolManager->GetTool<ROUTER_TOOL>();
if( routerTool && routerTool->RoutingInProgress() )
return true;
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 ) )
{
return false;
}
return ret;
if( m_head.Line().PointCount() )
ret = m_head.Line().CPoint( 0 );
m_head.Line().Clear();
m_tail.Line().Clear();
@ -1740,7 +1742,7 @@ bool LINE_PLACER::UnfixRoute()
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 UnfixRoute() override;
std::optional<VECTOR2I> UnfixRoute() 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 UnfixRoute() { return false; };
virtual std::optional<VECTOR2I> UnfixRoute() { return std::nullopt; };
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() )
return;
return std::nullopt;
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 );
void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
void UndoLastSegment();
std::optional<VECTOR2I> UndoLastSegment();
void CommitRouting();
void GetUpdatedItems( std::vector<PNS::ITEM*>& aRemoved, std::vector<PNS::ITEM*>& aAdded,

View File

@ -1362,9 +1362,16 @@ void ROUTER_TOOL::performRouting()
updateEndItem( *evt );
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 );
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 );
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE );
std::optional<VECTOR2D> startingPoint;
std::stack<PCB_SHAPE*> committedLines;
line->SetShape( SHAPE_T::SEGMENT );
line->SetFlags( IS_NEW );
@ -338,13 +339,14 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent );
Activate();
while( drawShape( aEvent, &line, startingPoint ) )
while( drawShape( aEvent, &line, startingPoint, &committedLines ) )
{
if( line )
{
commit.Add( line );
commit.Push( _( "Draw a line segment" ) );
startingPoint = VECTOR2D( line->GetEnd() );
committedLines.push( line );
}
else
{
@ -388,7 +390,7 @@ int DRAWING_TOOL::DrawRectangle( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent );
Activate();
while( drawShape( aEvent, &rect, startingPoint ) )
while( drawShape( aEvent, &rect, startingPoint, nullptr ) )
{
if( rect )
{
@ -449,7 +451,7 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
m_frame->PushTool( aEvent );
Activate();
while( drawShape( aEvent, &circle, startingPoint ) )
while( drawShape( aEvent, &circle, startingPoint, nullptr ) )
{
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,
std::optional<VECTOR2D> aStartingPoint )
std::optional<VECTOR2D> aStartingPoint,
std::stack<PCB_SHAPE*>* aCommittedGraphics )
{
SHAPE_T shape = ( *aGraphic )->GetShape();
@ -1863,7 +1866,7 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
COORDS_PADDING );
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() )
{
cleanup();
@ -2071,6 +2074,34 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &preview );
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 ) )
{
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
: POLYGON_GEOM_MANAGER::LEADER_MODE::DIRECT );
if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
if( evt->IsCancelInteractive() )
{
if( polyGeomMgr.PolygonPointCount() >= 2 && evt->IsAction( &ACTIONS::undo ) )
{
polyGeomMgr.DeleteLastCorner();
}
else if( polyGeomMgr.IsPolygonInProgress() )
if( polyGeomMgr.IsPolygonInProgress() )
{
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( !polyGeomMgr.IsPolygonInProgress() )
if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
{
// report finished as an empty shape
polyGeomMgr.SetFinished();
// start again
started = false;
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
cursorPos = last.value();
getViewControls()->WarpMouseCursor( cursorPos, true );
m_controls->ForceCursorPosition( true, cursorPos );
polyGeomMgr.SetCursorPosition( cursorPos );
}
else if( polyGeomMgr.IsPolygonInProgress() )
{
cleanup();
}
}
else if( polyGeomMgr.IsPolygonInProgress()

View File

@ -230,7 +230,8 @@ private:
* the same point.
*/
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.

View File

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