Few improvements to the GAL router:

- missing 'break track' functionality
- 'drag 45 degree' and 'drag free angle' context menu shorcuts, both in the router tool and in the default context menu
- bugfix: length tuner tool can now be used again

Fixes: lp:1708386
* https://bugs.launchpad.net/kicad/+bug/1708386

Fixes: lp:1708402
* https://bugs.launchpad.net/kicad/+bug/1708402
This commit is contained in:
Tomasz Włostowski 2017-08-03 17:53:07 +02:00
parent 9aaea050b9
commit 2d9ab80b4e
18 changed files with 425 additions and 205 deletions

View File

@ -109,10 +109,6 @@ LENGTH_TUNER_TOOL::~LENGTH_TUNER_TOOL()
void LENGTH_TUNER_TOOL::Reset( RESET_REASON aReason )
{
TOOL_BASE::Reset( aReason );
Go( &LENGTH_TUNER_TOOL::TuneSingleTrace, PCB_ACTIONS::routerActivateTuneSingleTrace.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::TuneDiffPair, PCB_ACTIONS::routerActivateTuneDiffPair.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::TuneDiffPairSkew, PCB_ACTIONS::routerActivateTuneDiffPairSkew.MakeEvent() );
}
@ -132,14 +128,14 @@ void LENGTH_TUNER_TOOL::performTuning()
{
if( m_startItem )
{
m_frame->SetActiveLayer( ToLAYER_ID ( m_startItem->Layers().Start() ) );
frame()->SetActiveLayer( ToLAYER_ID ( m_startItem->Layers().Start() ) );
if( m_startItem->Net() >= 0 )
highlightNet( true, m_startItem->Net() );
}
m_ctls->ForceCursorPosition( false );
m_ctls->SetAutoPan( true );
controls()->ForceCursorPosition( false );
controls()->SetAutoPan( true );
if( !m_router->StartRouting( m_startSnapPoint, m_startItem, 0 ) )
{
@ -155,7 +151,7 @@ void LENGTH_TUNER_TOOL::performTuning()
VECTOR2I end( m_startSnapPoint );
PNS_TUNE_STATUS_POPUP statusPopup( m_frame );
PNS_TUNE_STATUS_POPUP statusPopup( frame() );
statusPopup.Popup();
m_router->Move( end, NULL );
@ -210,27 +206,31 @@ void LENGTH_TUNER_TOOL::performTuning()
int LENGTH_TUNER_TOOL::TuneSingleTrace( const TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Trace Length" ) );
frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Trace Length" ) );
return mainLoop( PNS::PNS_MODE_TUNE_SINGLE );
}
int LENGTH_TUNER_TOOL::TuneDiffPair( const TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Length" ) );
frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Length" ) );
return mainLoop( PNS::PNS_MODE_TUNE_DIFF_PAIR );
}
int LENGTH_TUNER_TOOL::TuneDiffPairSkew( const TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Skew" ) );
frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Skew" ) );
return mainLoop( PNS::PNS_MODE_TUNE_DIFF_PAIR_SKEW );
}
void LENGTH_TUNER_TOOL::setTransitions()
{
Go( &LENGTH_TUNER_TOOL::TuneSingleTrace, PCB_ACTIONS::routerActivateTuneSingleTrace.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::TuneDiffPair, PCB_ACTIONS::routerActivateTuneDiffPair.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::TuneDiffPairSkew, PCB_ACTIONS::routerActivateTuneDiffPairSkew.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::routerOptionsDialog, ACT_RouterOptions.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::meanderSettingsDialog, ACT_Settings.MakeEvent() );
}
@ -245,9 +245,9 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
m_router->SetMode( aMode );
m_ctls->SetSnapping( true );
m_ctls->ShowCursor( true );
m_frame->UndoRedoBlock( true );
controls()->SetSnapping( true );
controls()->ShowCursor( true );
frame()->UndoRedoBlock( true );
std::unique_ptr<TUNER_TOOL_MENU> ctxMenu( new TUNER_TOOL_MENU );
SetContextMenu( ctxMenu.get() );
@ -270,8 +270,8 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
}
}
m_frame->SetNoToolSelected();
m_frame->UndoRedoBlock( false );
frame()->SetNoToolSelected();
frame()->UndoRedoBlock( false );
// Store routing settings till the next invocation
m_savedSettings = m_router->Settings();
@ -283,7 +283,7 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
int LENGTH_TUNER_TOOL::routerOptionsDialog( const TOOL_EVENT& aEvent )
{
DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );
DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
if( settingsDlg.ShowModal() == wxID_OK )
{
@ -302,7 +302,7 @@ int LENGTH_TUNER_TOOL::meanderSettingsDialog( const TOOL_EVENT& aEvent )
return 0;
PNS::MEANDER_SETTINGS settings = placer->MeanderSettings();
DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( m_frame, settings, m_router->Mode() );
DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( frame(), settings, m_router->Mode() );
if( settingsDlg.ShowModal() )
placer->UpdateSettings( settings );

View File

@ -30,7 +30,7 @@ DRAGGER::DRAGGER( ROUTER* aRouter ) :
{
m_world = NULL;
m_lastNode = NULL;
m_mode = DRAG_SEGMENT;
m_mode = DM_SEGMENT;
m_draggedVia = NULL;
m_shove = NULL;
m_draggedSegmentIndex = 0;
@ -62,14 +62,31 @@ bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg )
m_lastValidDraggedLine = m_draggedLine;
m_lastValidDraggedLine.ClearSegmentLinks();
if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 )
m_mode = DRAG_CORNER;
else if( ( aP - aSeg->Seg().B ).EuclideanNorm() <= w2 )
auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
if( distA <= w2 )
{
m_mode = DM_CORNER;
}
else if( distB <= w2 )
{
m_draggedSegmentIndex++;
m_mode = DRAG_CORNER;
} else
m_mode = DRAG_SEGMENT;
m_mode = DM_CORNER;
}
else if ( m_freeAngleMode )
{
if( distB < distA )
{
m_draggedSegmentIndex++;
}
m_mode = DM_CORNER;
}
else
{
m_mode = DM_SEGMENT;
}
return true;
}
@ -79,7 +96,7 @@ bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia )
{
m_draggedVia = aVia;
m_initialVia = aVia;
m_mode = DRAG_VIA;
m_mode = DM_VIA;
VECTOR2I p0( aVia->Pos() );
JOINT* jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() );
@ -112,6 +129,7 @@ bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem )
m_lastNode = NULL;
m_draggedItems.Clear();
m_currentMode = Settings().Mode();
m_freeAngleMode = Settings().GetFreeAngleMode() || (m_mode & DM_FREE_ANGLE);
aStartItem->Unmark( MK_LOCKED );
@ -130,6 +148,10 @@ bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem )
}
}
void DRAGGER::SetMode( int aMode )
{
m_mode = aMode;
}
bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
{
@ -141,16 +163,16 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
switch( m_mode )
{
case DRAG_SEGMENT:
case DRAG_CORNER:
case DM_SEGMENT:
case DM_CORNER:
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
LINE dragged( m_draggedLine );
if( m_mode == DRAG_SEGMENT )
if( m_mode == DM_SEGMENT )
dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
else
dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
dragged.DragCorner( aP, m_draggedSegmentIndex, thresh, m_freeAngleMode );
m_lastNode = m_shove->CurrentNode()->Branch();
@ -165,7 +187,7 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
break;
}
case DRAG_VIA: // fixme...
case DM_VIA: // fixme...
{
m_lastNode = m_shove->CurrentNode()->Branch();
dumbDragVia( m_initialVia, m_lastNode, aP );
@ -205,7 +227,7 @@ void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP )
LINE origLine( *l );
LINE draggedLine( *l );
draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ) );
draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ), 0, m_freeAngleMode );
draggedLine.ClearSegmentLinks();
m_draggedItems.Add( draggedLine );
@ -229,13 +251,13 @@ bool DRAGGER::dragShove( const VECTOR2I& aP )
switch( m_mode )
{
case DRAG_SEGMENT:
case DRAG_CORNER:
case DM_SEGMENT:
case DM_CORNER:
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
LINE dragged( m_draggedLine );
if( m_mode == DRAG_SEGMENT )
if( m_mode == DM_SEGMENT )
dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
else
dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
@ -264,7 +286,7 @@ bool DRAGGER::dragShove( const VECTOR2I& aP )
break;
}
case DRAG_VIA:
case DM_VIA:
{
VIA* newVia;
SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, &newVia );
@ -305,6 +327,9 @@ bool DRAGGER::FixRoute()
bool DRAGGER::Drag( const VECTOR2I& aP )
{
if( m_freeAngleMode )
return dragMarkObstacles( aP );
switch( m_currentMode )
{
case RM_MarkObstacles:

View File

@ -97,12 +97,10 @@ public:
/// @copydoc ALGO_BASE::Logger()
virtual LOGGER* Logger() override;
void SetMode( int aDragMode );
private:
enum DragMode {
DRAG_CORNER = 0,
DRAG_SEGMENT,
DRAG_VIA
};
bool dragMarkObstacles( const VECTOR2I& aP );
bool dragShove(const VECTOR2I& aP );
@ -112,7 +110,7 @@ private:
NODE* m_world;
NODE* m_lastNode;
DragMode m_mode;
int m_mode;
LINE m_draggedLine;
VIA* m_draggedVia;
LINE m_lastValidDraggedLine;
@ -123,6 +121,7 @@ private:
ITEM_SET m_origViaConnections;
VIA* m_initialVia;
ITEM_SET m_draggedItems;
bool m_freeAngleMode;
};
}

View File

@ -405,7 +405,7 @@ SHAPE_LINE_CHAIN dragCornerInternal( const SHAPE_LINE_CHAIN& aOrigin, const VECT
}
void LINE::DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
void LINE::dragCorner45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
{
SHAPE_LINE_CHAIN path;
@ -429,6 +429,37 @@ void LINE::DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
}
void LINE::dragCornerFree( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
{
m_line.Point( aIndex ) = aP;
m_line.Simplify();
}
void LINE::DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold, bool aFreeAngle )
{
if( aFreeAngle )
{
dragCornerFree ( aP, aIndex, aSnappingThreshold );
}
else
{
dragCorner45 ( aP, aIndex, aSnappingThreshold );
}
}
void LINE::DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold, bool aFreeAngle )
{
if( aFreeAngle )
{
assert( false );
}
else
{
dragSegment45 ( aP, aIndex, aSnappingThreshold );
}
}
VECTOR2I LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I& aP,
int aIndex, int aThreshold ) const
{
@ -517,7 +548,7 @@ VECTOR2I LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VEC
}
void LINE::DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
void LINE::dragSegment45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
{
SHAPE_LINE_CHAIN path( m_line );
VECTOR2I target( aP );

View File

@ -256,8 +256,8 @@ public:
virtual void Unmark( int aMarker = -1 ) override;
virtual int Marker() const override;
void DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 );
void DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 );
void DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0, bool aFreeAngle = false );
void DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0, bool aFreeAngle = false );
void SetRank( int aRank ) override;
int Rank() const override;
@ -268,6 +268,12 @@ public:
OPT_BOX2I ChangedArea( const LINE* aOther ) const;
private:
void dragSegment45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold );
void dragCorner45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold );
void dragSegmentFree( const VECTOR2I& aP, int aIndex, int aSnappingThreshold );
void dragCornerFree( const VECTOR2I& aP, int aIndex, int aSnappingThreshold );
VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP,
int aIndex, int aThreshold) const;

View File

@ -800,18 +800,18 @@ NODE* LINE_PLACER::CurrentNode( bool aLoopsRemoved ) const
}
void LINE_PLACER::splitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP )
bool LINE_PLACER::SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP )
{
if( !aSeg )
return;
return false;
if( !aSeg->OfKind( ITEM::SEGMENT_T ) )
return;
return false;
JOINT* jt = aNode->FindJoint( aP, aSeg );
if( jt && jt->LinkCount() >= 1 )
return;
return false;
SEGMENT* s_old = static_cast<SEGMENT*>( aSeg );
@ -826,6 +826,8 @@ void LINE_PLACER::splitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I
aNode->Remove( s_old );
aNode->Add( std::move( s_new[0] ), true );
aNode->Add( std::move( s_new[1] ), true );
return true;
}
@ -901,7 +903,7 @@ void LINE_PLACER::initPlacement()
world->KillChildren();
NODE* rootNode = world->Branch();
splitAdjacentSegments( rootNode, m_startItem, m_currentStart );
SplitAdjacentSegments( rootNode, m_startItem, m_currentStart );
setWorld( rootNode );
@ -950,7 +952,7 @@ bool LINE_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
if( eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && current.SegmentCount() )
{
splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
SplitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
if( Settings().RemoveLoops() )
removeLoops( m_lastNode, current );

View File

@ -189,6 +189,14 @@ public:
LOGGER* Logger() override;
/**
* Function SplitAdjacentSegments()
*
* Checks if point aP lies on segment aSeg. If so, splits the segment in two,
* forming a joint at aP and stores updated topology in node aNode.
*/
bool SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP );
private:
/**
@ -234,14 +242,6 @@ private:
*/
void setInitialDirection( const DIRECTION_45& aDirection );
/**
* Function splitAdjacentSegments()
*
* Checks if point aP lies on segment aSeg. If so, splits the segment in two,
* forming a joint at aP and stores updated topology in node aNode.
*/
void splitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP );
/**
* Function removeLoops()
*

View File

@ -124,12 +124,19 @@ const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP )
}
bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem )
bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem, int aDragMode )
{
if( aDragMode & DM_FREE_ANGLE )
m_forceMarkObstaclesMode = true;
else
m_forceMarkObstaclesMode = false;
if( !aStartItem || aStartItem->OfKind( ITEM::SOLID_T ) )
return false;
m_dragger.reset( new DRAGGER( this ) );
m_dragger->SetMode( aDragMode );
m_dragger->SetWorld( m_world.get() );
m_dragger->SetDebugDecorator ( m_iface->GetDebugDecorator () );
@ -148,6 +155,8 @@ bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem )
bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
{
m_forceMarkObstaclesMode = false;
switch( m_mode )
{
case PNS_MODE_ROUTE_SINGLE:
@ -262,7 +271,7 @@ void ROUTER::updateView( NODE* aNode, ITEM_SET& aCurrent )
if( !aNode )
return;
if( Settings().Mode() == RM_MarkObstacles )
if( Settings().Mode() == RM_MarkObstacles || m_forceMarkObstaclesMode )
markViolations( aNode, aCurrent, removed );
aNode->GetUpdatedItems( removed, added );
@ -486,4 +495,21 @@ void ROUTER::SetInterface( ROUTER_IFACE *aIface )
m_iface->SetRouter( this );
}
void ROUTER::BreakSegment( ITEM *aItem, const VECTOR2I& aP )
{
NODE *node = m_world->Branch();
LINE_PLACER placer( this );
if ( placer.SplitAdjacentSegments( node, aItem, aP ) )
{
CommitRouting( node );
}
else
{
delete node;
}
}
}

View File

@ -69,6 +69,14 @@ enum ROUTER_MODE {
PNS_MODE_TUNE_DIFF_PAIR_SKEW
};
enum DRAG_MODE
{
DM_CORNER = 0x1,
DM_SEGMENT = 0x2,
DM_VIA = 0x4,
DM_FREE_ANGLE = 0x8,
DM_ANY = 0x7
};
/**
* Class ROUTER
*
@ -126,6 +134,7 @@ public:
bool StartRouting( const VECTOR2I& aP, ITEM* aItem, int aLayer );
void Move( const VECTOR2I& aP, ITEM* aItem );
bool FixRoute( const VECTOR2I& aP, ITEM* aItem );
void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
void StopRouting();
@ -161,7 +170,7 @@ public:
const ITEM_SET QueryHoverItems( const VECTOR2I& aP );
const VECTOR2I SnapToItem( ITEM* aItem, VECTOR2I aP, bool& aSplitsSegment );
bool StartDragging( const VECTOR2I& aP, ITEM* aItem );
bool StartDragging( const VECTOR2I& aP, ITEM* aItem, int aDragMode = DM_ANY );
void SetIterLimit( int aX ) { m_iterLimit = aX; }
int GetIterLimit() const { return m_iterLimit; };
@ -253,6 +262,7 @@ private:
bool m_showInterSteps;
int m_snapshotIter;
bool m_violation;
bool m_forceMarkObstaclesMode = false;
ROUTING_SETTINGS m_settings;
SIZES_SETTINGS m_sizes;

View File

@ -45,6 +45,8 @@ ROUTING_SETTINGS::ROUTING_SETTINGS()
m_canViolateDRC = false;
m_freeAngleMode = false;
m_inlineDragEnabled = false;
m_snapToTracks = false;
m_snapToPads = false;
}

View File

@ -136,6 +136,12 @@ public:
void SetInlineDragEnabled ( bool aEnable ) { m_inlineDragEnabled = aEnable; }
bool InlineDragEnabled() const { return m_inlineDragEnabled; }
void SetSnapToTracks( bool aSnap ) { m_snapToTracks = aSnap; }
void SetSnapToPads( bool aSnap ) { m_snapToPads = aSnap; }
bool GetSnapToTracks() const { return m_snapToTracks; }
bool GetSnapToPads() const { return m_snapToPads; }
private:
bool m_shoveVias;
bool m_startDiagonal;
@ -148,6 +154,8 @@ private:
bool m_canViolateDRC;
bool m_freeAngleMode;
bool m_inlineDragEnabled;
bool m_snapToTracks;
bool m_snapToPads;
PNS_MODE m_routingMode;
PNS_OPTIMIZATION_EFFORT m_optimizerEffort;

View File

@ -68,7 +68,7 @@ TOOL_ACTION TOOL_BASE::ACT_RouterOptions( "pcbnew.InteractiveRouter.RouterOption
TOOL_BASE::TOOL_BASE( const std::string& aToolName ) :
TOOL_INTERACTIVE( aToolName )
PCB_TOOL( aToolName )
{
m_gridHelper = nullptr;
m_iface = nullptr;
@ -78,10 +78,6 @@ TOOL_BASE::TOOL_BASE( const std::string& aToolName ) :
m_startLayer = 0;
m_endItem = nullptr;
m_frame = nullptr;
m_ctls = nullptr;
m_board = nullptr;
m_gridHelper = nullptr;
}
@ -101,23 +97,19 @@ void TOOL_BASE::Reset( RESET_REASON aReason )
delete m_iface;
delete m_router;
m_frame = getEditFrame<PCB_EDIT_FRAME>();
m_ctls = getViewControls();
m_board = getModel<BOARD>();
m_iface = new PNS_KICAD_IFACE;
m_iface->SetBoard( m_board );
m_iface->SetBoard( board() );
m_iface->SetView( getView() );
m_iface->SetHostFrame( m_frame );
m_iface->SetHostFrame( frame() );
m_router = new ROUTER;
m_router->SetInterface(m_iface);
m_router->SetInterface( m_iface );
m_router->ClearWorld();
m_router->SyncWorld();
m_router->LoadSettings( m_savedSettings );
m_router->UpdateSizes( m_savedSizes );
m_gridHelper = new GRID_HELPER( m_frame );
m_gridHelper = new GRID_HELPER( frame() );
}
@ -206,11 +198,38 @@ void TOOL_BASE::highlightNet( bool aEnabled, int aNetcode )
getView()->UpdateAllLayersColor();
}
bool TOOL_BASE::checkSnap( ITEM *aItem )
{
bool doSnap = false;
// Sync PNS engine settings with the general PCB editor options. I know the code below is awful, but...
auto& pnss = m_router->Settings();
const auto& gens = frame()->Settings();
pnss.SetSnapToTracks( false );
pnss.SetSnapToPads( false );
if( gens.m_magneticPads == CAPTURE_CURSOR_IN_TRACK_TOOL || gens.m_magneticPads == CAPTURE_ALWAYS )
pnss.SetSnapToPads( true );
if( gens.m_magneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL || gens.m_magneticTracks == CAPTURE_ALWAYS )
pnss.SetSnapToTracks( true );
if( aItem )
{
if( ( aItem->OfKind( ITEM::VIA_T ) || aItem->OfKind( ITEM::SEGMENT_T ) ) && pnss.GetSnapToTracks() )
doSnap = true;
else if( aItem->OfKind( ITEM::SOLID_T ) && pnss.GetSnapToPads() )
doSnap = true;
}
return doSnap;
}
void TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent )
{
int tl = getView()->GetTopLayer();
VECTOR2I cp = m_ctls->GetCursorPosition();
VECTOR2I cp = controls()->GetCursorPosition();
VECTOR2I p;
bool snapEnabled = true;
@ -231,20 +250,21 @@ void TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent )
m_startItem = nullptr;
m_startSnapPoint = snapToItem( snapEnabled, m_startItem, p );
m_ctls->ForceCursorPosition( true, m_startSnapPoint );
controls()->ForceCursorPosition( true, checkSnap( m_startItem ) ? m_startSnapPoint : p );
}
void TOOL_BASE::updateEndItem( const TOOL_EVENT& aEvent )
{
VECTOR2I p = m_ctls->GetMousePosition();
VECTOR2I p = controls()->GetMousePosition();
int layer;
bool snapEnabled = !aEvent.Modifier( MD_SHIFT );
if( m_router->GetCurrentNets().empty() || m_router->GetCurrentNets().front() < 0 )
{
m_endSnapPoint = snapToItem( snapEnabled, nullptr, p );
m_ctls->ForceCursorPosition( true, m_endSnapPoint );
controls()->ForceCursorPosition( true, m_endSnapPoint );
m_endItem = nullptr;
return;
@ -267,10 +287,16 @@ void TOOL_BASE::updateEndItem( const TOOL_EVENT& aEvent )
break;
}
VECTOR2I cursorPos = snapToItem( snapEnabled, endItem, p );
m_ctls->ForceCursorPosition( true, cursorPos );
m_endItem = endItem;
m_endSnapPoint = cursorPos;
if( checkSnap( endItem ) )
{
VECTOR2I cursorPos = snapToItem( snapEnabled, endItem, p );
controls()->ForceCursorPosition( true, checkSnap( endItem ) ? cursorPos : p );
m_endItem = endItem;
m_endSnapPoint = cursorPos;
} else {
m_endItem = nullptr;
m_endSnapPoint = p;
}
if( m_endItem )
{

View File

@ -41,7 +41,7 @@ class PNS_TUNE_STATUS_POPUP;
namespace PNS {
class APIEXPORT TOOL_BASE : public TOOL_INTERACTIVE
class APIEXPORT TOOL_BASE : public PCB_TOOL
{
public:
static TOOL_ACTION ACT_RouterOptions;
@ -51,14 +51,10 @@ public:
virtual void Reset( RESET_REASON aReason ) override;
const ROUTING_SETTINGS& PNSSettings() const
{
return m_savedSettings;
}
ROUTER* Router() const;
protected:
bool checkSnap( ITEM* aItem );
const VECTOR2I snapToItem( bool aEnabled, ITEM* aItem, VECTOR2I aP);
virtual ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
virtual void highlightNet( bool aEnabled, int aNetcode = -1 );
@ -77,9 +73,6 @@ protected:
ITEM* m_endItem;
VECTOR2I m_endSnapPoint;
PCB_EDIT_FRAME* m_frame;
KIGFX::VIEW_CONTROLS* m_ctls;
BOARD* m_board;
GRID_HELPER* m_gridHelper;
PNS_KICAD_IFACE* m_iface;
ROUTER* m_router;

View File

@ -112,10 +112,28 @@ TOOL_ACTION PCB_ACTIONS::routerActivateTuneDiffPairSkew( "pcbnew.LengthTuner.Tun
_( "Tune skew of a differential pair" ), "", NULL, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::routerInlineDrag( "pcbnew.InteractiveRouter.InlineDrag",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ),
AS_CONTEXT, 0,
_( "Drag Track/Via" ), _( "Drags tracks and vias without breaking connections" ),
drag_xpm );
TOOL_ACTION PCB_ACTIONS::breakTrack( "pcbnew.InteractiveRouter.BreakTrack",
AS_GLOBAL, 0,
_( "Break Track" ),
_( "Splits the track segment into two segments connected at the cursor position." ),
break_line_xpm );
TOOL_ACTION PCB_ACTIONS::drag45Degree( "pcbnew.InteractiveRouter.Drag45Degree",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ),
_( "Drag (45 degree mode)" ),
_( "todo" ),
drag_segment_withslope_xpm );
TOOL_ACTION PCB_ACTIONS::dragFreeAngle( "pcbnew.InteractiveRouter.DragFreeAngle",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_ITEM ),
_( "Drag (free angle)" ),
_( "todo" ),
move_xpm );
static const TOOL_ACTION ACT_NewTrack( "pcbnew.InteractiveRouter.NewTrack", AS_CONTEXT,
TOOL_ACTION::LegacyHotKey( HK_ADD_NEW_TRACK ),
_( "New Track" ), _( "Starts laying a new track." ), add_tracks_xpm );
@ -180,7 +198,6 @@ static const TOOL_ACTION ACT_SetDpDimensions( "pcbnew.InteractiveRouter.SetDpDim
_( "Sets the width and gap of the currently routed differential pair." ),
ps_diff_pair_tune_length_xpm );
ROUTER_TOOL::ROUTER_TOOL() :
TOOL_BASE( "pcbnew.InteractiveRouter" )
{
@ -300,6 +317,11 @@ public:
Add( ACT_NewTrack );
Add( ACT_EndTrack );
Add( PCB_ACTIONS::breakTrack );
Add( PCB_ACTIONS::drag45Degree );
Add( PCB_ACTIONS::dragFreeAngle );
// Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry.
Add( ACT_PlaceThroughVia );
Add( ACT_PlaceBlindVia );
@ -349,12 +371,6 @@ ROUTER_TOOL::~ROUTER_TOOL()
bool ROUTER_TOOL::Init()
{
// Track & via dragging menu entry
auto selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
menu.AddItem( PCB_ACTIONS::routerInlineDrag, SELECTION_CONDITIONS::Count( 1 )
&& SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_VIA_T, EOT } ) );
m_savedSettings.Load( GetSettings() );
return true;
}
@ -379,10 +395,10 @@ int ROUTER_TOOL::getDefaultWidth( int aNetCode )
void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth,
int& aViaDiameter, int& aViaDrill )
{
BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings();
BOARD_DESIGN_SETTINGS &bds = board()->GetDesignSettings();
NETCLASSPTR netClass;
NETINFO_ITEM* ni = m_board->FindNet( aNetCode );
NETINFO_ITEM* ni = board()->FindNet( aNetCode );
if( ni )
{
@ -436,7 +452,7 @@ int ROUTER_TOOL::getStartLayer( const PNS::ITEM* aItem )
void ROUTER_TOOL::switchLayerOnViaPlacement()
{
int al = m_frame->GetActiveLayer();
int al = frame()->GetActiveLayer();
int cl = m_router->GetCurrentLayer();
if( cl != al )
@ -450,7 +466,7 @@ void ROUTER_TOOL::switchLayerOnViaPlacement()
newLayer = m_router->Sizes().GetLayerTop();
m_router->SwitchLayer( *newLayer );
m_frame->SetActiveLayer( ToLAYER_ID( *newLayer ) );
frame()->SetActiveLayer( ToLAYER_ID( *newLayer ) );
}
@ -486,12 +502,12 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent )
VIATYPE_T viaType = getViaTypeFromFlags( actViaFlags );
const bool selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
BOARD_DESIGN_SETTINGS& bds = board()->GetDesignSettings();
const int layerCount = bds.GetCopperLayerCount();
int currentLayer = m_router->GetCurrentLayer();
PCB_LAYER_ID pairTop = m_frame->GetScreen()->m_Route_Layer_TOP;
PCB_LAYER_ID pairBottom = m_frame->GetScreen()->m_Route_Layer_BOTTOM;
PCB_LAYER_ID pairTop = frame()->GetScreen()->m_Route_Layer_TOP;
PCB_LAYER_ID pairBottom = frame()->GetScreen()->m_Route_Layer_BOTTOM;
PNS::SIZES_SETTINGS sizes = m_router->Sizes();
@ -502,7 +518,7 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent )
{
wxPoint dlgPosition = wxGetMousePosition();
targetLayer = m_frame->SelectLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
targetLayer = frame()->SelectLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
LSET::AllNonCuMask(), dlgPosition );
}
@ -514,27 +530,27 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent )
// Cannot place microvias or blind vias if not allowed (obvious)
if( ( viaType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
{
DisplayError( m_frame, _( "Blind/buried vias have to be enabled in the design settings." ) );
DisplayError( frame(), _( "Blind/buried vias have to be enabled in the design settings." ) );
return false;
}
if( ( viaType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
{
DisplayError( m_frame, _( "Microvias have to be enabled in the design settings." ) );
DisplayError( frame(), _( "Microvias have to be enabled in the design settings." ) );
return false;
}
// Can only place through vias on 2-layer boards
if( ( viaType != VIA_THROUGH ) && ( layerCount <= 2 ) )
{
DisplayError( m_frame, _( "Only through vias are allowed on 2 layer boards." ) );
DisplayError( frame(), _( "Only through vias are allowed on 2 layer boards." ) );
return false;
}
// Can only place microvias if we're on an outer layer, or directly adjacent to one
if( ( viaType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount - 2 ) )
{
DisplayError( m_frame, _( "Microvias can be placed only between the outer layers " \
DisplayError( frame(), _( "Microvias can be placed only between the outer layers " \
"(F.Cu/B.Cu) and the ones directly adjacent to them." ) );
return false;
}
@ -638,11 +654,11 @@ bool ROUTER_TOOL::prepareInteractive()
if( !IsCopperLayer( routingLayer ) )
{
DisplayError( m_frame, _( "Tracks on Copper layers only" ) );
DisplayError( frame(), _( "Tracks on Copper layers only" ) );
return false;
}
m_frame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
frame()->SetActiveLayer( ToLAYER_ID( routingLayer ) );
// fixme: switch on invisible layer
@ -652,24 +668,24 @@ bool ROUTER_TOOL::prepareInteractive()
{
highlightNet( true, m_startItem->Net() );
// Update track width and via size shown in main toolbar comboboxes
m_frame->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() );
frame()->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() );
}
else
m_frame->SetCurrentNetClass( NETCLASS::Default );
frame()->SetCurrentNetClass( NETCLASS::Default );
m_ctls->ForceCursorPosition( false );
m_ctls->SetAutoPan( true );
controls()->ForceCursorPosition( false );
controls()->SetAutoPan( true );
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
sizes.Init( m_board, m_startItem );
sizes.AddLayerPair( m_frame->GetScreen()->m_Route_Layer_TOP,
m_frame->GetScreen()->m_Route_Layer_BOTTOM );
sizes.Init( board(), m_startItem );
sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
frame()->GetScreen()->m_Route_Layer_BOTTOM );
m_router->UpdateSizes( sizes );
if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
{
DisplayError( m_frame, m_router->FailureReason() );
DisplayError( frame(), m_router->FailureReason() );
highlightNet( false );
return false;
}
@ -677,7 +693,7 @@ bool ROUTER_TOOL::prepareInteractive()
m_endItem = NULL;
m_endSnapPoint = m_startSnapPoint;
m_frame->UndoRedoBlock( true );
frame()->UndoRedoBlock( true );
return true;
}
@ -687,9 +703,9 @@ bool ROUTER_TOOL::finishInteractive()
{
m_router->StopRouting();
m_ctls->SetAutoPan( false );
m_ctls->ForceCursorPosition( false );
m_frame->UndoRedoBlock( false );
controls()->SetAutoPan( false );
controls()->ForceCursorPosition( false );
frame()->UndoRedoBlock( false );
highlightNet( false );
return true;
@ -724,7 +740,7 @@ void ROUTER_TOOL::performRouting()
switchLayerOnViaPlacement();
// Synchronize the indicated layer
m_frame->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) );
frame()->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) );
updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem );
m_startItem = NULL;
@ -737,7 +753,7 @@ void ROUTER_TOOL::performRouting()
}
else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
{
m_router->SwitchLayer( m_frame->GetActiveLayer() );
m_router->SwitchLayer( frame()->GetActiveLayer() );
updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem ); // refresh
}
@ -763,7 +779,7 @@ int ROUTER_TOOL::DpDimensionsDialog( const TOOL_EVENT& aEvent )
Activate();
PNS::SIZES_SETTINGS sizes = m_router->Sizes();
DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( m_frame, sizes );
DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
if( settingsDlg.ShowModal() )
{
@ -779,7 +795,7 @@ int ROUTER_TOOL::SettingsDialog( const TOOL_EVENT& aEvent )
{
Activate();
DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );
DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
if( settingsDlg.ShowModal() )
m_savedSettings = m_router->Settings();
@ -813,17 +829,24 @@ void ROUTER_TOOL::setTransitions()
int ROUTER_TOOL::RouteSingleTrace( const TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Route Track" ) );
frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Route Track" ) );
return mainLoop( PNS::PNS_MODE_ROUTE_SINGLE );
}
int ROUTER_TOOL::RouteDiffPair( const TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Router Differential Pair" ) );
frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Router Differential Pair" ) );
return mainLoop( PNS::PNS_MODE_ROUTE_DIFF_PAIR );
}
void ROUTER_TOOL::breakTrack()
{
if ( m_startItem->OfKind( PNS::ITEM::SEGMENT_T ) )
{
m_router->BreakSegment( m_startItem, m_startSnapPoint );
}
}
int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
{
@ -837,7 +860,7 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
m_router->SetMode( aMode );
m_ctls->ShowCursor( true );
controls()->ShowCursor( true );
m_startSnapPoint = getViewControls()->GetCursorPosition();
@ -863,12 +886,25 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
{
updateStartItem( *evt );
}
else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
{
performDragging( PNS::DM_ANY | PNS::DM_FREE_ANGLE );
}
else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
{
performDragging( PNS::DM_ANY );
}
else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
{
updateStartItem( *evt );
breakTrack( );
}
else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &ACT_NewTrack ) )
{
updateStartItem( *evt );
if( evt->Modifier( MD_CTRL ) )
performDragging();
performDragging( PNS::DM_ANY );
else
performRouting();
}
@ -897,17 +933,17 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
}
void ROUTER_TOOL::performDragging()
void ROUTER_TOOL::performDragging( int aMode )
{
VIEW_CONTROLS* ctls = getViewControls();
if( m_startItem && m_startItem->IsLocked() )
{
if( !IsOK( m_frame, _( "The item is locked. Do you want to continue?" ) ) )
if( !IsOK( frame(), _( "The item is locked. Do you want to continue?" ) ) )
return;
}
bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem );
bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
if( !dragStarted )
return;
@ -917,7 +953,7 @@ void ROUTER_TOOL::performDragging()
ctls->SetAutoPan( true );
m_frame->UndoRedoBlock( true );
frame()->UndoRedoBlock( true );
while( OPT_TOOL_EVENT evt = Wait() )
{
@ -945,7 +981,7 @@ void ROUTER_TOOL::performDragging()
m_startItem = NULL;
m_frame->UndoRedoBlock( false );
frame()->UndoRedoBlock( false );
ctls->SetAutoPan( false );
ctls->ForceCursorPosition( false );
highlightNet( false );
@ -974,21 +1010,23 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
if( m_startItem && m_startItem->IsLocked() )
{
if( !IsOK( m_frame, _( "The item is locked. Do you want to continue?" ) ) )
if( !IsOK( frame(), _( "The item is locked. Do you want to continue?" ) ) )
return false;
}
VECTOR2I p0 = m_ctls->GetCursorPosition();
VECTOR2I p0 = controls()->GetCursorPosition();
bool dragStarted = m_router->StartDragging( p0, m_startItem );
int dragMode = aEvent.Parameter<int64_t> ();
bool dragStarted = m_router->StartDragging( p0, m_startItem, dragMode );
if( !dragStarted )
return 0;
m_ctls->ShowCursor( true );
m_ctls->ForceCursorPosition( false );
m_ctls->SetAutoPan( true );
m_frame->UndoRedoBlock( true );
controls()->ShowCursor( true );
controls()->ForceCursorPosition( false );
controls()->SetAutoPan( true );
frame()->UndoRedoBlock( true );
while( OPT_TOOL_EVENT evt = Wait() )
{
@ -1012,9 +1050,9 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
if( m_router->RoutingInProgress() )
m_router->StopRouting();
m_ctls->SetAutoPan( false );
m_ctls->ShowCursor( false );
m_frame->UndoRedoBlock( false );
controls()->SetAutoPan( false );
controls()->ShowCursor( false );
frame()->UndoRedoBlock( false );
return 0;
}
@ -1022,8 +1060,8 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
int ROUTER_TOOL::CustomTrackWidthDialog( const TOOL_EVENT& aEvent )
{
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
DIALOG_TRACK_VIA_SIZE sizeDlg( m_frame, bds );
BOARD_DESIGN_SETTINGS& bds = board()->GetDesignSettings();
DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
if( sizeDlg.ShowModal() )
{
@ -1038,7 +1076,7 @@ int ROUTER_TOOL::CustomTrackWidthDialog( const TOOL_EVENT& aEvent )
int ROUTER_TOOL::onTrackViaSizeChanged( const TOOL_EVENT& aEvent )
{
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
sizes.ImportCurrent( m_board->GetDesignSettings() );
sizes.ImportCurrent( board()->GetDesignSettings() );
m_router->UpdateSizes( sizes );
return 0;

View File

@ -51,7 +51,8 @@ private:
int getDefaultWidth( int aNetCode );
void performRouting();
void performDragging();
void performDragging( int aMode = PNS::DM_ANY );
void breakTrack();
void getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill );
void handleCommonEvents( const TOOL_EVENT& evt );

View File

@ -91,6 +91,10 @@ TOOL_ACTION PCB_ACTIONS::globalEditPads( "pcbnew.InteractiveEdit.globalPadEdit",
_( "Changes pad properties globally." ), push_pad_settings_xpm );
TOOL_ACTION PCB_ACTIONS::editActivate( "pcbnew.InteractiveEdit",
AS_GLOBAL, 0,
_( "Edit Activate" ), _( "" ), move_xpm, AF_ACTIVATE );
TOOL_ACTION PCB_ACTIONS::move( "pcbnew.InteractiveEdit.move",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_MOVE_ITEM ),
_( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE );
@ -157,7 +161,6 @@ TOOL_ACTION PCB_ACTIONS::measureTool( "pcbnew.InteractiveEdit.measureTool",
_( "Measuring tool" ), _( "Interactively measure distance between points" ),
nullptr, AF_ACTIVATE );
static wxPoint getAnchorPoint( const SELECTION &selection, const MOVE_PARAMETERS &params )
{
wxPoint anchorPoint;
@ -270,13 +273,17 @@ bool EDIT_TOOL::Init()
// Add context menu entries that are displayed when selection tool is active
CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu();
menu.AddItem( PCB_ACTIONS::editActivate, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::move, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::drag45Degree, SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) );
menu.AddItem( PCB_ACTIONS::dragFreeAngle, SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) );
menu.AddItem( PCB_ACTIONS::rotateCcw, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::rotateCw, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::flip, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::remove, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::properties, SELECTION_CONDITIONS::Count( 1 )
|| SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) );
menu.AddItem( PCB_ACTIONS::moveExact, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::positionRelative, SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::duplicate, SELECTION_CONDITIONS::NotEmpty );
@ -298,26 +305,39 @@ bool EDIT_TOOL::Init()
}
bool EDIT_TOOL::invokeInlineRouter()
bool EDIT_TOOL::invokeInlineRouter( int aDragMode )
{
TRACK* track = uniqueSelected<TRACK>();
VIA* via = uniqueSelected<VIA>();
if( track || via )
{
ROUTER_TOOL* theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
auto theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
assert( theRouter );
if( !theRouter->PNSSettings().InlineDragEnabled() )
if( !theRouter->Router()->Settings().InlineDragEnabled() )
return false;
m_toolMgr->RunAction( PCB_ACTIONS::routerInlineDrag, true );
m_toolMgr->RunAction( PCB_ACTIONS::routerInlineDrag, true, aDragMode );
return true;
}
return false;
}
int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
{
int mode = PNS::DM_ANY;
if( aEvent.IsAction( &PCB_ACTIONS::dragFreeAngle ) )
mode |= PNS::DM_FREE_ANGLE;
invokeInlineRouter( mode );
return 0;
}
int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
{
@ -354,13 +374,16 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// Main loop: keep receiving events
do
{
if( evt->IsAction( &PCB_ACTIONS::editActivate )
|| evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
bool matchingAction = evt->IsAction( &PCB_ACTIONS::editActivate )
|| evt->IsAction( &PCB_ACTIONS::move );
if( matchingAction
|| evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
{
if( selection.Empty() )
break;
BOARD_ITEM* curr_item = static_cast<BOARD_ITEM*>( selection.Front() );
auto curr_item = static_cast<BOARD_ITEM*>( selection.Front() );
if( m_dragging && evt->Category() == TC_MOUSE )
{
@ -376,7 +399,12 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
}
else if( !m_dragging ) // Prepare to start dragging
{
if( !invokeInlineRouter() )
bool invokedRouter = false;
if ( !evt->IsAction( &PCB_ACTIONS::move ) )
invokedRouter = invokeInlineRouter( PNS::DM_ANY );
if( !invokedRouter )
{
// deal with locked items (override lock or abort the operation)
SELECTION_LOCK_FLAGS lockFlags = m_selectionTool->CheckLock();
@ -509,6 +537,46 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
return 0;
}
bool EDIT_TOOL::changeTrackWidthOnClick( const SELECTION& selection )
{
if ( selection.Size() == 1 && frame()->Settings().m_editActionChangesTrackWidth )
{
auto item = static_cast<BOARD_ITEM *>( selection[0] );
m_commit->Modify( item );
if( auto via = dyn_cast<VIA*>( item ) )
{
int new_width, new_drill;
if( via->GetViaType() == VIA_MICROVIA )
{
auto net = via->GetNet();
new_width = net->GetMicroViaSize();
new_drill = net->GetMicroViaDrillSize();
}
else
{
new_width = board()->GetDesignSettings().GetCurrentViaSize();
new_drill = board()->GetDesignSettings().GetCurrentViaDrill();
}
via->SetDrill( new_drill );
via->SetWidth( new_width );
}
else if ( auto track = dyn_cast<TRACK*>( item ) )
{
int new_width = board()->GetDesignSettings().GetCurrentTrackWidth();
track->SetWidth( new_width );
}
m_commit->Push( _("Edit track width/via size") );
return true;
}
return false;
}
int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
{
@ -522,41 +590,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
// Tracks & vias are treated in a special way:
if( ( SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) )( selection ) )
{
if ( selection.Size() == 1 && editFrame->Settings().m_editActionChangesTrackWidth )
{
auto item = static_cast<BOARD_ITEM *>( selection[0] );
m_commit->Modify( item );
if( auto via = dyn_cast<VIA*>( item ) )
{
int new_width, new_drill;
if( via->GetViaType() == VIA_MICROVIA )
{
auto net = via->GetNet();
new_width = net->GetMicroViaSize();
new_drill = net->GetMicroViaDrillSize();
}
else
{
new_width = board()->GetDesignSettings().GetCurrentViaSize();
new_drill = board()->GetDesignSettings().GetCurrentViaDrill();
}
via->SetDrill( new_drill );
via->SetWidth( new_width );
}
else if ( auto track = dyn_cast<TRACK*>( item ) )
{
int new_width = board()->GetDesignSettings().GetCurrentTrackWidth();
track->SetWidth( new_width );
}
m_commit->Push( _("Edit track width/via size") );
}
else
if ( !changeTrackWidthOnClick( selection ) )
{
DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection );
@ -1151,6 +1185,9 @@ int EDIT_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
void EDIT_TOOL::setTransitions()
{
Go( &EDIT_TOOL::Main, PCB_ACTIONS::editActivate.MakeEvent() );
Go( &EDIT_TOOL::Main, PCB_ACTIONS::move.MakeEvent() );
Go( &EDIT_TOOL::Drag, PCB_ACTIONS::drag45Degree.MakeEvent() );
Go( &EDIT_TOOL::Drag, PCB_ACTIONS::dragFreeAngle.MakeEvent() );
Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCw.MakeEvent() );
Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCcw.MakeEvent() );
Go( &EDIT_TOOL::Flip, PCB_ACTIONS::flip.MakeEvent() );
@ -1226,7 +1263,7 @@ int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent )
template<class T>
T* EDIT_TOOL::uniqueSelected()
{
const auto selection = m_selectionTool->GetSelection();
auto& selection = m_selectionTool->RequestSelection( SELECTION_DEFAULT );
if( selection.Size() != 1 )
return nullptr;

View File

@ -29,6 +29,7 @@
#include <math/vector2d.h>
#include <tools/pcb_tool.h>
class BOARD_COMMIT;
class BOARD_ITEM;
class SELECTION_TOOL;
@ -60,6 +61,13 @@ public:
*/
int Main( const TOOL_EVENT& aEvent );
/**
* Function Drag()
*
* todo
*/
int Drag( const TOOL_EVENT& aEvent );
/**
* Function Edit()
*
@ -151,7 +159,10 @@ private:
int editFootprintInFpEditor( const TOOL_EVENT& aEvent );
bool invokeInlineRouter();
bool invokeInlineRouter( int aDragMode );
bool changeTrackWidthOnClick( const SELECTION& selection );
/**
* Function hoverSelection()

View File

@ -86,6 +86,9 @@ public:
/// Activation of the edit tool
static TOOL_ACTION editActivate;
/// move an item
static TOOL_ACTION move;
/// Rotation of selected objects clockwise
static TOOL_ACTION rotateCw;
@ -120,6 +123,11 @@ public:
static TOOL_ACTION remove;
static TOOL_ACTION removeAlt;
static TOOL_ACTION breakTrack;
static TOOL_ACTION drag45Degree;
static TOOL_ACTION dragFreeAngle;
// Drawing Tool
/// Activation of the drawing tool (line)
static TOOL_ACTION drawLine;
@ -197,9 +205,6 @@ public:
/// Activation of the Push and Shove router (inline dragging mode)
static TOOL_ACTION routerInlineDrag;
/// Break track action
static TOOL_ACTION breakTrack;
// Point Editor
/// Break outline (insert additional points to an edge)
static TOOL_ACTION pointEditorAddCorner;