Allow move tool to run on top of other tools.

Fixes: lp:1784480
* https://bugs.launchpad.net/kicad/+bug/1784480
This commit is contained in:
Jeff Young 2019-07-01 22:01:33 +01:00
parent ad26ece8d4
commit 9effd24f3a
39 changed files with 844 additions and 472 deletions

View File

@ -366,7 +366,7 @@ void EDA_DRAW_FRAME::AddStandardSubMenus( TOOL_MENU& aToolMenu )
void EDA_DRAW_FRAME::DisplayToolMsg( const wxString& msg )
{
SetStatusText( msg, 5 );
SetStatusText( msg, 6 );
}
@ -461,7 +461,7 @@ void EDA_DRAW_FRAME::PopTool()
}
}
else
DisplayToolMsg( ACTIONS::selectionTool.GetName() );
DisplayToolMsg( ACTIONS::selectionTool.GetLabel() );
}

View File

@ -54,7 +54,7 @@ static const std::string flag2string( int aFlag, const FlagString* aExps )
void TOOL_EVENT::init()
{
// By default only MESSAGEs and Cancels are passed to multiple recipients
m_passEvent = m_category == TC_MESSAGE || TOOL_EVT_UTILS::IsCancelInteractive( *this );
m_passEvent = m_category == TC_MESSAGE || IsCancelInteractive();
m_hasPosition = ( m_category == TC_MOUSE || m_category == TC_COMMAND );
}
@ -183,35 +183,42 @@ bool TOOL_EVENT::IsDblClick( int aButtonMask ) const
}
bool TOOL_EVT_UTILS::IsCancelInteractive( const TOOL_EVENT& aEvt )
bool TOOL_EVENT::IsCancelInteractive()
{
if( aEvt.GetCommandStr() && aEvt.GetCommandStr().get() == ACTIONS::cancelInteractive.GetName() )
if( GetCommandStr() && GetCommandStr().get() == ACTIONS::cancelInteractive.GetName() )
return true;
if( aEvt.GetCommandId() && aEvt.GetCommandId().get() == ACTIONS::cancelInteractive.GetId() )
if( GetCommandId() && GetCommandId().get() == ACTIONS::cancelInteractive.GetId() )
return true;
return aEvt.IsCancel();
return IsCancel();
}
bool TOOL_EVT_UTILS::IsSelectionEvent( const TOOL_EVENT& aEvt )
bool TOOL_EVENT::IsSelectionEvent()
{
return aEvt.Matches( EVENTS::ClearedEvent )
|| aEvt.Matches( EVENTS::UnselectedEvent )
|| aEvt.Matches( EVENTS::SelectedEvent );
return Matches( EVENTS::ClearedEvent )
|| Matches( EVENTS::UnselectedEvent )
|| Matches( EVENTS::SelectedEvent );
}
bool TOOL_EVT_UTILS::IsPointEditor( const TOOL_EVENT& aEvt )
bool TOOL_EVENT::IsPointEditor()
{
if( aEvt.GetCommandStr() && aEvt.GetCommandStr().get().find( "PointEditor" ) >= 0 )
if( GetCommandStr() && GetCommandStr().get().find( "PointEditor" ) != wxNOT_FOUND )
return true;
if( aEvt.GetCommandId() && aEvt.GetCommandId() == ACTIONS::activatePointEditor.GetId() )
if( GetCommandId() && GetCommandId() == ACTIONS::activatePointEditor.GetId() )
return true;
return false;
}
bool TOOL_EVENT::IsMoveTool()
{
if( GetCommandStr() && GetCommandStr().get().find( "InteractiveMove" ) != wxNOT_FOUND )
return true;
return false;
}

View File

@ -52,7 +52,7 @@ int ZOOM_TOOL::Main( const TOOL_EVENT& aEvent )
{
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
break;
else if( evt->IsDrag( BUT_LEFT ) || evt->IsDrag( BUT_RIGHT ) )
@ -84,7 +84,7 @@ bool ZOOM_TOOL::selectRegion()
while( TOOL_EVENT* evt = Wait() )
{
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
cancelled = true;
break;

View File

@ -128,22 +128,39 @@ int CVPCB_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
const VECTOR2I cursorPos = controls.GetCursorPosition();
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto clearRuler = [&] () {
view.SetVisible( &ruler, false );
controls.SetAutoPan( false );
controls.CaptureCursor( false );
originSet = false;
};
if( evt->IsCancelInteractive() )
{
if( originSet )
clearRuler();
else
{
view.SetVisible( &ruler, false );
controls.SetAutoPan( false );
controls.CaptureCursor( false );
originSet = false;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
if( evt->IsActivate() )
else if( evt->IsActivate() )
{
if( originSet )
clearRuler();
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
// click or drag starts
@ -199,7 +216,6 @@ int CVPCB_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
view.SetVisible( &ruler, false );
view.Remove( &ruler );
controls.ApplySettings( previous_settings );
m_frame->PopTool();
return 0;
}

View File

@ -667,12 +667,12 @@ TOOL_ACTION EE_ACTIONS::finishLine( "eeschema.InteractiveDrawingLineWireBus.fini
// SCH_MOVE_TOOL
//
TOOL_ACTION EE_ACTIONS::move( "eeschema.InteractiveEdit.move",
TOOL_ACTION EE_ACTIONS::move( "eeschema.InteractiveMove.move",
AS_GLOBAL,
'M', LEGACY_HK_NAME( "Move Item" ),
_( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE );
TOOL_ACTION EE_ACTIONS::drag( "eeschema.InteractiveEdit.drag",
TOOL_ACTION EE_ACTIONS::drag( "eeschema.InteractiveMove.drag",
AS_GLOBAL,
'G', LEGACY_HK_NAME( "Drag Item" ),
_( "Drag" ), _( "Drags the selected item(s)" ), move_xpm, AF_ACTIVATE );

View File

@ -92,7 +92,7 @@ int EE_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( m_cancelHandler )
{

View File

@ -295,7 +295,7 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
// Main loop: keep receiving events
while( TOOL_EVENT* evt = Wait() )
{
if( !m_editPoints || TOOL_EVT_UTILS::IsSelectionEvent( *evt ) )
if( !m_editPoints || evt->IsSelectionEvent() )
break;
if ( !inDrag )
@ -328,7 +328,7 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
inDrag = false;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( inDrag ) // Restore the last change
{
@ -336,8 +336,11 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
inDrag = false;
modified = false;
}
else if( evt->IsCancelInteractive() )
break;
break;
if( evt->IsActivate() && !evt->IsMoveTool() )
break;
}
else

View File

@ -400,7 +400,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
else if( evt->IsCancelInteractive() )
{
ClearSelection();
}
@ -658,7 +658,7 @@ bool EE_SELECTION_TOOL::selectMultiple()
while( TOOL_EVENT* evt = Wait() )
{
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
cancelled = true;
break;

View File

@ -89,22 +89,38 @@ int LIB_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete item;
item = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( item )
cleanup();
else
{
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete item;
item = nullptr;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( item )
cleanup();
if( evt->IsActivate() )
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
@ -207,7 +223,6 @@ int LIB_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
m_frame->PopTool();
return 0;
}
@ -242,23 +257,43 @@ int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete item;
item = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( item )
cleanup();
else
{
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete item;
item = nullptr;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
// Continue on if it's just the point editor; otherwise give way to new tool
if( evt->IsActivate() && !TOOL_EVT_UTILS::IsPointEditor( *evt ) )
else if( evt->IsActivate() )
{
if( item )
cleanup();
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) && !item )
@ -339,7 +374,6 @@ int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
m_frame->PopTool();
return 0;
}
@ -357,8 +391,14 @@ int LIB_DRAWING_TOOLS::PlaceAnchor( const TOOL_EVENT& aEvent )
{
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() )
{
m_frame->PopTool();
break;
}
else if( evt->IsActivate() )
{
m_frame->PopTool();
break;
}
else if( evt->IsClick( BUT_LEFT ) )
@ -387,7 +427,6 @@ int LIB_DRAWING_TOOLS::PlaceAnchor( const TOOL_EVENT& aEvent )
}
}
m_frame->PopTool();
return 0;
}

View File

@ -197,7 +197,7 @@ int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
//------------------------------------------------------------------------
// Handle cancel
//
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( m_moveInProgress )
restore_state = true;

View File

@ -118,22 +118,38 @@ int SCH_DRAWING_TOOLS::PlaceComponent( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( component ? wxCURSOR_ARROW : wxCURSOR_PENCIL );
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete component;
component = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( component )
cleanup();
else
{
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete component;
component = nullptr;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( component )
cleanup();
if( evt->IsActivate() )
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
@ -210,7 +226,6 @@ int SCH_DRAWING_TOOLS::PlaceComponent( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( component != nullptr );
}
m_frame->PopTool();
return 0;
}
@ -247,25 +262,44 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( image ? wxCURSOR_ARROW : wxCURSOR_PENCIL );
cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete image;
image = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( image )
cleanup();
else
{
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete image;
image = nullptr;
if( immediateMode )
break;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
if( evt->IsActivate() )
if( immediateMode )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( image )
cleanup();
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
@ -315,7 +349,10 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
m_view->ClearPreview();
if( immediateMode )
{
m_frame->PopTool();
break;
}
}
}
else if( evt->IsClick( BUT_RIGHT ) )
@ -339,7 +376,6 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( image != nullptr );
}
m_frame->PopTool();
return 0;
}
@ -403,10 +439,24 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
cursorPos = (wxPoint) getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() )
{
m_frame->PopTool();
break;
}
else if( evt->IsActivate() )
{
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !m_frame->GetScreen()->GetItem( cursorPos, 0, type ) )
@ -442,7 +492,6 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
delete previewItem;
m_view->ClearPreview();
m_frame->PopTool();
return 0;
}
@ -469,22 +518,42 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( item ? wxCURSOR_ARROW : wxCURSOR_PENCIL );
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete item;
item = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( item )
cleanup();
else
{
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete item;
item = nullptr;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( item )
cleanup();
if( evt->IsActivate() )
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
@ -585,7 +654,7 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
}
else if( item && TOOL_EVT_UTILS::IsSelectionEvent( *evt ) )
else if( item && evt->IsSelectionEvent() )
{
// This happens if our text was replaced out from under us by ConvertTextType()
EE_SELECTION& selection = m_selectionTool->GetSelection();
@ -611,7 +680,6 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
m_frame->PopTool();
return 0;
}
@ -639,23 +707,42 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
{
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_view->ClearPreview();
delete sheet;
sheet = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( sheet )
cleanup();
else
{
delete sheet;
sheet = nullptr;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( sheet )
cleanup();
if( evt->IsActivate() )
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) && !sheet )
@ -712,7 +799,6 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( sheet != nullptr);
}
m_frame->PopTool();
return 0;
}

View File

@ -265,10 +265,7 @@ int SCH_LINE_WIRE_BUS_TOOL::DrawSegments( const TOOL_EVENT& aEvent )
segment = startSegments( layer, cursorPos );
}
doDrawSegments( layer, segment );
m_frame->PopTool();
return 0;
return doDrawSegments( layer, segment );
}
@ -316,10 +313,12 @@ int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
// If we have an unfolded wire to draw, then draw it
if( segment )
doDrawSegments( LAYER_WIRE, segment );
m_frame->PopTool();
return 0;
return doDrawSegments( LAYER_WIRE, segment );
else
{
m_frame->PopTool();
return 0;
}
}
@ -461,35 +460,51 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( int aType, SCH_LINE* aSegment )
//------------------------------------------------------------------------
// Handle cancel:
//
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
aSegment = nullptr;
s_wires.DeleteAll();
if( m_busUnfold.entry )
m_frame->RemoveFromScreen( m_busUnfold.entry );
if( m_busUnfold.label && m_busUnfold.label_placed )
m_frame->RemoveFromScreen( m_busUnfold.label );
delete m_busUnfold.entry;
delete m_busUnfold.label;
m_busUnfold = {};
m_view->ClearPreview();
m_view->ShowPreview( false );
};
if( evt->IsCancelInteractive() )
{
if( aSegment || m_busUnfold.in_progress )
cleanup();
else
{
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
aSegment = nullptr;
s_wires.DeleteAll();
if( m_busUnfold.entry )
m_frame->RemoveFromScreen( m_busUnfold.entry );
if( m_busUnfold.label && m_busUnfold.label_placed )
m_frame->RemoveFromScreen( m_busUnfold.label );
delete m_busUnfold.entry;
delete m_busUnfold.label;
m_busUnfold = {};
m_view->ClearPreview();
m_view->ShowPreview( false );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( aSegment || m_busUnfold.in_progress )
cleanup();
if( evt->IsActivate() )
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
//------------------------------------------------------------------------
// Handle finish:

View File

@ -335,7 +335,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
//------------------------------------------------------------------------
// Handle cancel
//
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
else if( evt->IsCancelInteractive() )
{
if( m_moveInProgress )
restore_state = true;

View File

@ -355,7 +355,7 @@ bool GERBVIEW_SELECTION_TOOL::selectMultiple()
while( TOOL_EVENT* evt = Wait() )
{
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
if( evt->IsCancelInteractive() )
{
cancelled = true;
break;
@ -777,22 +777,39 @@ int GERBVIEW_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
const VECTOR2I cursorPos = controls.GetCursorPosition();
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto clearRuler = [&] () {
view.SetVisible( &ruler, false );
controls.SetAutoPan( false );
controls.CaptureCursor( false );
originSet = false;
};
if( evt->IsCancelInteractive() )
{
if( originSet )
clearRuler();
else
{
view.SetVisible( &ruler, false );
controls.SetAutoPan( false );
controls.CaptureCursor( false );
originSet = false;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
if( evt->IsActivate() )
else if( evt->IsActivate() )
{
if( originSet )
clearRuler();
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
// click or drag starts
@ -848,7 +865,6 @@ int GERBVIEW_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
view.SetVisible( &ruler, false );
view.Remove( &ruler );
controls.ApplySettings( previous_settings );
m_frame->PopTool();
return 0;
}

View File

@ -375,6 +375,37 @@ public:
*/
bool IsAction( const TOOL_ACTION* aAction ) const;
/**
* Function IsCancelInteractive()
*
* Indicates the event should restart/end an ongoing interactive tool's event loop (eg esc
* key, click cancel, start different tool).
*/
bool IsCancelInteractive();
/**
* Function IsSelectionEvent()
*
* Indicates an selection-changed notification event.
*/
bool IsSelectionEvent();
/**
* Function IsPointEditor
*
* Indicates if the event is from one of the point editors. Usually used to allow the
* point editor to activate itself without de-activating the current drawing tool.
*/
bool IsPointEditor();
/**
* Function IsMoveTool
*
* Indicates if the event is from one of the move tools. Usually used to allow move to
* be done without de-activating the current drawing tool.
*/
bool IsMoveTool();
/**
* Function Parameter()
* Returns a non-standard parameter assigned to the event. Its meaning depends on the
@ -638,38 +669,4 @@ inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEvent,
}
/**
* Namespace TOOL_EVT_UTILS
*
* Utility functions for dealing with various tool events. These are free functions, so they
* interface with any classes exclusively via the public interfaces, so they don't need to be
* subsumed into the "helped" classes.
*/
namespace TOOL_EVT_UTILS
{
/**
* Function IsCancelInteractive()
*
* Indicates the event should restart/end an ongoing interactive tool's event loop (eg esc
* key, click cancel, start different tool).
*/
bool IsCancelInteractive( const TOOL_EVENT& aEvt );
/**
* Function IsSelectionEvent()
*
* Indicates an selection-changed notification event.
*/
bool IsSelectionEvent( const TOOL_EVENT& aEvt );
/**
* Function IsPointEditor
*
* Indicates if the event is from one of the point editors. Usually used to allow the
* point editor to activate itself without de-activating the current drawing tool.
*/
bool IsPointEditor( const TOOL_EVENT& aEvt );
}
#endif

View File

@ -60,7 +60,7 @@ TOOL_ACTION PL_ACTIONS::placeImage( "plEditor.InteractiveDrawing.placeImage",
// PL_EDIT_TOOL
//
TOOL_ACTION PL_ACTIONS::move( "plEditor.InteractiveEdit.move",
TOOL_ACTION PL_ACTIONS::move( "plEditor.InteractiveMove.move",
AS_GLOBAL,
'M', LEGACY_HK_NAME( "Move Item" ),
_( "Move" ), _( "Moves the selected item(s)" ),

View File

@ -93,24 +93,40 @@ int PL_DRAWING_TOOLS::PlaceItem( const TOOL_EVENT& aEvent )
m_frame->GetCanvas()->SetCurrentCursor( item ? wxCURSOR_ARROW : wxCURSOR_PENCIL );
cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
delete item;
item = nullptr;
// There's nothing to roll-back, but we still need to pop the undo stack
m_frame->RollbackFromUndo();
};
if( evt->IsCancelInteractive() )
{
if( item )
cleanup();
else
{
m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
delete item;
item = nullptr;
// There's nothing to roll-back, but we still need to pop the undo stack
m_frame->RollbackFromUndo();
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( item )
cleanup();
if( evt->IsActivate() )
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
@ -163,7 +179,6 @@ int PL_DRAWING_TOOLS::PlaceItem( const TOOL_EVENT& aEvent )
getViewControls()->CaptureCursor( item != nullptr );
}
m_frame->PopTool();
return 0;
}
@ -196,7 +211,7 @@ int PL_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
@ -205,12 +220,12 @@ int PL_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
item = nullptr;
m_frame->RollbackFromUndo();
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
else if( evt->IsCancelInteractive() )
{
break;
}
if( evt->IsActivate() && !TOOL_EVT_UTILS::IsPointEditor( *evt ) )
if( evt->IsActivate() && !evt->IsPointEditor() && !evt->IsMoveTool() )
break;
}

View File

@ -185,7 +185,7 @@ int PL_EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
//------------------------------------------------------------------------
// Handle cancel
//
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( m_moveInProgress )
restore_state = true;

View File

@ -119,7 +119,7 @@ int PL_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( m_cancelHandler )
{

View File

@ -185,7 +185,7 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
// Main loop: keep receiving events
while( TOOL_EVENT* evt = Wait() )
{
if( !m_editPoints || TOOL_EVT_UTILS::IsSelectionEvent( *evt ) )
if( !m_editPoints || evt->IsSelectionEvent() )
break;
if ( !inDrag )
@ -213,7 +213,7 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
inDrag = false;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( inDrag ) // Restore the last change
{
@ -221,8 +221,11 @@ int PL_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
inDrag = false;
modified = false;
}
else if( evt->IsCancelInteractive() )
break;
break;
if( evt->IsActivate() && !evt->IsMoveTool() )
break;
}
else

View File

@ -180,7 +180,7 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
else if( evt->IsCancelInteractive() )
{
ClearSelection();
}
@ -308,7 +308,7 @@ bool PL_SELECTION_TOOL::selectMultiple()
while( TOOL_EVENT* evt = Wait() )
{
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
cancelled = true;
break;

View File

@ -57,7 +57,6 @@ MODULE* PCB_EDIT_FRAME::CreateMuWaveBaseFootprint( const wxString& aValue,
int aTextSize, int aPadCount )
{
MODULE* module = CreateNewModule( aValue );
AddModuleToBoard( module );
if( aTextSize > 0 )
{

View File

@ -192,7 +192,7 @@ void LENGTH_TUNER_TOOL::performTuning()
{
frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
break;
else if( evt->IsMotion() )
{
@ -280,7 +280,7 @@ int LENGTH_TUNER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
{
frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
break; // Finish
}

View File

@ -76,6 +76,8 @@ protected:
GRID_HELPER* m_gridHelper;
PNS_KICAD_IFACE* m_iface;
ROUTER* m_router;
bool m_cancelled;
};
}

View File

@ -805,10 +805,18 @@ void ROUTER_TOOL::performRouting()
still_routing = m_router->FixRoute( m_endSnapPoint, m_endItem );
break;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate()
else if( evt->IsCancelInteractive() || evt->IsActivate()
|| evt->IsUndoRedo()
|| evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
{
if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
m_cancelled = true;
if( evt->IsActivate() && !evt->IsMoveTool() )
m_cancelled = true;
break;
}
}
finishInteractive();
@ -849,9 +857,7 @@ int ROUTER_TOOL::SettingsDialog( const TOOL_EVENT& aEvent )
void ROUTER_TOOL::breakTrack()
{
if( m_startItem && m_startItem->OfKind( PNS::ITEM::SEGMENT_T ) )
{
m_router->BreakSegment( m_startItem, m_startSnapPoint );
}
}
@ -871,6 +877,7 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
VIEW_CONTROLS* ctls = getViewControls();
ctls->ShowCursor( true );
ctls->ForceCursorPosition( false );
m_cancelled = false;
m_startSnapPoint = ctls->GetCursorPosition();
std::unique_ptr<ROUTER_TOOL_MENU> ctxMenu( new ROUTER_TOOL_MENU( *frame, mode ) );
@ -885,9 +892,23 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
{
frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() )
{
break; // Finish
frame->PopTool();
break;
}
else if( evt->IsActivate() )
{
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
frame->PopTool();
break;
}
}
else if( evt->Action() == TA_UNDO_REDO_PRE )
{
@ -928,15 +949,24 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
updateStartItem( *evt );
if( evt->Modifier( MD_CTRL ) )
performDragging( PNS::DM_ANY );
else
performRouting();
if( evt->HasPosition() )
{
if( evt->Modifier( MD_CTRL ) )
performDragging( PNS::DM_ANY );
else
performRouting();
}
}
else if( evt->IsAction( &ACT_PlaceThroughVia ) )
{
m_toolMgr->RunAction( PCB_ACTIONS::layerToggle, true );
}
if( m_cancelled )
{
frame->PopTool();
break;
}
}
SetContextMenu( nullptr );
@ -945,7 +975,6 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
m_savedSettings = m_router->Settings();
m_savedSizes = m_router->Sizes();
frame->PopTool();
return 0;
}
@ -991,9 +1020,14 @@ void ROUTER_TOOL::performDragging( int aMode )
if( m_router->FixRoute( m_endSnapPoint, m_endItem ) )
break;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate()
|| evt->IsUndoRedo() )
else if( evt->IsCancelInteractive() || evt->IsActivate() || evt->IsUndoRedo() )
{
if( evt->IsCancelInteractive() && !m_startItem )
m_cancelled = true;
if( evt->IsActivate() && !evt->IsMoveTool() )
m_cancelled = true;
break;
}
@ -1135,7 +1169,7 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
{
frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
if( evt->IsCancelInteractive() )
{
break;
}

View File

@ -27,14 +27,10 @@
#include "pcb_actions.h"
#include <pcb_edit_frame.h>
#include <class_draw_panel_gal.h>
#include <project.h>
#include <id.h>
#include <pcbnew_id.h>
#include <confirm.h>
#include <import_gfx/dialog_import_gfx.h>
#include <view/view_group.h>
#include <view/view_controls.h>
#include <view/view.h>
#include <gal/graphics_abstraction_layer.h>
@ -172,7 +168,6 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
line->SetFlags( IS_NEW );
}
m_frame->PopTool();
return 0;
}
@ -214,7 +209,6 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
startingPoint = NULLOPT;
}
m_frame->PopTool();
return 0;
}
@ -253,7 +247,6 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
immediateMode = false;
}
m_frame->PopTool();
return 0;
}
@ -291,27 +284,40 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
if( reselect && text )
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, text );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_controls->ShowCursor( true );
delete text;
text = NULL;
};
if( evt->IsCancelInteractive() )
{
if( text )
cleanup();
else
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
// Delete the old text and have another try
delete text;
text = NULL;
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_controls->ShowCursor( true );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( text )
cleanup();
if( evt->IsActivate() )
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsClick( BUT_RIGHT ) )
{
@ -433,7 +439,6 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
}
frame()->SetMsgPanel( board() );
m_frame->PopTool();
return 0;
}
@ -495,24 +500,44 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
VECTOR2I cursorPos = grid.BestSnapAnchor( m_controls->GetMousePosition(), nullptr );
m_controls->ForceCursorPosition( true, cursorPos );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
preview.Clear();
delete dimension;
dimension = nullptr;
step = SET_ORIGIN;
};
if( evt->IsCancelInteractive() )
{
m_controls->SetAutoPan( false );
if( step != SET_ORIGIN ) // start from the beginning
cleanup();
else
{
preview.Clear();
delete dimension;
step = SET_ORIGIN;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( step != SET_ORIGIN )
cleanup();
if( evt->IsActivate() )
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN )
{
@ -647,7 +672,6 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
m_view->Remove( &preview );
frame()->SetMsgPanel( board() );
m_frame->PopTool();
return 0;
}
@ -744,7 +768,7 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
else if( evt->Category() == TC_COMMAND )
{
// TODO it should be handled by EDIT_TOOL, so add items and select?
if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) )
if( evt->IsCancelInteractive() )
{
const auto rotationPoint = (wxPoint) cursorPos;
const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *m_frame, *evt );
@ -761,9 +785,11 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
m_view->Update( &preview );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
preview.FreeItems();
m_frame->PopTool();
break;
}
}
@ -784,7 +810,6 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
preview.Clear();
m_view->Remove( &preview );
m_frame->PopTool();
return 0;
}
@ -825,17 +850,20 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
// Usually, we do not need to change twice the anchor position,
// so deselect the active tool
m_frame->PopTool();
break;
}
else if( evt->IsClick( BUT_RIGHT ) )
{
m_menu.ShowContextMenu( selection() );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
m_frame->PopTool();
break;
}
}
m_frame->PopTool();
return 0;
}
@ -858,6 +886,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, OPT<VECTOR2D
bool direction45 = false; // 45 degrees only mode
bool started = false;
bool cancelled = false;
bool isLocalOriginSet = ( m_frame->GetScreen()->m_LocalOrigin != VECTOR2D( 0, 0 ) );
VECTOR2I cursorPos = m_controls->GetMousePosition();
@ -905,20 +934,48 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, OPT<VECTOR2D
frame()->SetMsgPanel( aGraphic );
}
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
preview.Clear();
m_view->Update( &preview );
delete aGraphic;
aGraphic = nullptr;
if( !isLocalOriginSet )
m_frame->GetScreen()->m_LocalOrigin = VECTOR2D( 0, 0 );
};
if( evt->IsCancelInteractive() )
{
if( started )
cleanup();
else
{
preview.Clear();
m_view->Update( &preview );
delete aGraphic;
aGraphic = nullptr;
if( !isLocalOriginSet )
m_frame->GetScreen()->m_LocalOrigin = VECTOR2D( 0, 0 );
m_frame->PopTool();
cancelled = true;
break;
}
}
else if( evt->IsActivate() )
{
if( started )
cleanup();
break;
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
cancelled = true;
break;
}
else
{
m_frame->PopTool();
cancelled = true;
break;
}
}
else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
{
@ -966,7 +1023,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, OPT<VECTOR2D
else
{
auto snapItem = dyn_cast<DRAWSEGMENT*>( grid.GetSnapped() );
auto mod = dyn_cast<MODULE*>( m_frame->GetModel() );
if( aGraphic->GetEnd() == aGraphic->GetStart()
|| ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT )
@ -1047,7 +1103,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, OPT<VECTOR2D
m_controls->CaptureCursor( false );
m_controls->ForceCursorPosition( false );
return started;
return cancelled;
}
@ -1089,6 +1145,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic, bool aImmediateMode )
m_controls->SetSnapping( true );
bool firstPoint = false;
bool cancelled = false;
// Prime the pump
if( aImmediateMode )
@ -1107,7 +1164,46 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic, bool aImmediateMode )
VECTOR2I cursorPos = grid.BestSnapAnchor( m_controls->GetMousePosition(), aGraphic );
m_controls->ForceCursorPosition( true, cursorPos );
if( evt->IsClick( BUT_LEFT ) )
auto cleanup = [&] () {
preview.Clear();
delete aGraphic;
aGraphic = nullptr;
};
if( evt->IsCancelInteractive() )
{
if( firstPoint )
cleanup();
else
{
m_frame->PopTool();
cancelled = true;
break;
}
}
else if( evt->IsActivate() )
{
if( firstPoint )
cleanup();
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
cancelled = true;
break;
}
else
{
m_frame->PopTool();
cancelled = true;
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !firstPoint )
{
@ -1141,17 +1237,6 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic, bool aImmediateMode )
// update, but don't step the manager state
arcManager.AddPoint( cursorPos, false );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
{
if( firstPoint )
{
preview.Clear();
delete aGraphic;
aGraphic = nullptr;
}
break;
}
else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
{
m_lineWidth = getSegmentWidth( getDrawingLayer() );
@ -1208,7 +1293,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic, bool aImmediateMode )
m_controls->CaptureCursor( false );
m_controls->ForceCursorPosition( false );
return !arcManager.IsReset();
return cancelled;
}
@ -1313,25 +1398,42 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
VECTOR2I cursorPos = grid.BestSnapAnchor( m_controls->GetMousePosition(), layers );
m_controls->ForceCursorPosition( true, cursorPos );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
polyGeomMgr.Reset();
started = false;
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
};
if( evt->IsCancelInteractive())
{
if( polyGeomMgr.IsPolygonInProgress() )
{
polyGeomMgr.Reset();
// start again
started = false;
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
if( polyGeomMgr.IsPolygonInProgress() )
cleanup();
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( polyGeomMgr.IsPolygonInProgress() )
cleanup();
// pre-empted by another tool, give up
if( evt->IsActivate() && !TOOL_EVT_UTILS::IsPointEditor( *evt ) )
if( evt->IsPointEditor() )
{
// don't exit (the point editor runs in the background)
}
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
m_frame->PopTool();
break;
}
}
else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
{
@ -1374,7 +1476,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
m_controls->CaptureCursor( true );
}
}
}
else if( evt->IsAction( &PCB_ACTIONS::deleteLastPoint ) )
{
@ -1412,7 +1513,6 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
} // end while
m_controls->ForceCursorPosition( false );
m_frame->PopTool();
return 0;
}
@ -1696,10 +1796,8 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::VIA );
frame()->PushTool( aEvent.GetCommandStr().get() );
doInteractiveItemPlacement( &placer, _( "Place via" ),
IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP );
doInteractiveItemPlacement( &placer, _( "Place via" ), IPO_REPEAT | IPO_SINGLE_CLICK );
frame()->PopTool();
return 0;
}

View File

@ -412,7 +412,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( PCB_ACTIONS::updateLocalRatsnest, false );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
restore_state = true; // Canceling the tool means that items have to be restored
break; // Finish
@ -1135,22 +1135,39 @@ int EDIT_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
const VECTOR2I cursorPos = grid.BestSnapAnchor( controls.GetMousePosition(), nullptr );
controls.ForceCursorPosition(true, cursorPos );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto clearRuler = [&] () {
view.SetVisible( &ruler, false );
controls.SetAutoPan( false );
controls.CaptureCursor( false );
originSet = false;
};
if( evt->IsCancelInteractive() )
{
if( originSet )
clearRuler();
else
{
view.SetVisible( &ruler, false );
controls.SetAutoPan( false );
controls.CaptureCursor( false );
originSet = false;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
frame()->PopTool();
break;
}
}
if( evt->IsActivate() )
else if( evt->IsActivate() )
{
if( originSet )
clearRuler();
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
frame()->PopTool();
break;
}
}
// click or drag starts
@ -1203,7 +1220,6 @@ int EDIT_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
view.SetVisible( &ruler, false );
view.Remove( &ruler );
frame()->PopTool();
return 0;
}

View File

@ -36,6 +36,12 @@ class BOARD_COMMIT;
class BOARD_ITEM;
class CONNECTIVITY_DATA;
namespace KIGFX {
namespace PREVIEW {
class RULER_ITEM;
}
}
/**
* Function EditToolSelectionFilter
*
@ -196,6 +202,8 @@ private:
///> of edit reference point).
VECTOR2I m_cursor;
KIGFX::PREVIEW::RULER_ITEM* m_ruler;
///> Returns the right modification point (e.g. for rotation), depending on the number of
///> selected items.
bool updateModificationPoint( PCBNEW_SELECTION& aSelection );

View File

@ -318,7 +318,6 @@ int MODULE_EDITOR_TOOLS::PlacePad( const TOOL_EVENT& aEvent )
doInteractiveItemPlacement( &placer, _( "Place pad" ),
IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP );
frame()->PopTool();
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors.
* Copyright (C) 2017-2019 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -38,7 +38,6 @@
#include <microwave/microwave_inductor.h>
#include "pcb_actions.h"
#include "selection_tool.h"
#include "tool_event_utils.h"
MICROWAVE_TOOL::MICROWAVE_TOOL() :
@ -58,71 +57,44 @@ void MICROWAVE_TOOL::Reset( RESET_REASON aReason )
int MICROWAVE_TOOL::addMicrowaveFootprint( const TOOL_EVENT& aEvent )
{
auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
std::function<std::unique_ptr<MODULE>()> creator;
switch( aEvent.Parameter<intptr_t>() )
{
case MWAVE_TOOL_SIMPLE_ID::GAP:
creator = [&frame] () {
return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 0 ) );
};
break;
case MWAVE_TOOL_SIMPLE_ID::STUB:
creator = [&frame] () {
return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 1 ) );
};
break;
case MWAVE_TOOL_SIMPLE_ID::STUB_ARC:
creator = [&frame] () {
return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 2 ) );
};
break;
case MWAVE_TOOL_SIMPLE_ID::FUNCTION_SHAPE:
creator = [&frame] () {
return std::unique_ptr<MODULE>( frame.Create_MuWavePolygonShape() );
};
break;
default:
break;
};
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
struct MICROWAVE_PLACER : public INTERACTIVE_PLACER_BASE
{
const std::function<std::unique_ptr<MODULE>()>& m_creator;
MICROWAVE_PLACER( const std::function<std::unique_ptr<MODULE>()>& aCreator ) :
m_creator( aCreator ) {};
MICROWAVE_PLACER( PCB_EDIT_FRAME* aFrame, int aType ) :
m_frame( aFrame ),
m_itemType( aType )
{ };
std::unique_ptr<BOARD_ITEM> CreateItem() override
{
auto module = m_creator();
// Module has been added in the legacy backend,
// so we have to remove it before committing the change
// @todo LEGACY
if( module )
switch( m_itemType )
{
m_board->Remove( module.get() );
}
return std::unique_ptr<BOARD_ITEM>( module.release() );
case MWAVE_TOOL_SIMPLE_ID::GAP:
return std::unique_ptr<MODULE>( m_frame->Create_MuWaveComponent( 0 ) );
case MWAVE_TOOL_SIMPLE_ID::STUB:
return std::unique_ptr<MODULE>( m_frame->Create_MuWaveComponent( 1 ) );
case MWAVE_TOOL_SIMPLE_ID::STUB_ARC:
return std::unique_ptr<MODULE>( m_frame->Create_MuWaveComponent( 2 ) );
case MWAVE_TOOL_SIMPLE_ID::FUNCTION_SHAPE:
return std::unique_ptr<MODULE>( m_frame->Create_MuWavePolygonShape() );
default:
return std::unique_ptr<MODULE>();
};
}
private:
PCB_EDIT_FRAME* m_frame;
int m_itemType;
};
MICROWAVE_PLACER placer( creator );
MICROWAVE_PLACER placer( frame, aEvent.Parameter<intptr_t>() );
frame.PushTool( aEvent.GetCommandStr().get() );
frame->PushTool( aEvent.GetCommandStr().get() );
doInteractiveItemPlacement( &placer, _( "Place microwave feature" ),
IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP | IPO_PROPERTIES );
IPO_REPEAT | IPO_ROTATE | IPO_FLIP );
frame.PopTool();
return 0;
}
@ -212,31 +184,44 @@ int MICROWAVE_TOOL::drawMicrowaveInductor( const TOOL_EVENT& aEvent )
frame.GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
VECTOR2I cursorPos = controls.GetCursorPosition();
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
originSet = false;
controls.CaptureCursor( false );
controls.SetAutoPan( false );
view.SetVisible( &previewRect, false );
view.Update( &previewRect, KIGFX::GEOMETRY );
};
if( evt->IsCancelInteractive() )
{
if( originSet )
cleanup();
else
{
// had an in-progress area, so start again but don't
// cancel the tool
originSet = false;
controls.CaptureCursor( false );
controls.SetAutoPan( false );
view.SetVisible( &previewRect, false );
view.Update( &previewRect, KIGFX::GEOMETRY );
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
frame.PopTool();
break;
}
}
if( evt->IsActivate() )
else if( evt->IsActivate() )
{
if( originSet )
cleanup();
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
frame.PopTool();
break;
}
}
// A click or drag starts
else if( !originSet &&
( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) ) )
else if( !originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) ) )
{
tpGeomMgr.SetOrigin( cursorPos );
tpGeomMgr.SetEnd( cursorPos );
@ -283,7 +268,6 @@ int MICROWAVE_TOOL::drawMicrowaveInductor( const TOOL_EVENT& aEvent )
controls.CaptureCursor( false );
controls.SetAutoPan( false );
view.Remove( &previewRect );
frame.PopTool();
return 0;
}

View File

@ -366,7 +366,24 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
{
frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_BULLSEYE );
if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
if( evt->IsCancelInteractive() )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
commit.Revert();
frame()->PopTool();
break;
}
else if( evt->IsActivate() )
{
commit.Push( _( "Renumber pads" ) );
frame()->PopTool();
break;
}
else if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
{
selectedPads.clear();
VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
@ -471,22 +488,6 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
break;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
{
// This is a cancel-current-action (ie: <esc>).
if( evt->IsCancel() )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
commit.Revert();
}
else
{
commit.Push( _( "Renumber pads" ) );
}
break;
}
else if( evt->IsClick( BUT_RIGHT ) )
{
m_menu.ShowContextMenu( selection() );
@ -505,7 +506,6 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
}
statusPopup.Hide();
frame()->PopTool();
return 0;
}

View File

@ -185,7 +185,7 @@ TOOL_ACTION PCB_ACTIONS::editActivate( "pcbnew.InteractiveEdit",
_( "Edit Activate" ), "",
move_xpm, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::move( "pcbnew.InteractiveEdit.move",
TOOL_ACTION PCB_ACTIONS::move( "pcbnew.InteractiveMove.move",
AS_GLOBAL,
'M', LEGACY_HK_NAME( "Move Item" ),
_( "Move" ), _( "Moves the selected item(s)" ),

View File

@ -542,21 +542,38 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent )
if( reselect && module )
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, module );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] () {
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
commit.Revert();
module = NULL;
};
if( evt->IsCancelInteractive() )
{
if( module )
cleanup();
else
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
commit.Revert();
module = NULL;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{
m_frame->PopTool();
break;
}
}
if( evt->IsActivate() ) // now finish unconditionally
else if( evt->IsActivate() )
{
if( module )
cleanup();
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
frame()->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
@ -620,7 +637,6 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent )
controls->CaptureCursor( !!module );
}
m_frame->PopTool();
return 0;
}
@ -719,11 +735,26 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
cursorPos = controls->GetCursorPosition( !evt->Modifier( MD_ALT ) );
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() )
{
frame()->PopTool();
break;
}
else if( evt->IsActivate() )
{
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
else
{
frame()->PopTool();
break;
}
}
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
{
target->SetWidth( target->GetWidth() + WIDTH_STEP );
@ -772,7 +803,6 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent )
delete target;
view->Remove( &preview );
controls->SetSnapping( false );
m_frame->PopTool();
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -57,18 +57,27 @@ void PCB_TOOL_BASE::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer
aPlacer->m_frame = frame();
aPlacer->m_modifiers = 0;
if( aOptions & IPO_SINGLE_CLICK && !( aOptions & IPO_PROPERTIES ) )
auto makeNewItem = [&] ( VECTOR2I aPosition )
{
VECTOR2I cursorPos = controls()->GetCursorPosition();
newItem = aPlacer->CreateItem();
if( newItem )
{
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
newItem->SetPosition( (wxPoint) aPosition );
preview.Add( newItem.get() );
if( newItem->Type() == PCB_MODULE_T )
{
auto module = dyn_cast<MODULE*>( newItem.get() );
// modules have more drawable parts
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) );
}
}
}
};
if( aOptions & IPO_SINGLE_CLICK )
makeNewItem( controls()->GetCursorPosition() );
// Main loop: keep receiving events
while( TOOL_EVENT* evt = Wait() )
@ -76,36 +85,58 @@ void PCB_TOOL_BASE::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer
VECTOR2I cursorPos = controls()->GetCursorPosition();
aPlacer->m_modifiers = evt->Modifier();
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
auto cleanup = [&] ()
{
newItem = nullptr;
preview.Clear();
view()->Update( &preview );
controls()->SetAutoPan( false );
controls()->CaptureCursor( false );
controls()->ShowCursor( true );
};
if( evt->IsCancelInteractive() )
{
if( aOptions & IPO_SINGLE_CLICK )
{
cleanup();
frame()->PopTool();
break;
}
else if( newItem )
cleanup();
else
{
frame()->PopTool();
break;
}
}
else if( evt->IsActivate() )
{
if( newItem )
cleanup();
if( evt->IsPointEditor() )
{
// Delete the old item and have another try
newItem = nullptr;
preview.Clear();
controls()->SetAutoPan( false );
controls()->CaptureCursor( false );
controls()->ShowCursor( true );
if( aOptions & IPO_SINGLE_CLICK )
break;
// don't exit (the point editor runs in the background)
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
else if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
break;
}
if( evt->IsActivate() ) // now finish unconditionally
else
{
frame()->PopTool();
break;
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !newItem )
{
// create the item if possible
newItem = aPlacer->CreateItem();
makeNewItem( cursorPos );
// no item created, so wait for another click
if( !newItem )
@ -113,18 +144,6 @@ void PCB_TOOL_BASE::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer
controls()->CaptureCursor( true );
controls()->SetAutoPan( true );
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
preview.Add( newItem.get() );
if( newItem->Type() == PCB_MODULE_T )
{
auto module = dyn_cast<MODULE*>( newItem.get() );
// modules have more drawable parts
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) );
}
}
else
{
@ -137,14 +156,7 @@ void PCB_TOOL_BASE::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer
continue;
}
preview.Remove( newItem.get() );
if( newItem->Type() == PCB_MODULE_T )
{
auto module = dyn_cast<MODULE*>( newItem.get() );
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) );
}
preview.Clear();
newItem.release();
commit.Push( aCommitMessage );
@ -155,18 +167,8 @@ void PCB_TOOL_BASE::doInteractiveItemPlacement( INTERACTIVE_PLACER_BASE* aPlacer
if( !( aOptions & IPO_REPEAT ) )
break;
if( aOptions & IPO_SINGLE_CLICK && !( aOptions & IPO_PROPERTIES ) )
{
VECTOR2I pos = controls()->GetCursorPosition();
newItem = aPlacer->CreateItem();
if( newItem )
{
newItem->SetPosition( wxPoint( pos.x, pos.y ) );
preview.Add( newItem.get() );
}
}
if( aOptions & IPO_SINGLE_CLICK )
makeNewItem( controls()->GetCursorPosition() );
}
}
else if( evt->IsClick( BUT_RIGHT ) )

View File

@ -109,9 +109,8 @@ protected:
enum INTERACTIVE_PLACEMENT_OPTIONS {
IPO_ROTATE = 1,
IPO_FLIP = 2,
IPO_PROPERTIES = 4,
IPO_SINGLE_CLICK = 8,
IPO_REPEAT = 16
IPO_SINGLE_CLICK = 4,
IPO_REPEAT = 8
};

View File

@ -100,7 +100,7 @@ int PCBNEW_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( m_cancelHandler )
{

View File

@ -338,7 +338,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
grid.SetUseGrid( !evt->Modifier( MD_ALT ) );
controls->SetSnapping( !evt->Modifier( MD_ALT ) );
if( !m_editPoints || TOOL_EVT_UTILS::IsSelectionEvent( *evt ) )
if( !m_editPoints || evt->IsSelectionEvent() )
break;
if ( !inDrag )
@ -387,12 +387,15 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
m_refill = true;
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
else if( evt->IsCancelInteractive() || evt->IsActivate() )
{
if( inDrag ) // Restore the last change
commit.Revert();
else if( evt->IsCancelInteractive() )
break;
break;
if( evt->IsActivate() && !evt->IsMoveTool() )
break;
}
else

View File

@ -515,7 +515,7 @@ bool SELECTION_TOOL::selectMultiple()
while( TOOL_EVENT* evt = Wait() )
{
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
if( evt->IsCancelInteractive() || evt->IsActivate() )
{
cancelled = true;
break;

View File

@ -295,8 +295,9 @@ static void CheckInvalidsMatchExpected( BOARD& aBoard,
const std::vector<COURTYARD_INVALID_INFO>& aExpInvalids )
{
KI_TEST::CheckUnorderedMatches( aExpInvalids, aMarkers,
[&]( const COURTYARD_INVALID_INFO& aInvalid,
const std::unique_ptr<MARKER_PCB>& aMarker ) {
[&]( const COURTYARD_INVALID_INFO& aInvalid,
const std::unique_ptr<MARKER_PCB>& aMarker )
{
return InvalidMatchesExpected( aBoard, *aMarker, aInvalid );
} );
}