ADDED: Move with Reference action

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/4755
Fixes: https://gitlab.com/kicad/code/kicad/-/issues/2304
This commit is contained in:
Jon Evans 2020-07-05 17:36:12 -04:00
parent 66f38dfc10
commit 707ce66cc6
4 changed files with 130 additions and 58 deletions

View File

@ -290,33 +290,46 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
int EDIT_TOOL::Move( const TOOL_EVENT& aEvent ) int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
{ {
KIGFX::VIEW_CONTROLS* controls = getViewControls(); return doMoveSelection( aEvent );
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); }
int EDIT_TOOL::MoveWithReference( const TOOL_EVENT& aEvent )
{
return doMoveSelection( aEvent, true );
}
int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
{
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
KIGFX::VIEW_CONTROLS* controls = getViewControls();
VECTOR2I originalCursorPos = controls->GetCursorPosition(); VECTOR2I originalCursorPos = controls->GetCursorPosition();
// 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)
PCBNEW_SELECTION& selection = m_selectionTool->RequestSelection( PCBNEW_SELECTION& selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS );
} ); } );
if( m_dragging || selection.Empty() ) if( m_dragging || selection.Empty() )
return 0; return 0;
LSET item_layers = selection.GetSelectionLayers(); LSET item_layers = selection.GetSelectionLayers();
bool unselect = selection.IsHover(); //N.B. This must be saved before the re-selection below bool unselect = selection.IsHover(); // N.B. This must be saved before the re-selection below
// Now filter out locked pads. We cannot do this in the first RequestSelection() as we need // Now filter out locked pads. We cannot do this in the first RequestSelection() as we need
// the item_layers when a pad is the selection front (ie: will become curr_tiem). // the item_layers when a pad is the selection front (ie: will become curr_tiem).
selection = m_selectionTool->RequestSelection( selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS ); EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS );
} ); } );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -332,7 +345,7 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
{ {
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item ); BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
MODULE* module = dynamic_cast<MODULE*>( item ); MODULE* module = dynamic_cast<MODULE*>( item );
if( boardItem ) if( boardItem )
sel_items.push_back( boardItem ); sel_items.push_back( boardItem );
@ -361,9 +374,10 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
grid.SetUseGrid( !evt->Modifier( MD_ALT ) ); grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
controls->SetSnapping( !evt->Modifier( MD_ALT ) ); controls->SetSnapping( !evt->Modifier( MD_ALT ) );
if( evt->IsAction( &PCB_ACTIONS::move ) || evt->IsMotion() || if( evt->IsAction( &PCB_ACTIONS::move ) || evt->IsMotion()
evt->IsAction( &PCB_ACTIONS::drag ) || evt->IsDrag( BUT_LEFT ) || || evt->IsAction( &PCB_ACTIONS::drag ) || evt->IsDrag( BUT_LEFT )
evt->IsAction( &ACTIONS::refreshPreview ) ) || evt->IsAction( &ACTIONS::refreshPreview )
|| evt->IsAction( &PCB_ACTIONS::moveWithReference ) )
{ {
if( m_dragging && evt->Category() == TC_MOUSE ) if( m_dragging && evt->Category() == TC_MOUSE )
{ {
@ -400,9 +414,11 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
frame()->UpdateMsgPanel(); frame()->UpdateMsgPanel();
} }
else if( !m_dragging ) // Prepare to start dragging else if( !m_dragging ) // Prepare to start dragging
{ {
if ( !evt->IsAction( &PCB_ACTIONS::move ) && isInteractiveDragEnabled() ) if( !( evt->IsAction( &PCB_ACTIONS::move )
|| evt->IsAction( &PCB_ACTIONS::moveWithReference ) )
&& isInteractiveDragEnabled() )
{ {
if( invokeInlineRouter( PNS::DM_ANY ) ) if( invokeInlineRouter( PNS::DM_ANY ) )
break; break;
@ -437,7 +453,7 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
editFrame->UndoRedoBlock( true ); editFrame->UndoRedoBlock( true );
m_cursor = controls->GetCursorPosition(); m_cursor = controls->GetCursorPosition();
if ( selection.HasReferencePoint() ) if( selection.HasReferencePoint() )
{ {
// start moving with the reference point attached to the cursor // start moving with the reference point attached to the cursor
grid.SetAuxAxes( false ); grid.SetAuxAxes( false );
@ -463,11 +479,32 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
items.push_back( static_cast<BOARD_ITEM*>( item ) ); items.push_back( static_cast<BOARD_ITEM*>( item ) );
m_cursor = grid.BestDragOrigin( originalCursorPos, items );
// 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
m_cursor = grid.BestDragOrigin( originalCursorPos, items ); if( aPickReference )
selection.SetReferencePoint( m_cursor ); {
grid.SetAuxAxes( true, m_cursor ); VECTOR2I ref;
if( pickReferencePoint( _( "Select reference point for move..." ),
"", "", ref ) )
{
selection.SetReferencePoint( ref );
controls->ForceCursorPosition( true, ref );
m_cursor = ref;
}
else
{
// Cancel before move started
break;
}
}
else
{
selection.SetReferencePoint( m_cursor );
grid.SetAuxAxes( true, m_cursor );
}
} }
controls->SetCursorPosition( m_cursor, false ); controls->SetCursorPosition( m_cursor, false );
@ -497,11 +534,11 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
{ {
if( evt->IsAction( &ACTIONS::doDelete ) ) if( evt->IsAction( &ACTIONS::doDelete ) )
{ {
break; // finish -- there is no further processing for removed items break; // finish -- there is no further processing for removed items
} }
else if( evt->IsAction( &ACTIONS::duplicate ) ) else if( evt->IsAction( &ACTIONS::duplicate ) )
{ {
break; // finish -- Duplicate tool will start a new Move with the dup'ed items break; // finish -- Duplicate tool will start a new Move with the dup'ed items
} }
else if( evt->IsAction( &PCB_ACTIONS::moveExact ) ) else if( evt->IsAction( &PCB_ACTIONS::moveExact ) )
{ {
@ -512,13 +549,13 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
i->Move( -totalMovement ); i->Move( -totalMovement );
} }
break; // finish -- we moved exactly, so we are finished break; // finish -- we moved exactly, so we are finished
} }
} }
else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
{ {
break; // finish break; // finish
} }
else else
@ -540,9 +577,6 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
// Discard reference point when selection is "dropped" onto the board (ie: not dragging anymore) // Discard reference point when selection is "dropped" onto the board (ie: not dragging anymore)
selection.ClearReferencePoint(); selection.ClearReferencePoint();
if( unselect )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
// If canceled, we need to remove the dynamic ratsnest from the screen // If canceled, we need to remove the dynamic ratsnest from the screen
if( restore_state ) if( restore_state )
{ {
@ -554,15 +588,19 @@ int EDIT_TOOL::Move( const TOOL_EVENT& aEvent )
m_commit->Push( _( "Drag" ) ); m_commit->Push( _( "Drag" ) );
} }
if( unselect )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
editFrame->PopTool( tool ); editFrame->PopTool( tool );
return 0; return 0;
} }
int EDIT_TOOL::ChangeTrackWidth( const TOOL_EVENT& aEvent ) int EDIT_TOOL::ChangeTrackWidth( const TOOL_EVENT& aEvent )
{ {
const auto& selection = m_selectionTool->RequestSelection( const auto& selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) {
{
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS );
} ); } );
@ -1338,7 +1376,8 @@ bool EDIT_TOOL::updateModificationPoint( PCBNEW_SELECTION& aSelection )
} }
bool EDIT_TOOL::pickCopyReferencePoint( VECTOR2I& aReferencePoint ) bool EDIT_TOOL::pickReferencePoint( const wxString& aTooltip, const wxString& aSuccessMessage,
const wxString& aCanceledMessage, VECTOR2I& aReferencePoint )
{ {
std::string tool = "pcbnew.InteractiveEdit.selectReferencePoint"; std::string tool = "pcbnew.InteractiveEdit.selectReferencePoint";
STATUS_TEXT_POPUP statusPopup( frame() ); STATUS_TEXT_POPUP statusPopup( frame() );
@ -1346,35 +1385,51 @@ bool EDIT_TOOL::pickCopyReferencePoint( VECTOR2I& aReferencePoint )
OPT<VECTOR2I> pickedPoint; OPT<VECTOR2I> pickedPoint;
bool done = false; bool done = false;
statusPopup.SetText( _( "Select reference point for the copy..." ) ); statusPopup.SetText( aTooltip );
picker->SetClickHandler( picker->SetClickHandler(
[&]( const VECTOR2D& aPoint ) -> bool [&]( const VECTOR2D& aPoint ) -> bool
{ {
pickedPoint = aPoint; pickedPoint = aPoint;
statusPopup.SetText( _( "Selection copied." ) );
statusPopup.Expire( 800 ); if( !aSuccessMessage.empty() )
return false; // we don't need any more points {
} ); statusPopup.SetText( aSuccessMessage );
statusPopup.Expire( 800 );
}
else
{
statusPopup.Hide();
}
return false; // we don't need any more points
} );
picker->SetMotionHandler( picker->SetMotionHandler(
[&] ( const VECTOR2D& aPos ) [&]( const VECTOR2D& aPos )
{ {
statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) ); statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
} ); } );
picker->SetCancelHandler( picker->SetCancelHandler(
[&]() [&]()
{ {
statusPopup.SetText( _( "Copy cancelled." ) ); if( !aCanceledMessage.empty() )
statusPopup.Expire( 800 ); {
} ); statusPopup.SetText( aCanceledMessage );
statusPopup.Expire( 800 );
}
else
{
statusPopup.Hide();
}
} );
picker->SetFinalizeHandler( picker->SetFinalizeHandler(
[&]( const int& aFinalState ) [&]( const int& aFinalState )
{ {
done = true; done = true;
} ); } );
statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) ); statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
statusPopup.Popup(); statusPopup.Popup();
@ -1401,8 +1456,7 @@ int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent )
Activate(); Activate();
PCBNEW_SELECTION& selection = m_selectionTool->RequestSelection( PCBNEW_SELECTION& selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector ) {
{
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS ); EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS );
} ); } );
@ -1410,7 +1464,8 @@ int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent )
return 1; return 1;
VECTOR2I refPoint; VECTOR2I refPoint;
bool rv = pickCopyReferencePoint( refPoint ); bool rv = pickReferencePoint( _( "Select reference point for the copy..." ),
_( "Selection copied." ), _( "Copy cancelled." ), refPoint );
frame()->SetMsgPanel( board() ); frame()->SetMsgPanel( board() );
if( !rv ) if( !rv )
@ -1454,8 +1509,9 @@ void EDIT_TOOL::setTransitions()
Go( &EDIT_TOOL::Remove, ACTIONS::doDelete.MakeEvent() ); Go( &EDIT_TOOL::Remove, ACTIONS::doDelete.MakeEvent() );
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::Duplicate, ACTIONS::duplicate.MakeEvent() ); Go( &EDIT_TOOL::MoveWithReference, PCB_ACTIONS::moveWithReference.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() );
Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirror.MakeEvent() ); Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirror.MakeEvent() );

View File

@ -134,6 +134,11 @@ public:
*/ */
int MoveExact( const TOOL_EVENT& aEvent ); int MoveExact( const TOOL_EVENT& aEvent );
/**
* Moves an item but with a reference point selected first
*/
int MoveWithReference( const TOOL_EVENT& aEvent );
/** /**
* Function CreateArray() * Function CreateArray()
* Creates an array of the selected items, invoking the array editor dialog to set the options. * Creates an array of the selected items, invoking the array editor dialog to set the options.
@ -179,7 +184,10 @@ private:
bool invokeInlineRouter( int aDragMode ); bool invokeInlineRouter( int aDragMode );
bool isInteractiveDragEnabled() const; bool isInteractiveDragEnabled() const;
bool pickCopyReferencePoint( VECTOR2I& aReferencePoint ); int doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference = false );
bool pickReferencePoint( const wxString& aTooltip, const wxString& aSuccessMessage,
const wxString& aCanceledMessage, VECTOR2I& aReferencePoint );
private: private:
SELECTION_TOOL* m_selectionTool; // Selection tool used for obtaining selected items SELECTION_TOOL* m_selectionTool; // Selection tool used for obtaining selected items

View File

@ -199,6 +199,11 @@ TOOL_ACTION PCB_ACTIONS::move( "pcbnew.InteractiveMove.move",
_( "Move" ), _( "Moves the selected item(s)" ), _( "Move" ), _( "Moves the selected item(s)" ),
move_xpm, AF_ACTIVATE ); move_xpm, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::moveWithReference( "pcbnew.InteractiveMove.moveWithReference",
AS_GLOBAL, 0, "", _( "Move with Reference" ),
_( "Moves the selected item(s) with a specified starting point" ),
move_xpm, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::drag( "pcbnew.InteractiveMove.drag", TOOL_ACTION PCB_ACTIONS::drag( "pcbnew.InteractiveMove.drag",
AS_GLOBAL, 0, "", "", "", AS_GLOBAL, 0, "", "", "",
move_xpm, AF_ACTIVATE ); move_xpm, AF_ACTIVATE );

View File

@ -92,6 +92,9 @@ public:
static TOOL_ACTION move; static TOOL_ACTION move;
static TOOL_ACTION drag; static TOOL_ACTION drag;
/// move with a reference point
static TOOL_ACTION moveWithReference;
/// Rotation of selected objects /// Rotation of selected objects
static TOOL_ACTION rotateCw; static TOOL_ACTION rotateCw;
static TOOL_ACTION rotateCcw; static TOOL_ACTION rotateCcw;