Integrate move individually into move algo so other commands don't choke.

Also adds commands to cancel and finish move individually.

Fixes https://gitlab.com/kicad/code/kicad/issues/12750

Fixes https://gitlab.com/kicad/code/kicad/issues/12749
This commit is contained in:
Jeff Young 2022-11-13 13:14:18 +00:00
parent 365674dfdf
commit 7089e99f4b
5 changed files with 106 additions and 74 deletions

View File

@ -437,9 +437,14 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
} }
if( changed && copy ) if( changed && copy )
{
m_commit.Modified( aPcbFootprint, copy ); m_commit.Modified( aPcbFootprint, copy );
}
else else
{
copy->SetParentGroup( nullptr );
delete copy; delete copy;
}
return true; return true;
} }
@ -621,9 +626,14 @@ bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( FOOTPRINT* aFootprint
} }
if( changed && copy ) if( changed && copy )
{
m_commit.Modified( aFootprint, copy ); m_commit.Modified( aFootprint, copy );
}
else else
{
copy->SetParentGroup( nullptr );
delete copy; delete copy;
}
return true; return true;
} }

View File

@ -2260,7 +2260,7 @@ void EDIT_TOOL::setTransitions()
{ {
Go( &EDIT_TOOL::GetAndPlace, PCB_ACTIONS::getAndPlace.MakeEvent() ); Go( &EDIT_TOOL::GetAndPlace, PCB_ACTIONS::getAndPlace.MakeEvent() );
Go( &EDIT_TOOL::Move, PCB_ACTIONS::move.MakeEvent() ); Go( &EDIT_TOOL::Move, PCB_ACTIONS::move.MakeEvent() );
Go( &EDIT_TOOL::MoveIndividually, PCB_ACTIONS::moveIndividually.MakeEvent() ); Go( &EDIT_TOOL::Move, PCB_ACTIONS::moveIndividually.MakeEvent() );
Go( &EDIT_TOOL::Drag, PCB_ACTIONS::drag45Degree.MakeEvent() ); Go( &EDIT_TOOL::Drag, PCB_ACTIONS::drag45Degree.MakeEvent() );
Go( &EDIT_TOOL::Drag, PCB_ACTIONS::dragFreeAngle.MakeEvent() ); Go( &EDIT_TOOL::Drag, PCB_ACTIONS::dragFreeAngle.MakeEvent() );
Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCw.MakeEvent() ); Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCw.MakeEvent() );
@ -2270,7 +2270,7 @@ void EDIT_TOOL::setTransitions()
Go( &EDIT_TOOL::Remove, PCB_ACTIONS::deleteFull.MakeEvent() ); Go( &EDIT_TOOL::Remove, PCB_ACTIONS::deleteFull.MakeEvent() );
Go( &EDIT_TOOL::Properties, PCB_ACTIONS::properties.MakeEvent() ); Go( &EDIT_TOOL::Properties, PCB_ACTIONS::properties.MakeEvent() );
Go( &EDIT_TOOL::MoveExact, PCB_ACTIONS::moveExact.MakeEvent() ); Go( &EDIT_TOOL::MoveExact, PCB_ACTIONS::moveExact.MakeEvent() );
Go( &EDIT_TOOL::MoveWithReference, PCB_ACTIONS::moveWithReference.MakeEvent() ); Go( &EDIT_TOOL::Move, PCB_ACTIONS::moveWithReference.MakeEvent() );
Go( &EDIT_TOOL::Duplicate, ACTIONS::duplicate.MakeEvent() ); Go( &EDIT_TOOL::Duplicate, ACTIONS::duplicate.MakeEvent() );
Go( &EDIT_TOOL::Duplicate, PCB_ACTIONS::duplicateIncrement.MakeEvent() ); Go( &EDIT_TOOL::Duplicate, PCB_ACTIONS::duplicateIncrement.MakeEvent() );
Go( &EDIT_TOOL::CreateArray, PCB_ACTIONS::createArray.MakeEvent() ); Go( &EDIT_TOOL::CreateArray, PCB_ACTIONS::createArray.MakeEvent() );

View File

@ -80,11 +80,6 @@ public:
*/ */
int Move( const TOOL_EVENT& aEvent ); int Move( const TOOL_EVENT& aEvent );
/**
* Move a selection of items one-at-a-time.
*/
int MoveIndividually( const TOOL_EVENT& aEvent );
/** /**
* Invoke the PNS router to drag tracks or do an offline resizing of an arc track * Invoke the PNS router to drag tracks or do an offline resizing of an arc track
* if a single arc track is selected. * if a single arc track is selected.
@ -150,11 +145,6 @@ public:
*/ */
int MoveExact( const TOOL_EVENT& aEvent ); int MoveExact( const TOOL_EVENT& aEvent );
/**
* Move an item but with a reference point selected first
*/
int MoveWithReference( const TOOL_EVENT& aEvent );
/** /**
* Create an array of the selected items, invoking the array editor dialog to set the options. * Create an array of the selected items, invoking the array editor dialog to set the options.
*/ */
@ -197,7 +187,7 @@ private:
bool invokeInlineRouter( int aDragMode ); bool invokeInlineRouter( int aDragMode );
bool isRouterActive() const; bool isRouterActive() const;
int doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference = false ); int doMoveSelection( const TOOL_EVENT& aEvent );
VECTOR2I getSafeMovement( const VECTOR2I& aMovement, const BOX2I& aSourceBBox, VECTOR2I getSafeMovement( const VECTOR2I& aMovement, const BOX2I& aSourceBBox,
const VECTOR2D& aBBoxOffset ); const VECTOR2D& aBBoxOffset );

View File

@ -241,46 +241,6 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
} }
int EDIT_TOOL::MoveIndividually( const TOOL_EVENT& aEvent )
{
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
if( isRouterActive() )
{
wxBell();
return 0;
}
EDA_ITEMS sortedItems = selTool->GetSelection().GetItemsSortedBySelectionOrder();
if( sortedItems.size() == 0 )
return 0;
for( EDA_ITEM* item : sortedItems )
{
selTool->ClearSelection();
selTool->AddItemToSel( item );
doMoveSelection( aEvent );
}
selTool->AddItemsToSel( &sortedItems );
return 0;
}
int EDIT_TOOL::MoveWithReference( const TOOL_EVENT& aEvent )
{
if( isRouterActive() )
{
wxBell();
return 0;
}
return doMoveSelection( aEvent, true );
}
VECTOR2I EDIT_TOOL::getSafeMovement( const VECTOR2I& aMovement, const BOX2I& aSourceBBox, VECTOR2I EDIT_TOOL::getSafeMovement( const VECTOR2I& aMovement, const BOX2I& aSourceBBox,
const VECTOR2D& aBBoxOffset ) const VECTOR2D& aBBoxOffset )
{ {
@ -315,13 +275,19 @@ VECTOR2I EDIT_TOOL::getSafeMovement( const VECTOR2I& aMovement, const BOX2I& aSo
} }
int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent )
{ {
bool moveWithReference = aEvent.IsAction( &PCB_ACTIONS::moveWithReference );
bool moveIndividually = aEvent.IsAction( &PCB_ACTIONS::moveIndividually );
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
PCBNEW_SETTINGS* cfg = editFrame->GetPcbNewSettings(); PCBNEW_SETTINGS* cfg = editFrame->GetPcbNewSettings();
BOARD* board = editFrame->GetBoard(); BOARD* board = editFrame->GetBoard();
KIGFX::VIEW_CONTROLS* controls = getViewControls(); KIGFX::VIEW_CONTROLS* controls = getViewControls();
VECTOR2I originalCursorPos = controls->GetCursorPosition(); VECTOR2I originalCursorPos = controls->GetCursorPosition();
STATUS_TEXT_POPUP statusPopup( frame() );
wxString status;
size_t itemIdx = 0;
// Be sure that there is at least one item that we can modify. If nothing was selected before, // Be sure that there is at least one item that we can modify. If nothing was selected before,
// try looking for the stuff under mouse cursor (i.e. KiCad old-style hover selection) // try looking for the stuff under mouse cursor (i.e. KiCad old-style hover selection)
@ -368,16 +334,6 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
controls->SetAutoPan( true ); controls->SetAutoPan( true );
controls->ForceCursorPosition( false ); controls->ForceCursorPosition( false );
if( aPickReference && !pickReferencePoint( _( "Select reference point for move..." ), "", "",
pickedReferencePoint ) )
{
if( is_hover )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
editFrame->PopTool( aEvent );
return 0;
}
auto displayConstraintsMessage = auto displayConstraintsMessage =
[editFrame]( bool constrained ) [editFrame]( bool constrained )
{ {
@ -385,6 +341,32 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
: wxT( "" ) ); : wxT( "" ) );
}; };
auto updateStatusPopup =
[&]( EDA_ITEM* item, size_t ii, size_t count )
{
wxString status = _( "Click to place %s (item %ld of %ld)\n"
"Press <esc> to cancel all; double-click to finish" );
wxString msg;
if( item->Type() == PCB_FOOTPRINT_T )
{
FOOTPRINT* fp = static_cast<FOOTPRINT*>( item );
msg = fp->GetReference();
}
else if( item->Type() == PCB_PAD_T )
{
PAD* pad = static_cast<PAD*>( item );
FOOTPRINT* fp = static_cast<FOOTPRINT*>( pad->GetParentFootprint() );
msg = wxString::Format( _( "%s pad %s" ), fp->GetReference(), pad->GetNumber() );
}
else
{
msg = item->GetTypeDesc().Lower();
}
statusPopup.SetText( wxString::Format( status, msg, ii, count ) );
};
std::vector<BOARD_ITEM*> sel_items; // All the items operated on by the move below std::vector<BOARD_ITEM*> sel_items; // All the items operated on by the move below
std::vector<BOARD_ITEM*> orig_items; // All the original items in the selection std::vector<BOARD_ITEM*> orig_items; // All the original items in the selection
@ -412,6 +394,35 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
} }
} }
if( moveWithReference && !pickReferencePoint( _( "Select reference point for move..." ), "", "",
pickedReferencePoint ) )
{
if( is_hover )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
editFrame->PopTool( aEvent );
return 0;
}
if( moveIndividually )
{
orig_items.clear();
for( EDA_ITEM* item : selection.GetItemsSortedBySelectionOrder() )
orig_items.push_back( static_cast<BOARD_ITEM*>( item ) );
updateStatusPopup( orig_items[ itemIdx ], itemIdx + 1, orig_items.size() );
statusPopup.Popup();
statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
canvas()->SetStatusPopup( statusPopup.GetPanel() );
m_selectionTool->ClearSelection();
m_selectionTool->AddItemToSel( orig_items[ itemIdx ] );
sel_items.clear();
sel_items.push_back( orig_items[ itemIdx ] );
}
bool restore_state = false; bool restore_state = false;
VECTOR2I originalPos; VECTOR2I originalPos;
VECTOR2I totalMovement; VECTOR2I totalMovement;
@ -624,22 +635,18 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
} }
else else
{ {
std::vector<BOARD_ITEM*> items; for( BOARD_ITEM* item : sel_items )
for( EDA_ITEM* item : selection )
{ {
items.push_back( static_cast<BOARD_ITEM*>( item ) );
if( showCourtyardConflicts && item->Type() == PCB_FOOTPRINT_T ) if( showCourtyardConflicts && item->Type() == PCB_FOOTPRINT_T )
drc_on_move->m_FpInMove.push_back( static_cast<FOOTPRINT*>( item ) ); drc_on_move->m_FpInMove.push_back( static_cast<FOOTPRINT*>( item ) );
} }
m_cursor = grid.BestDragOrigin( originalCursorPos, items, m_cursor = grid.BestDragOrigin( originalCursorPos, sel_items,
&m_selectionTool->GetFilter() ); &m_selectionTool->GetFilter() );
// Set the current cursor position to the first dragged item origin, so the // Set the current cursor position to the first dragged item origin, so the
// movement vector could be computed later // movement vector could be computed later
if( aPickReference ) if( moveWithReference )
{ {
selection.SetReferencePoint( pickedReferencePoint ); selection.SetReferencePoint( pickedReferencePoint );
controls->ForceCursorPosition( true, pickedReferencePoint ); controls->ForceCursorPosition( true, pickedReferencePoint );
@ -668,6 +675,8 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
} }
statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
m_toolMgr->RunAction( PCB_ACTIONS::updateLocalRatsnest, false, new VECTOR2I( movement ) ); m_toolMgr->RunAction( PCB_ACTIONS::updateLocalRatsnest, false, new VECTOR2I( movement ) );
} }
else if( evt->IsCancelInteractive() || evt->IsActivate() ) else if( evt->IsCancelInteractive() || evt->IsActivate() )
@ -723,7 +732,31 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
eatFirstMouseUp = false; eatFirstMouseUp = false;
continue; continue;
} }
else if( moveIndividually && m_dragging )
{
if( ++itemIdx < orig_items.size() )
{
m_selectionTool->ClearSelection();
m_selectionTool->AddItemToSel( orig_items[ itemIdx ] );
selection.ClearReferencePoint();
sel_items.clear();
sel_items.push_back( orig_items[ itemIdx ] );
updateStatusPopup( orig_items[ itemIdx ], itemIdx + 1, orig_items.size() );
// Pick up new item
m_dragging = false;
controls->ForceCursorPosition( false );
m_toolMgr->RunAction( PCB_ACTIONS::move );
continue;
}
}
break; // finish
}
else if( evt->IsDblClick( BUT_LEFT ) )
{
break; // finish break; // finish
} }
else if( evt->IsAction( &PCB_ACTIONS::toggleHV45Mode ) ) else if( evt->IsAction( &PCB_ACTIONS::toggleHV45Mode ) )

View File

@ -331,7 +331,7 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
setCursor(); setCursor();
STATUS_TEXT_POPUP statusPopup( frame() ); STATUS_TEXT_POPUP statusPopup( frame() );
wxString msg = _( "Click on pad %s%d\nPress <esc> to cancel or double-click to commit" ); wxString msg = _( "Click on pad %s%d\nPress <esc> to cancel all; double-click to finish" );
statusPopup.SetText( wxString::Format( msg, padPrefix, seqPadNum ) ); statusPopup.SetText( wxString::Format( msg, padPrefix, seqPadNum ) );
statusPopup.Popup(); statusPopup.Popup();
statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) ); statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
@ -448,8 +448,7 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
} }
} }
} }
else if( ( evt->IsKeyPressed() && evt->KeyCode() == WXK_RETURN ) || else if( evt->IsDblClick( BUT_LEFT ) )
evt->IsDblClick( BUT_LEFT ) )
{ {
commit.Push( _( "Renumber pads" ) ); commit.Push( _( "Renumber pads" ) );
frame()->PopTool( aEvent ); frame()->PopTool( aEvent );