2013-09-18 17:55:16 +00:00
/*
* KiRouter - a push - and - ( sometimes - ) shove PCB router
*
2017-01-18 08:04:11 +00:00
* Copyright ( C ) 2013 - 2017 CERN
2021-01-27 22:15:38 +00:00
* Copyright ( C ) 2017 - 2021 KiCad Developers , see AUTHORS . txt for contributors .
*
* @ author Tomasz Wlostowski < tomasz . wlostowski @ cern . ch >
2013-09-26 21:53:54 +00:00
*
2013-09-18 17:55:16 +00:00
* This program is free software : you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation , either version 3 of the License , or ( at your
* option ) any later version .
2013-09-26 21:53:54 +00:00
*
2013-09-18 17:55:16 +00:00
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
2013-09-26 21:53:54 +00:00
*
2013-09-18 17:55:16 +00:00
* You should have received a copy of the GNU General Public License along
2014-05-14 13:53:54 +00:00
* with this program . If not , see < http : //www.gnu.org/licenses/>.
2013-09-18 17:55:16 +00:00
*/
2020-10-16 11:20:37 +00:00
# include <wx/hyperlink.h>
2021-02-11 22:08:46 +00:00
# include <advanced_config.h>
2016-06-29 10:23:11 +00:00
# include <functional>
using namespace std : : placeholders ;
2020-11-12 20:19:22 +00:00
# include <board.h>
2021-06-06 19:03:10 +00:00
# include <board_design_settings.h>
2020-11-14 18:11:28 +00:00
# include <board_item.h>
2020-11-12 20:19:22 +00:00
# include <footprint.h>
2020-10-04 23:34:59 +00:00
# include <fp_shape.h>
2020-11-12 20:19:22 +00:00
# include <pad.h>
2021-06-03 18:05:43 +00:00
# include <zone.h>
2018-01-29 20:58:58 +00:00
# include <pcb_edit_frame.h>
2014-04-04 09:50:15 +00:00
# include <pcbnew_id.h>
2014-05-14 13:53:54 +00:00
# include <dialogs/dialog_pns_settings.h>
2015-02-18 00:29:54 +00:00
# include <dialogs/dialog_pns_diff_pair_dimensions.h>
2014-05-14 13:53:54 +00:00
# include <dialogs/dialog_track_via_size.h>
2020-10-16 11:20:37 +00:00
# include <widgets/infobar.h>
2021-05-16 10:17:44 +00:00
# include <widgets/appearance_controls.h>
2015-09-24 09:04:42 +00:00
# include <confirm.h>
2017-02-20 12:20:39 +00:00
# include <bitmaps.h>
2019-05-14 11:14:00 +00:00
# include <tool/action_menu.h>
2015-05-05 18:39:41 +00:00
# include <tool/tool_manager.h>
2020-09-24 22:48:46 +00:00
# include <tool/tool_menu.h>
2017-02-21 12:42:08 +00:00
# include <tools/pcb_actions.h>
2020-12-16 13:31:32 +00:00
# include <tools/pcb_selection_tool.h>
2021-01-16 23:17:32 +00:00
# include <tools/pcb_grid_helper.h>
2013-09-18 17:55:16 +00:00
# include "router_tool.h"
# include "pns_segment.h"
# include "pns_router.h"
2020-02-28 22:16:55 +00:00
# include "pns_itemset.h"
2020-04-16 22:29:28 +00:00
# include "pns_logger.h"
# include "pns_kicad_iface.h"
2013-09-18 17:55:16 +00:00
2020-10-05 18:38:40 +00:00
# include <plugins/kicad/kicad_plugin.h>
2020-04-16 22:35:44 +00:00
2013-10-14 14:13:35 +00:00
using namespace KIGFX ;
2017-03-22 16:56:01 +00:00
/**
* Flags used by via tool actions
*/
enum VIA_ACTION_FLAGS
{
// Via type
VIA_MASK = 0x03 ,
2021-01-27 22:15:38 +00:00
VIA = 0x00 , ///< Normal via
BLIND_VIA = 0x01 , ///< blind/buried via
MICROVIA = 0x02 , ///< Microvia
2017-03-16 11:20:18 +00:00
// Select layer
2021-01-27 22:15:38 +00:00
SELECT_LAYER = VIA_MASK + 1 , ///< Ask user to select layer before adding via
2017-03-22 16:56:01 +00:00
} ;
2019-06-17 00:34:21 +00:00
// Actions, being statically-defined, require specialized I18N handling. We continue to
// use the _() macro so that string harvesting by the I18N framework doesn't have to be
// specialized, but we don't translate on initialization and instead do it in the getters.
# undef _
# define _(s) s
2019-06-24 15:27:05 +00:00
static const TOOL_ACTION ACT_EndTrack ( " pcbnew.InteractiveRouter.EndTrack " ,
2019-10-03 21:31:33 +00:00
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
WXK_END , " " ,
2019-06-24 15:27:05 +00:00
_ ( " Finish Track " ) , _ ( " Stops laying the current track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : checked_ok ) ;
2015-04-02 14:09:26 +00:00
2019-10-03 21:31:33 +00:00
static const TOOL_ACTION ACT_AutoEndRoute ( " pcbnew.InteractiveRouter.AutoEndRoute " ,
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
' F ' , " " ,
2019-06-24 15:27:05 +00:00
_ ( " Auto-finish Track " ) , _ ( " Automagically finishes laying the current track. " ) ) ;
2015-04-02 14:09:26 +00:00
2017-01-18 08:04:11 +00:00
static const TOOL_ACTION ACT_PlaceThroughVia ( " pcbnew.InteractiveRouter.PlaceVia " ,
2019-10-03 21:31:33 +00:00
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
' V ' , LEGACY_HK_NAME ( " Add Through Via " ) ,
_ ( " Place Through Via " ) ,
_ ( " Adds a through-hole via at the end of currently routed track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : via , AF_NONE , ( void * ) VIA_ACTION_FLAGS : : VIA ) ;
2015-05-03 18:43:07 +00:00
2017-01-18 08:04:11 +00:00
static const TOOL_ACTION ACT_PlaceBlindVia ( " pcbnew.InteractiveRouter.PlaceBlindVia " ,
2019-10-03 21:31:33 +00:00
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
MD_ALT + MD_SHIFT + ' V ' , LEGACY_HK_NAME ( " Add Blind/Buried Via " ) ,
_ ( " Place Blind/Buried Via " ) ,
_ ( " Adds a blind or buried via at the end of currently routed track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : via_buried , AF_NONE , ( void * ) VIA_ACTION_FLAGS : : BLIND_VIA ) ;
2015-05-03 18:43:07 +00:00
2017-01-18 08:04:11 +00:00
static const TOOL_ACTION ACT_PlaceMicroVia ( " pcbnew.InteractiveRouter.PlaceMicroVia " ,
2019-10-03 21:31:33 +00:00
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
MD_CTRL + ' V ' , LEGACY_HK_NAME ( " Add MicroVia " ) ,
_ ( " Place Microvia " ) , _ ( " Adds a microvia at the end of currently routed track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : via_microvia , AF_NONE , ( void * ) VIA_ACTION_FLAGS : : MICROVIA ) ;
2019-06-09 21:57:23 +00:00
2020-12-11 18:29:52 +00:00
static const TOOL_ACTION ACT_SelLayerAndPlaceThroughVia (
" pcbnew.InteractiveRouter.SelLayerAndPlaceVia " ,
2019-06-09 21:57:23 +00:00
AS_CONTEXT ,
' < ' , LEGACY_HK_NAME ( " Select Layer and Add Through Via " ) ,
_ ( " Select Layer and Place Through Via... " ) ,
_ ( " Select a layer, then add a through-hole via at the end of currently routed track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : select_w_layer , AF_NONE ,
2019-06-09 21:57:23 +00:00
( void * ) ( VIA_ACTION_FLAGS : : VIA | VIA_ACTION_FLAGS : : SELECT_LAYER ) ) ;
2020-12-11 18:29:52 +00:00
static const TOOL_ACTION ACT_SelLayerAndPlaceBlindVia (
" pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia " ,
2019-10-03 21:31:33 +00:00
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
MD_ALT + ' < ' , LEGACY_HK_NAME ( " Select Layer and Add Blind/Buried Via " ) ,
_ ( " Select Layer and Place Blind/Buried Via... " ) ,
2021-06-28 18:16:33 +00:00
_ ( " Select a layer, then add a blind or buried via at the end of currently routed track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : select_w_layer , AF_NONE ,
2019-06-09 21:57:23 +00:00
( void * ) ( VIA_ACTION_FLAGS : : BLIND_VIA | VIA_ACTION_FLAGS : : SELECT_LAYER ) ) ;
2017-03-16 11:20:18 +00:00
2021-06-28 18:16:33 +00:00
static const TOOL_ACTION ACT_SelLayerAndPlaceMicroVia (
" pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia " ,
AS_CONTEXT ,
0 , " " ,
_ ( " Select Layer and Place Micro Via... " ) ,
_ ( " Select a layer, then add a micro via at the end of currently routed track. " ) ,
BITMAPS : : select_w_layer , AF_NONE ,
( void * ) ( VIA_ACTION_FLAGS : : MICROVIA | VIA_ACTION_FLAGS : : SELECT_LAYER ) ) ;
2017-01-18 08:04:11 +00:00
static const TOOL_ACTION ACT_CustomTrackWidth ( " pcbnew.InteractiveRouter.CustomTrackViaSize " ,
2019-10-03 21:31:33 +00:00
AS_CONTEXT ,
2019-06-09 21:57:23 +00:00
' Q ' , LEGACY_HK_NAME ( " Custom Track/Via Size " ) ,
_ ( " Custom Track/Via Size... " ) ,
_ ( " Shows a dialog for changing the track width and via size. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : width_track ) ;
2019-06-09 21:57:23 +00:00
2019-10-03 21:31:33 +00:00
static const TOOL_ACTION ACT_SwitchPosture ( " pcbnew.InteractiveRouter.SwitchPosture " ,
2019-06-09 21:57:23 +00:00
AS_CONTEXT ,
' / ' , LEGACY_HK_NAME ( " Switch Track Posture " ) ,
_ ( " Switch Track Posture " ) ,
_ ( " Switches posture of the currently routed track. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : change_entry_orient ) ;
2015-05-03 18:43:07 +00:00
2019-05-17 00:13:21 +00:00
static const TOOL_ACTION ACT_SwitchRounding ( " pcbnew.InteractiveRouter.SwitchRounding " ,
AS_CONTEXT ,
2021-03-21 19:55:56 +00:00
MD_CTRL + ' / ' , " " ,
_ ( " Track Corner Mode " ) ,
_ ( " Switches between sharp and rounded corners when routing tracks. " ) ,
2021-03-08 02:59:07 +00:00
BITMAPS : : switch_corner_rounding_shape ) ;
2019-05-17 00:13:21 +00:00
2019-06-17 00:34:21 +00:00
# undef _
# define _(s) wxGetTranslation((s))
2013-09-18 17:55:16 +00:00
ROUTER_TOOL : : ROUTER_TOOL ( ) :
2021-04-01 17:09:22 +00:00
TOOL_BASE ( " pcbnew.InteractiveRouter " ) ,
m_lastTargetLayer ( UNDEFINED_LAYER )
2015-02-18 16:53:46 +00:00
{
2014-05-14 13:53:54 +00:00
}
2013-09-26 21:53:54 +00:00
2014-05-16 11:37:31 +00:00
2019-06-15 00:29:42 +00:00
class TRACK_WIDTH_MENU : public ACTION_MENU
2014-05-14 13:53:54 +00:00
{
public :
2018-04-28 15:22:25 +00:00
TRACK_WIDTH_MENU ( PCB_EDIT_FRAME & aFrame ) :
2019-06-15 00:29:42 +00:00
ACTION_MENU ( true ) ,
2018-04-28 15:22:25 +00:00
m_frame ( aFrame )
2014-05-14 13:53:54 +00:00
{
2021-03-08 02:59:07 +00:00
SetIcon ( BITMAPS : : width_track_via ) ;
2017-01-23 13:47:49 +00:00
SetTitle ( _ ( " Select Track/Via Width " ) ) ;
2014-05-14 13:53:54 +00:00
}
2013-10-11 12:26:09 +00:00
2018-04-28 15:22:25 +00:00
protected :
2019-05-14 11:14:00 +00:00
ACTION_MENU * create ( ) const override
2014-05-14 13:53:54 +00:00
{
2018-04-28 15:22:25 +00:00
return new TRACK_WIDTH_MENU ( m_frame ) ;
}
2014-06-24 16:17:18 +00:00
2018-04-28 15:22:25 +00:00
void update ( ) override
{
2019-12-20 14:11:39 +00:00
EDA_UNITS units = m_frame . GetUserUnits ( ) ;
2018-06-17 13:50:49 +00:00
BOARD_DESIGN_SETTINGS & bds = m_frame . GetBoard ( ) - > GetDesignSettings ( ) ;
bool useIndex = ! bds . m_UseConnectedTrackWidth & &
! bds . UseCustomTrackViaSize ( ) ;
wxString msg ;
2017-01-20 17:33:11 +00:00
2018-04-28 15:22:25 +00:00
Clear ( ) ;
2014-05-14 13:53:54 +00:00
2018-02-09 16:28:33 +00:00
Append ( ID_POPUP_PCB_SELECT_AUTO_WIDTH , _ ( " Use Starting Track Width " ) ,
2014-05-16 11:37:31 +00:00
_ ( " Route using the width of the starting track. " ) , wxITEM_CHECK ) ;
2018-04-28 15:22:25 +00:00
Check ( ID_POPUP_PCB_SELECT_AUTO_WIDTH ,
bds . m_UseConnectedTrackWidth & & ! bds . UseCustomTrackViaSize ( ) ) ;
2014-05-14 13:53:54 +00:00
2018-02-09 16:28:33 +00:00
Append ( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES , _ ( " Use Net Class Values " ) ,
2014-05-16 11:37:31 +00:00
_ ( " Use track and via sizes from the net class " ) , wxITEM_CHECK ) ;
2018-04-28 15:22:25 +00:00
Check ( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES ,
useIndex & & bds . GetTrackWidthIndex ( ) = = 0 & & bds . GetViaSizeIndex ( ) = = 0 ) ;
Append ( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH , _ ( " Use Custom Values... " ) ,
_ ( " Specify custom track and via sizes " ) , wxITEM_CHECK ) ;
Check ( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH , bds . UseCustomTrackViaSize ( ) ) ;
2014-05-14 13:53:54 +00:00
AppendSeparator ( ) ;
2015-07-07 16:36:56 +00:00
// Append the list of tracks & via sizes
2018-04-28 15:22:25 +00:00
for ( unsigned i = 0 ; i < bds . m_TrackWidthList . size ( ) ; i + + )
{
int width = bds . m_TrackWidthList [ i ] ;
2014-05-14 13:53:54 +00:00
2018-04-28 15:22:25 +00:00
if ( i = = 0 )
msg = _ ( " Track netclass width " ) ;
else
2020-10-02 20:51:24 +00:00
msg . Printf ( _ ( " Track %s " ) , MessageTextFromValue ( units , width ) ) ;
2018-04-28 15:22:25 +00:00
int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i ;
Append ( menuIdx , msg , wxEmptyString , wxITEM_CHECK ) ;
Check ( menuIdx , useIndex & & bds . GetTrackWidthIndex ( ) = = i ) ;
}
AppendSeparator ( ) ;
for ( unsigned i = 0 ; i < bds . m_ViasDimensionsList . size ( ) ; i + + )
{
VIA_DIMENSION via = bds . m_ViasDimensionsList [ i ] ;
if ( i = = 0 )
msg = _ ( " Via netclass values " ) ;
else
{
if ( via . m_Drill > 0 )
2019-01-14 12:12:20 +00:00
msg . Printf ( _ ( " Via %s, drill %s " ) ,
2020-10-02 20:51:24 +00:00
MessageTextFromValue ( units , via . m_Diameter ) ,
MessageTextFromValue ( units , via . m_Drill ) ) ;
2019-01-14 12:12:20 +00:00
else
2020-10-02 20:51:24 +00:00
msg . Printf ( _ ( " Via %s " ) , MessageTextFromValue ( units , via . m_Diameter ) ) ;
2018-04-28 15:22:25 +00:00
}
int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i ;
Append ( menuIdx , msg , wxEmptyString , wxITEM_CHECK ) ;
Check ( menuIdx , useIndex & & bds . GetViaSizeIndex ( ) = = i ) ;
}
2017-01-20 17:33:11 +00:00
}
OPT_TOOL_EVENT eventHandler ( const wxMenuEvent & aEvent ) override
2014-05-14 13:53:54 +00:00
{
2018-04-28 15:22:25 +00:00
BOARD_DESIGN_SETTINGS & bds = m_frame . GetBoard ( ) - > GetDesignSettings ( ) ;
2014-05-14 13:53:54 +00:00
int id = aEvent . GetId ( ) ;
2018-04-28 15:22:25 +00:00
// On Windows, this handler can be called with an event ID not existing in any
// menuitem, so only set flags when we have an ID match.
2014-05-14 13:53:54 +00:00
if ( id = = ID_POPUP_PCB_SELECT_CUSTOM_WIDTH )
{
2018-04-28 15:22:25 +00:00
bds . UseCustomTrackViaSize ( true ) ;
bds . m_UseConnectedTrackWidth = false ;
m_frame . GetToolManager ( ) - > RunAction ( ACT_CustomTrackWidth , true ) ;
2014-05-14 13:53:54 +00:00
}
else if ( id = = ID_POPUP_PCB_SELECT_AUTO_WIDTH )
{
2018-04-28 15:22:25 +00:00
bds . UseCustomTrackViaSize ( false ) ;
bds . m_UseConnectedTrackWidth = true ;
2014-05-14 13:53:54 +00:00
}
else if ( id = = ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES )
{
2018-04-28 15:22:25 +00:00
bds . UseCustomTrackViaSize ( false ) ;
bds . m_UseConnectedTrackWidth = false ;
2014-05-14 13:53:54 +00:00
bds . SetViaSizeIndex ( 0 ) ;
bds . SetTrackWidthIndex ( 0 ) ;
}
2018-04-28 15:22:25 +00:00
else if ( id > = ID_POPUP_PCB_SELECT_VIASIZE1 & & id < = ID_POPUP_PCB_SELECT_VIASIZE16 )
2014-05-14 13:53:54 +00:00
{
2018-04-28 15:22:25 +00:00
bds . UseCustomTrackViaSize ( false ) ;
bds . m_UseConnectedTrackWidth = false ;
2014-05-14 13:53:54 +00:00
bds . SetViaSizeIndex ( id - ID_POPUP_PCB_SELECT_VIASIZE1 ) ;
}
2018-04-28 15:22:25 +00:00
else if ( id > = ID_POPUP_PCB_SELECT_WIDTH1 & & id < = ID_POPUP_PCB_SELECT_WIDTH16 )
2014-05-14 13:53:54 +00:00
{
2018-04-28 15:22:25 +00:00
bds . UseCustomTrackViaSize ( false ) ;
bds . m_UseConnectedTrackWidth = false ;
2014-05-14 13:53:54 +00:00
bds . SetTrackWidthIndex ( id - ID_POPUP_PCB_SELECT_WIDTH1 ) ;
}
2018-04-28 15:22:25 +00:00
return OPT_TOOL_EVENT ( PCB_ACTIONS : : trackViaSizeChanged . MakeEvent ( ) ) ;
}
private :
PCB_EDIT_FRAME & m_frame ;
} ;
2019-06-15 00:29:42 +00:00
class DIFF_PAIR_MENU : public ACTION_MENU
2018-04-28 15:22:25 +00:00
{
public :
DIFF_PAIR_MENU ( PCB_EDIT_FRAME & aFrame ) :
2019-06-15 00:29:42 +00:00
ACTION_MENU ( true ) ,
2018-04-28 15:22:25 +00:00
m_frame ( aFrame )
{
2021-03-08 02:59:07 +00:00
SetIcon ( BITMAPS : : width_track_via ) ;
2018-04-28 15:22:25 +00:00
SetTitle ( _ ( " Select Differential Pair Dimensions " ) ) ;
}
protected :
2019-05-14 11:14:00 +00:00
ACTION_MENU * create ( ) const override
2018-04-28 15:22:25 +00:00
{
return new DIFF_PAIR_MENU ( m_frame ) ;
}
void update ( ) override
{
2019-12-20 14:11:39 +00:00
EDA_UNITS units = m_frame . GetUserUnits ( ) ;
const BOARD_DESIGN_SETTINGS & bds = m_frame . GetBoard ( ) - > GetDesignSettings ( ) ;
2018-04-28 15:22:25 +00:00
Clear ( ) ;
Append ( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR , _ ( " Use Net Class Values " ) ,
_ ( " Use differential pair dimensions from the net class " ) , wxITEM_CHECK ) ;
Check ( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR ,
! bds . UseCustomDiffPairDimensions ( ) & & bds . GetDiffPairIndex ( ) = = 0 ) ;
Append ( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR , _ ( " Use Custom Values... " ) ,
_ ( " Specify custom differential pair dimensions " ) , wxITEM_CHECK ) ;
Check ( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR , bds . UseCustomDiffPairDimensions ( ) ) ;
AppendSeparator ( ) ;
// Append the list of differential pair dimensions
// Drop index 0 which is the current netclass dimensions (which are handled above)
for ( unsigned i = 1 ; i < bds . m_DiffPairDimensionsList . size ( ) ; + + i )
2017-01-20 07:29:24 +00:00
{
2018-04-28 15:22:25 +00:00
DIFF_PAIR_DIMENSION diffPair = bds . m_DiffPairDimensionsList [ i ] ;
wxString msg ;
2020-10-20 19:05:04 +00:00
if ( diffPair . m_Gap < = 0 )
{
if ( diffPair . m_ViaGap < = 0 )
{
msg . Printf ( _ ( " Width %s " ) ,
MessageTextFromValue ( units , diffPair . m_Width ) ) ;
}
else
{
2020-10-25 09:02:07 +00:00
msg . Printf ( _ ( " Width %s, via gap %s " ) ,
2020-10-20 19:05:04 +00:00
MessageTextFromValue ( units , diffPair . m_Width ) ,
MessageTextFromValue ( units , diffPair . m_ViaGap ) ) ;
}
}
else
{
if ( diffPair . m_ViaGap < = 0 )
{
msg . Printf ( _ ( " Width %s, gap %s " ) ,
MessageTextFromValue ( units , diffPair . m_Width ) ,
MessageTextFromValue ( units , diffPair . m_Gap ) ) ;
}
else
{
2020-11-23 10:42:25 +00:00
msg . Printf ( _ ( " Width %s, gap %s, via gap %s " ) ,
2020-10-20 19:05:04 +00:00
MessageTextFromValue ( units , diffPair . m_Width ) ,
MessageTextFromValue ( units , diffPair . m_Gap ) ,
MessageTextFromValue ( units , diffPair . m_ViaGap ) ) ;
}
}
2018-04-28 15:22:25 +00:00
int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1 ;
Append ( menuIdx , msg , wxEmptyString , wxITEM_CHECK ) ;
Check ( menuIdx , ! bds . UseCustomDiffPairDimensions ( ) & & bds . GetDiffPairIndex ( ) = = i ) ;
2017-01-20 07:29:24 +00:00
}
2018-04-28 15:22:25 +00:00
}
2017-01-20 07:29:24 +00:00
2018-04-28 15:22:25 +00:00
OPT_TOOL_EVENT eventHandler ( const wxMenuEvent & aEvent ) override
{
BOARD_DESIGN_SETTINGS & bds = m_frame . GetBoard ( ) - > GetDesignSettings ( ) ;
int id = aEvent . GetId ( ) ;
// On Windows, this handler can be called with an event ID not existing in any
// menuitem, so only set flags when we have an ID match.
if ( id = = ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR )
{
bds . UseCustomDiffPairDimensions ( true ) ;
TOOL_MANAGER * toolManager = m_frame . GetToolManager ( ) ;
2019-06-03 20:06:58 +00:00
toolManager - > RunAction ( PCB_ACTIONS : : routerDiffPairDialog , true ) ;
2018-04-28 15:22:25 +00:00
}
else if ( id = = ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR )
{
bds . UseCustomDiffPairDimensions ( false ) ;
bds . SetDiffPairIndex ( 0 ) ;
}
else if ( id > = ID_POPUP_PCB_SELECT_DIFFPAIR1 & & id < = ID_POPUP_PCB_SELECT_DIFFPAIR16 )
2017-01-20 07:29:24 +00:00
{
2018-04-28 15:22:25 +00:00
bds . UseCustomDiffPairDimensions ( false ) ;
// remember that the menu doesn't contain index 0 (which is the netclass values)
bds . SetDiffPairIndex ( id - ID_POPUP_PCB_SELECT_DIFFPAIR1 + 1 ) ;
2017-01-20 07:29:24 +00:00
}
2017-02-21 12:42:08 +00:00
return OPT_TOOL_EVENT ( PCB_ACTIONS : : trackViaSizeChanged . MakeEvent ( ) ) ;
2014-05-14 13:53:54 +00:00
}
2015-07-07 16:36:56 +00:00
private :
2018-04-28 15:22:25 +00:00
PCB_EDIT_FRAME & m_frame ;
2014-05-14 13:53:54 +00:00
} ;
2013-09-18 17:55:16 +00:00
2020-09-24 22:48:46 +00:00
ROUTER_TOOL : : ~ ROUTER_TOOL ( )
2014-05-16 11:37:31 +00:00
{
2020-09-24 22:48:46 +00:00
}
2017-02-06 16:00:51 +00:00
2020-09-24 22:48:46 +00:00
bool ROUTER_TOOL : : Init ( )
{
2021-04-01 17:09:22 +00:00
m_lastTargetLayer = UNDEFINED_LAYER ;
2020-09-24 22:48:46 +00:00
PCB_EDIT_FRAME * frame = getEditFrame < PCB_EDIT_FRAME > ( ) ;
2017-02-06 16:00:51 +00:00
2020-09-24 22:48:46 +00:00
wxASSERT ( frame ) ;
2017-08-03 15:53:07 +00:00
2020-09-24 22:48:46 +00:00
auto & menu = m_menu . GetMenu ( ) ;
menu . SetTitle ( _ ( " Interactive Router " ) ) ;
2017-08-03 15:53:07 +00:00
2021-01-14 15:17:24 +00:00
m_trackViaMenu = std : : make_shared < TRACK_WIDTH_MENU > ( * frame ) ;
m_trackViaMenu - > SetTool ( this ) ;
m_menu . AddSubMenu ( m_trackViaMenu ) ;
2014-05-14 13:53:54 +00:00
2021-01-14 15:17:24 +00:00
m_diffPairMenu = std : : make_shared < DIFF_PAIR_MENU > ( * frame ) ;
m_diffPairMenu - > SetTool ( this ) ;
m_menu . AddSubMenu ( m_diffPairMenu ) ;
2015-02-18 16:53:46 +00:00
2021-05-08 18:55:02 +00:00
auto notRoutingCond =
[ this ] ( const SELECTION & )
{
return ! m_router - > RoutingInProgress ( ) ;
} ;
2020-09-24 22:48:46 +00:00
menu . AddItem ( ACTIONS : : cancelInteractive , SELECTION_CONDITIONS : : ShowAlways ) ;
2015-02-18 16:53:46 +00:00
2020-09-24 22:48:46 +00:00
menu . AddSeparator ( ) ;
2017-01-09 13:59:30 +00:00
2021-06-19 10:36:37 +00:00
menu . AddItem ( PCB_ACTIONS : : routeSingleTrack , notRoutingCond ) ;
menu . AddItem ( PCB_ACTIONS : : routeDiffPair , notRoutingCond ) ;
menu . AddItem ( ACT_EndTrack , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( PCB_ACTIONS : : routerUndoLastSegment , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( PCB_ACTIONS : : breakTrack , notRoutingCond ) ;
2018-04-28 15:22:25 +00:00
2021-06-19 10:36:37 +00:00
menu . AddItem ( PCB_ACTIONS : : drag45Degree , notRoutingCond ) ;
menu . AddItem ( PCB_ACTIONS : : dragFreeAngle , notRoutingCond ) ;
2015-07-24 07:42:46 +00:00
2020-09-24 22:48:46 +00:00
// Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry.
2021-06-19 10:36:37 +00:00
menu . AddItem ( ACT_PlaceThroughVia , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( ACT_PlaceBlindVia , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( ACT_PlaceMicroVia , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( ACT_SelLayerAndPlaceThroughVia , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( ACT_SelLayerAndPlaceBlindVia , SELECTION_CONDITIONS : : ShowAlways ) ;
2021-06-28 18:16:33 +00:00
menu . AddItem ( ACT_SelLayerAndPlaceMicroVia , SELECTION_CONDITIONS : : ShowAlways ) ;
2021-06-19 10:36:37 +00:00
menu . AddItem ( ACT_SwitchPosture , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddItem ( ACT_SwitchRounding , SELECTION_CONDITIONS : : ShowAlways ) ;
2020-09-24 22:48:46 +00:00
menu . AddSeparator ( ) ;
auto diffPairCond =
[ this ] ( const SELECTION & )
{
return m_router - > Mode ( ) = = PNS : : PNS_MODE_ROUTE_DIFF_PAIR ;
} ;
2017-01-20 17:33:11 +00:00
2021-06-19 10:36:37 +00:00
menu . AddMenu ( m_trackViaMenu . get ( ) , SELECTION_CONDITIONS : : ShowAlways ) ;
menu . AddMenu ( m_diffPairMenu . get ( ) , diffPairCond ) ;
2014-05-14 13:53:54 +00:00
2021-06-19 10:36:37 +00:00
menu . AddItem ( PCB_ACTIONS : : routerSettingsDialog , SELECTION_CONDITIONS : : ShowAlways ) ;
2014-05-16 11:37:31 +00:00
2020-09-24 23:17:54 +00:00
menu . AddSeparator ( ) ;
2015-07-02 14:09:51 +00:00
2020-09-24 22:48:46 +00:00
frame - > AddStandardSubMenus ( m_menu ) ;
2017-01-20 17:33:11 +00:00
2015-07-02 14:09:51 +00:00
return true ;
2013-09-18 17:55:16 +00:00
}
2013-12-09 09:42:38 +00:00
void ROUTER_TOOL : : Reset ( RESET_REASON aReason )
2013-09-18 17:55:16 +00:00
{
2021-04-01 17:09:22 +00:00
m_lastTargetLayer = UNDEFINED_LAYER ;
2018-04-24 23:28:13 +00:00
if ( aReason = = RUN )
TOOL_BASE : : Reset ( aReason ) ;
2013-09-18 17:55:16 +00:00
}
2021-02-11 22:08:46 +00:00
// Saves the complete event log and the dump of the PCB, allowing us to
// recreate hard-to-find P&S quirks and bugs.
2015-05-18 11:48:11 +00:00
2021-02-11 22:08:46 +00:00
void ROUTER_TOOL : : saveRouterDebugLog ( )
2013-09-18 17:55:16 +00:00
{
2021-02-11 22:08:46 +00:00
auto logger = m_router - > Logger ( ) ;
2020-12-11 18:29:52 +00:00
2021-02-11 22:08:46 +00:00
if ( ! logger )
return ;
2020-09-24 22:48:46 +00:00
2021-02-11 22:08:46 +00:00
wxString cwd = wxGetCwd ( ) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
wxFileName fname_log ( cwd ) ;
fname_log . SetName ( " pns.log " ) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
wxFileName fname_dump ( cwd ) ;
fname_dump . SetName ( " pns.dump " ) ;
2021-01-27 22:15:38 +00:00
2021-02-11 22:08:46 +00:00
wxString msg = wxString : : Format ( _ ( " Event file: %s \n Board dump: %s " ) , fname_log . GetFullPath ( ) , fname_log . GetFullPath ( ) ) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
int rv = OKOrCancelDialog ( nullptr , _ ( " Save router log " ) , _ ( " Would you like to save the router \n event log for debugging purposes? " ) , msg , _ ( " OK " ) , _ ( " Cancel " ) ) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
if ( ! rv )
return ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
FILE * f = fopen ( fname_log . GetFullPath ( ) . c_str ( ) , " wb " ) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
// save base router configuration (mode, etc.)
2021-09-20 19:32:38 +00:00
fprintf ( f , " config %d %d %d %d \n " ,
2021-02-11 22:08:46 +00:00
m_router - > Settings ( ) . Mode ( ) ,
m_router - > Settings ( ) . RemoveLoops ( ) ? 1 : 0 ,
2021-09-20 19:32:38 +00:00
m_router - > Settings ( ) . GetFixAllSegments ( ) ? 1 : 0 ,
m_router - > Settings ( ) . GetCornerMode ( )
2021-02-11 22:08:46 +00:00
) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
const auto & events = logger - > GetEvents ( ) ;
2020-04-16 22:35:44 +00:00
2021-02-11 22:08:46 +00:00
for ( auto evt : events )
{
2021-06-03 22:12:26 +00:00
fprintf ( f , " event %d %d %d %s \n " , evt . p . x , evt . p . y , evt . type ,
( const char * ) evt . uuid . c_str ( ) ) ;
2021-02-11 22:08:46 +00:00
}
fclose ( f ) ;
// Export as *.kicad_pcb format, using a strategy which is specifically chosen
// as an example on how it could also be used to send it to the system clipboard.
PCB_IO pcb_io ;
pcb_io . Save ( fname_dump . GetFullPath ( ) , m_iface - > GetBoard ( ) , nullptr ) ;
}
void ROUTER_TOOL : : handleCommonEvents ( TOOL_EVENT & aEvent )
{
2021-02-17 21:01:34 +00:00
if ( aEvent . Category ( ) = = TC_VIEW | | aEvent . Category ( ) = = TC_MOUSE )
{
2021-04-10 20:13:01 +00:00
BOX2D viewAreaD = getView ( ) - > GetGAL ( ) - > GetVisibleWorldExtents ( ) ;
2021-02-17 21:01:34 +00:00
m_router - > SetVisibleViewArea ( BOX2I ( viewAreaD . GetOrigin ( ) , viewAreaD . GetSize ( ) ) ) ;
}
2021-02-11 22:08:46 +00:00
if ( ! aEvent . IsKeyPressed ( ) )
return ;
switch ( aEvent . KeyCode ( ) )
{
case ' 0 ' :
if ( ! ADVANCED_CFG : : GetCfg ( ) . m_ShowRouterDebugGraphics )
return ;
saveRouterDebugLog ( ) ;
aEvent . SetPassEvent ( false ) ;
break ;
default :
break ;
2014-05-16 11:37:31 +00:00
}
2014-05-14 13:53:54 +00:00
}
2013-09-26 21:53:54 +00:00
2015-05-18 11:48:11 +00:00
2016-08-29 17:31:13 +00:00
int ROUTER_TOOL : : getStartLayer ( const PNS : : ITEM * aItem )
2014-11-14 18:15:58 +00:00
{
int tl = getView ( ) - > GetTopLayer ( ) ;
2013-09-26 21:53:54 +00:00
2014-11-14 19:19:00 +00:00
if ( m_startItem )
2014-11-14 18:15:58 +00:00
{
2016-08-29 17:31:13 +00:00
const LAYER_RANGE & ls = m_startItem - > Layers ( ) ;
2014-11-14 18:15:58 +00:00
2014-11-14 19:19:00 +00:00
if ( ls . Overlaps ( tl ) )
2014-11-14 18:15:58 +00:00
return tl ;
else
return ls . Start ( ) ;
}
2014-11-14 19:19:00 +00:00
2014-11-14 18:15:58 +00:00
return tl ;
}
2015-05-18 11:48:11 +00:00
2014-11-14 18:15:58 +00:00
void ROUTER_TOOL : : switchLayerOnViaPlacement ( )
2013-09-18 17:55:16 +00:00
{
2017-08-03 15:53:07 +00:00
int al = frame ( ) - > GetActiveLayer ( ) ;
2014-11-14 18:15:58 +00:00
int cl = m_router - > GetCurrentLayer ( ) ;
2014-11-14 19:19:00 +00:00
2014-11-14 18:15:58 +00:00
if ( cl ! = al )
{
m_router - > SwitchLayer ( al ) ;
}
2017-11-01 11:14:16 +00:00
OPT < int > newLayer = m_router - > Sizes ( ) . PairedLayer ( cl ) ;
2014-11-14 18:15:58 +00:00
2015-09-24 16:34:22 +00:00
if ( ! newLayer )
newLayer = m_router - > Sizes ( ) . GetLayerTop ( ) ;
m_router - > SwitchLayer ( * newLayer ) ;
2021-04-01 17:09:22 +00:00
m_lastTargetLayer = * newLayer ;
2014-11-14 18:15:58 +00:00
}
2015-05-18 11:48:11 +00:00
2019-12-28 00:55:11 +00:00
static VIATYPE getViaTypeFromFlags ( int aFlags )
2014-11-14 18:15:58 +00:00
{
2017-03-22 16:56:01 +00:00
switch ( aFlags & VIA_ACTION_FLAGS : : VIA_MASK )
{
2019-12-28 00:55:11 +00:00
case VIA_ACTION_FLAGS : : VIA :
return VIATYPE : : THROUGH ;
case VIA_ACTION_FLAGS : : BLIND_VIA :
return VIATYPE : : BLIND_BURIED ;
case VIA_ACTION_FLAGS : : MICROVIA :
return VIATYPE : : MICROVIA ;
2017-03-22 16:56:01 +00:00
default :
2017-01-18 08:04:11 +00:00
wxASSERT_MSG ( false , " Unhandled via type " ) ;
2019-12-28 00:55:11 +00:00
return VIATYPE : : THROUGH ;
2017-03-22 16:56:01 +00:00
}
}
2020-07-03 23:49:19 +00:00
static PCB_LAYER_ID getTargetLayerFromEvent ( const TOOL_EVENT & aEvent )
{
if ( aEvent . IsAction ( & PCB_ACTIONS : : layerTop ) )
return F_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner1 ) )
return In1_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner2 ) )
return In2_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner3 ) )
return In3_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner4 ) )
return In4_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner5 ) )
return In5_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner6 ) )
return In6_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner7 ) )
return In7_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner8 ) )
return In8_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner9 ) )
return In9_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner10 ) )
return In10_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner11 ) )
return In11_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner12 ) )
return In12_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner13 ) )
return In13_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner14 ) )
return In14_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner15 ) )
return In15_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner16 ) )
return In16_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner17 ) )
return In17_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner18 ) )
return In18_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner19 ) )
return In19_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner20 ) )
return In20_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner21 ) )
return In21_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner22 ) )
return In22_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner23 ) )
return In23_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner24 ) )
return In24_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner25 ) )
return In25_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner26 ) )
return In26_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner27 ) )
return In27_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner28 ) )
return In28_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner29 ) )
return In29_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerInner30 ) )
return In30_Cu ;
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerBottom ) )
return B_Cu ;
else
return UNDEFINED_LAYER ;
}
2020-12-02 21:16:48 +00:00
int ROUTER_TOOL : : onLayerCommand ( const TOOL_EVENT & aEvent )
{
return handleLayerSwitch ( aEvent , false ) ;
}
2017-03-22 16:56:01 +00:00
int ROUTER_TOOL : : onViaCommand ( const TOOL_EVENT & aEvent )
2020-12-02 21:16:48 +00:00
{
return handleLayerSwitch ( aEvent , true ) ;
}
int ROUTER_TOOL : : handleLayerSwitch ( const TOOL_EVENT & aEvent , bool aForceVia )
2017-03-22 16:56:01 +00:00
{
2020-12-11 18:29:52 +00:00
wxCHECK ( m_router , 0 ) ;
2020-07-12 01:58:36 +00:00
if ( ! IsToolActive ( ) )
return 0 ;
2020-07-03 23:49:19 +00:00
// First see if this is one of the switch layer commands
2020-10-11 23:12:55 +00:00
LSEQ layers = LSET ( board ( ) - > GetEnabledLayers ( ) & LSET : : AllCuMask ( ) ) . Seq ( ) ;
PCB_LAYER_ID currentLayer = ( PCB_LAYER_ID ) m_router - > GetCurrentLayer ( ) ;
PCB_LAYER_ID targetLayer = UNDEFINED_LAYER ;
2017-01-18 08:04:11 +00:00
2020-07-03 23:49:19 +00:00
if ( aEvent . IsAction ( & PCB_ACTIONS : : layerNext ) )
{
size_t idx = 0 ;
for ( size_t i = 0 ; i < layers . size ( ) ; i + + )
{
2021-04-01 17:09:22 +00:00
if ( layers [ i ] = = m_lastTargetLayer )
2020-07-03 23:49:19 +00:00
{
idx = i ;
break ;
}
}
idx = ( idx + 1 ) % layers . size ( ) ;
targetLayer = layers [ idx ] ;
}
else if ( aEvent . IsAction ( & PCB_ACTIONS : : layerPrev ) )
{
size_t idx = 0 ;
for ( size_t i = 0 ; i < layers . size ( ) ; i + + )
{
2021-04-01 17:09:22 +00:00
if ( layers [ i ] = = m_lastTargetLayer )
2020-07-03 23:49:19 +00:00
{
idx = i ;
break ;
}
}
idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers . size ( ) - 1 ) ;
targetLayer = layers [ idx ] ;
}
else
{
targetLayer = getTargetLayerFromEvent ( aEvent ) ;
}
2021-04-01 17:09:22 +00:00
if ( targetLayer ! = UNDEFINED_LAYER )
2020-12-02 21:16:48 +00:00
{
2021-04-01 17:09:22 +00:00
m_lastTargetLayer = targetLayer ;
if ( targetLayer = = currentLayer )
return 0 ;
if ( ! aForceVia & & m_router & & m_router - > SwitchLayer ( targetLayer ) )
{
updateEndItem ( aEvent ) ;
m_router - > Move ( m_endSnapPoint , m_endItem ) ; // refresh
return 0 ;
}
2020-12-02 21:16:48 +00:00
}
2020-07-03 23:49:19 +00:00
BOARD_DESIGN_SETTINGS & bds = board ( ) - > GetDesignSettings ( ) ;
const int layerCount = bds . GetCopperLayerCount ( ) ;
PCB_LAYER_ID pairTop = frame ( ) - > GetScreen ( ) - > m_Route_Layer_TOP ;
2017-08-03 15:53:07 +00:00
PCB_LAYER_ID pairBottom = frame ( ) - > GetScreen ( ) - > m_Route_Layer_BOTTOM ;
2014-11-14 18:15:58 +00:00
2016-08-29 17:31:13 +00:00
PNS : : SIZES_SETTINGS sizes = m_router - > Sizes ( ) ;
2014-05-14 13:53:54 +00:00
2020-07-03 23:49:19 +00:00
VIATYPE viaType = VIATYPE : : THROUGH ;
bool selectLayer = false ;
2017-03-16 11:20:18 +00:00
2020-07-03 23:49:19 +00:00
// Otherwise it is one of the router-specific via commands
if ( targetLayer = = UNDEFINED_LAYER )
2017-03-16 11:20:18 +00:00
{
2020-07-03 23:49:19 +00:00
const int actViaFlags = aEvent . Parameter < intptr_t > ( ) ;
selectLayer = actViaFlags & VIA_ACTION_FLAGS : : SELECT_LAYER ;
2017-03-16 11:20:18 +00:00
2020-07-03 23:49:19 +00:00
viaType = getViaTypeFromFlags ( actViaFlags ) ;
2019-11-10 17:34:16 +00:00
2020-07-03 23:49:19 +00:00
// ask the user for a target layer
if ( selectLayer )
{
2021-02-02 17:19:25 +00:00
wxPoint endPoint = ( wxPoint ) view ( ) - > ToScreen ( m_endSnapPoint ) ;
endPoint = frame ( ) - > GetCanvas ( ) - > ClientToScreen ( endPoint ) ;
2021-02-17 19:47:28 +00:00
targetLayer = frame ( ) - > SelectOneLayer ( static_cast < PCB_LAYER_ID > ( currentLayer ) ,
LSET : : AllNonCuMask ( ) , endPoint ) ;
2020-07-03 23:49:19 +00:00
2021-02-02 17:19:25 +00:00
// Reset the cursor to the end of the track
controls ( ) - > SetCursorPosition ( m_endSnapPoint ) ;
2021-02-19 16:28:20 +00:00
if ( targetLayer = = UNDEFINED_LAYER ) // cancelled by user
return 0 ;
2020-07-03 23:49:19 +00:00
}
2017-03-16 11:20:18 +00:00
}
2015-02-18 00:29:54 +00:00
// fixme: P&S supports more than one fixed layer pair. Update the dialog?
2014-11-14 18:15:58 +00:00
sizes . ClearLayerPairs ( ) ;
2013-09-26 21:53:54 +00:00
2014-11-14 19:19:00 +00:00
if ( ! m_router - > IsPlacingVia ( ) )
2014-11-14 18:15:58 +00:00
{
// Cannot place microvias or blind vias if not allowed (obvious)
2019-12-28 00:55:11 +00:00
if ( ( viaType = = VIATYPE : : BLIND_BURIED ) & & ( ! bds . m_BlindBuriedViaAllowed ) )
2015-09-24 09:04:42 +00:00
{
2020-10-16 11:20:37 +00:00
WX_INFOBAR * infobar = frame ( ) - > GetInfoBar ( ) ;
wxHyperlinkCtrl * button = new wxHyperlinkCtrl ( infobar , wxID_ANY ,
2020-12-11 12:09:37 +00:00
_ ( " Show board setup " ) ,
wxEmptyString ) ;
2020-10-16 11:20:37 +00:00
button - > Bind ( wxEVT_COMMAND_HYPERLINK , std : : function < void ( wxHyperlinkEvent & aEvent ) > (
[ & ] ( wxHyperlinkEvent & aEvent )
{
getEditFrame < PCB_EDIT_FRAME > ( ) - > ShowBoardSetupDialog ( _ ( " Constraints " ) ) ;
} ) ) ;
2020-10-16 16:07:59 +00:00
infobar - > RemoveAllButtons ( ) ;
infobar - > AddButton ( button ) ;
2021-02-15 23:18:13 +00:00
infobar - > ShowMessageFor ( _ ( " Blind/buried vias must first be enabled in "
2020-10-16 11:20:37 +00:00
" Board Setup > Design Rules > Constraints. " ) ,
2021-08-01 20:51:08 +00:00
10000 , wxICON_ERROR , WX_INFOBAR : : MESSAGE_TYPE : : DRC_VIOLATION ) ;
2014-11-14 18:15:58 +00:00
return false ;
2015-09-24 09:04:42 +00:00
}
2015-05-18 11:48:11 +00:00
2019-12-28 00:55:11 +00:00
if ( ( viaType = = VIATYPE : : MICROVIA ) & & ( ! bds . m_MicroViasAllowed ) )
2015-09-24 09:04:42 +00:00
{
2020-10-16 11:20:37 +00:00
WX_INFOBAR * infobar = frame ( ) - > GetInfoBar ( ) ;
wxHyperlinkCtrl * button = new wxHyperlinkCtrl ( infobar , wxID_ANY ,
2020-12-01 13:05:31 +00:00
_ ( " Show board setup " ) , wxEmptyString ) ;
2020-10-16 11:20:37 +00:00
button - > Bind ( wxEVT_COMMAND_HYPERLINK , std : : function < void ( wxHyperlinkEvent & aEvent ) > (
[ & ] ( wxHyperlinkEvent & aEvent )
{
getEditFrame < PCB_EDIT_FRAME > ( ) - > ShowBoardSetupDialog ( _ ( " Constraints " ) ) ;
} ) ) ;
2020-10-16 16:07:59 +00:00
infobar - > RemoveAllButtons ( ) ;
infobar - > AddButton ( button ) ;
2021-02-15 23:18:13 +00:00
infobar - > ShowMessageFor ( _ ( " Microvias must first be enabled in "
2020-10-16 11:20:37 +00:00
" Board Setup > Design Rules > Constraints. " ) ,
2021-08-01 20:51:08 +00:00
10000 , wxICON_ERROR , WX_INFOBAR : : MESSAGE_TYPE : : DRC_VIOLATION ) ;
2014-11-14 18:15:58 +00:00
return false ;
2015-09-24 09:04:42 +00:00
}
2015-09-24 16:34:22 +00:00
}
2014-11-14 19:19:00 +00:00
2015-09-24 16:34:22 +00:00
// Convert blind/buried via to a through hole one, if it goes through all layers
2019-12-28 00:55:11 +00:00
if ( viaType = = VIATYPE : : BLIND_BURIED
& & ( ( targetLayer = = B_Cu & & currentLayer = = F_Cu )
| | ( targetLayer = = F_Cu & & currentLayer = = B_Cu ) ) )
2015-09-24 16:34:22 +00:00
{
2019-12-28 00:55:11 +00:00
viaType = VIATYPE : : THROUGH ;
2014-05-14 13:53:54 +00:00
}
2013-09-18 17:55:16 +00:00
2021-07-02 14:53:49 +00:00
if ( targetLayer = = UNDEFINED_LAYER )
2015-06-18 18:22:23 +00:00
{
2021-07-02 14:53:49 +00:00
// Implicic layer selection
switch ( viaType )
2017-03-16 11:20:18 +00:00
{
2021-07-02 14:53:49 +00:00
case VIATYPE : : THROUGH :
2017-03-16 11:20:18 +00:00
// use the default layer pair
2020-10-11 23:12:55 +00:00
currentLayer = pairTop ;
targetLayer = pairBottom ;
2021-07-02 14:53:49 +00:00
break ;
2015-10-05 16:28:41 +00:00
2021-07-02 14:53:49 +00:00
case VIATYPE : : MICROVIA :
2021-07-02 14:48:32 +00:00
if ( currentLayer = = F_Cu | | currentLayer = = In1_Cu )
{
// front-side microvia
currentLayer = F_Cu ;
2021-08-07 18:29:49 +00:00
if ( layerCount > 2 ) // Ensure the inner layer In1_Cu exists
targetLayer = In1_Cu ;
else
targetLayer = B_Cu ;
2021-07-02 14:48:32 +00:00
}
else if ( currentLayer = = B_Cu | | currentLayer = = layerCount - 2 )
{
// back-side microvia
currentLayer = B_Cu ,
targetLayer = ( PCB_LAYER_ID ) ( layerCount - 2 ) ;
}
else
{
2021-07-02 14:53:49 +00:00
wxFAIL_MSG ( " Invalid implicit layer pair for microvia (must be on "
" or adjacent to an outer layer). " ) ;
2021-07-02 14:48:32 +00:00
}
2021-07-02 14:53:49 +00:00
break ;
2015-09-24 16:34:22 +00:00
2021-07-02 14:53:49 +00:00
case VIATYPE : : BLIND_BURIED :
2017-03-16 11:20:18 +00:00
if ( currentLayer = = pairTop | | currentLayer = = pairBottom )
{
// the current layer is on the defined layer pair,
// swap to the other side
2020-10-11 23:12:55 +00:00
currentLayer = pairTop ;
targetLayer = pairBottom ;
2017-03-16 11:20:18 +00:00
}
else
{
// the current layer is not part of the current layer pair,
// so fallback and swap to the top layer of the pair by default
2020-10-11 23:12:55 +00:00
targetLayer = pairTop ;
2017-03-16 11:20:18 +00:00
}
2021-07-02 14:53:49 +00:00
break ;
2015-09-24 16:34:22 +00:00
2021-07-02 14:53:49 +00:00
default :
wxFAIL_MSG ( " unexpected via type " ) ;
break ;
}
2015-06-18 18:22:23 +00:00
}
2015-07-02 14:09:51 +00:00
2020-11-06 16:43:59 +00:00
sizes . SetViaDiameter ( bds . m_ViasMinSize ) ;
sizes . SetViaDrill ( bds . m_MinThroughDrill ) ;
2020-10-11 23:12:55 +00:00
if ( bds . UseNetClassVia ( ) | | viaType = = VIATYPE : : MICROVIA )
{
2021-06-11 21:07:02 +00:00
PCB_VIA dummyVia ( board ( ) ) ;
2020-10-11 23:12:55 +00:00
dummyVia . SetViaType ( viaType ) ;
dummyVia . SetLayerPair ( currentLayer , targetLayer ) ;
if ( ! m_router - > GetCurrentNets ( ) . empty ( ) )
dummyVia . SetNetCode ( m_router - > GetCurrentNets ( ) [ 0 ] ) ;
DRC_CONSTRAINT constraint ;
2021-02-08 14:53:49 +00:00
constraint = bds . m_DRCEngine - > EvalRules ( VIA_DIAMETER_CONSTRAINT , & dummyVia , nullptr ,
currentLayer ) ;
2020-11-06 16:43:59 +00:00
if ( ! constraint . IsNull ( ) )
2020-11-17 17:41:57 +00:00
sizes . SetViaDiameter ( constraint . m_Value . Opt ( ) ) ;
2020-10-11 23:12:55 +00:00
2021-02-08 14:53:49 +00:00
constraint = bds . m_DRCEngine - > EvalRules ( HOLE_SIZE_CONSTRAINT , & dummyVia , nullptr ,
currentLayer ) ;
2020-11-06 16:43:59 +00:00
if ( ! constraint . IsNull ( ) )
2020-11-17 17:41:57 +00:00
sizes . SetViaDrill ( constraint . m_Value . Opt ( ) ) ;
2020-10-11 23:12:55 +00:00
}
else
{
sizes . SetViaDiameter ( bds . GetCurrentViaSize ( ) ) ;
sizes . SetViaDrill ( bds . GetCurrentViaDrill ( ) ) ;
}
2017-01-18 08:04:11 +00:00
sizes . SetViaType ( viaType ) ;
2020-10-11 23:12:55 +00:00
sizes . AddLayerPair ( currentLayer , targetLayer ) ;
2015-09-24 16:34:22 +00:00
2014-11-14 18:15:58 +00:00
m_router - > UpdateSizes ( sizes ) ;
2021-04-01 17:09:22 +00:00
if ( ! m_router - > IsPlacingVia ( ) )
m_router - > ToggleViaPlacement ( ) ;
m_lastTargetLayer = targetLayer ;
2014-11-14 19:19:00 +00:00
2018-07-26 22:35:11 +00:00
if ( m_router - > RoutingInProgress ( ) )
2021-08-21 16:24:41 +00:00
{
2018-07-26 22:35:11 +00:00
updateEndItem ( aEvent ) ;
2021-08-21 16:24:41 +00:00
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
}
2018-07-26 22:35:11 +00:00
else
2021-08-21 16:24:41 +00:00
{
2018-07-26 22:35:11 +00:00
updateStartItem ( aEvent ) ;
2021-08-21 16:24:41 +00:00
}
2014-11-14 18:15:58 +00:00
2017-01-18 08:04:11 +00:00
return 0 ;
2014-11-14 18:15:58 +00:00
}
2015-02-18 00:29:54 +00:00
bool ROUTER_TOOL : : prepareInteractive ( )
2014-11-14 18:15:58 +00:00
{
2021-05-16 10:17:44 +00:00
PCB_EDIT_FRAME * editFrame = getEditFrame < PCB_EDIT_FRAME > ( ) ;
int routingLayer = getStartLayer ( m_startItem ) ;
2016-11-13 18:02:44 +00:00
if ( ! IsCopperLayer ( routingLayer ) )
{
2021-05-16 10:17:44 +00:00
editFrame - > ShowInfoBarError ( _ ( " Tracks on Copper layers only. " ) ) ;
2016-11-13 18:02:44 +00:00
return false ;
}
2019-06-09 23:21:50 +00:00
editFrame - > SetActiveLayer ( ToLAYER_ID ( routingLayer ) ) ;
2014-11-14 18:15:58 +00:00
2021-05-16 10:17:44 +00:00
if ( ! getView ( ) - > IsLayerVisible ( routingLayer ) )
{
editFrame - > GetAppearancePanel ( ) - > SetLayerVisible ( routingLayer , true ) ;
editFrame - > GetCanvas ( ) - > Refresh ( ) ;
}
2021-03-29 21:45:07 +00:00
if ( m_startItem & & m_startItem - > Net ( ) > 0 )
2020-10-14 00:30:38 +00:00
highlightNet ( true , m_startItem - > Net ( ) ) ;
2017-08-03 15:53:07 +00:00
controls ( ) - > SetAutoPan ( true ) ;
2013-09-18 17:55:16 +00:00
2016-08-29 17:31:13 +00:00
PNS : : SIZES_SETTINGS sizes ( m_router - > Sizes ( ) ) ;
2014-11-14 19:19:00 +00:00
2020-10-08 22:01:09 +00:00
m_iface - > ImportSizes ( sizes , m_startItem , - 1 ) ;
2017-08-03 15:53:07 +00:00
sizes . AddLayerPair ( frame ( ) - > GetScreen ( ) - > m_Route_Layer_TOP ,
frame ( ) - > GetScreen ( ) - > m_Route_Layer_BOTTOM ) ;
2020-10-08 22:01:09 +00:00
2015-02-18 00:29:54 +00:00
m_router - > UpdateSizes ( sizes ) ;
2015-02-18 16:53:46 +00:00
2015-05-18 11:48:11 +00:00
if ( ! m_router - > StartRouting ( m_startSnapPoint , m_startItem , routingLayer ) )
2015-02-18 00:29:54 +00:00
{
2021-01-04 17:51:50 +00:00
// It would make more sense to leave the net highlighted as the higher-contrast mode
// makes the router clearances more visible. However, since we just started routing
// the conversion of the screen from low contrast to high contrast is a bit jarring and
2021-01-27 22:15:38 +00:00
// makes the infobar coming up less noticeable.
2015-05-18 11:48:11 +00:00
highlightNet ( false ) ;
2021-01-04 17:51:50 +00:00
frame ( ) - > ShowInfoBarError ( m_router - > FailureReason ( ) , true ,
[ & ] ( )
{
m_router - > ClearViewDecorations ( ) ;
} ) ;
2018-02-16 08:04:22 +00:00
controls ( ) - > SetAutoPan ( false ) ;
2015-02-18 00:29:54 +00:00
return false ;
}
2013-09-18 17:55:16 +00:00
2019-06-09 21:57:23 +00:00
m_endItem = nullptr ;
2013-09-18 17:55:16 +00:00
m_endSnapPoint = m_startSnapPoint ;
2021-07-03 17:21:51 +00:00
updateMessagePanel ( ) ;
2017-08-03 15:53:07 +00:00
frame ( ) - > UndoRedoBlock ( true ) ;
2016-08-15 15:16:50 +00:00
2015-02-18 00:29:54 +00:00
return true ;
}
2015-05-18 11:48:11 +00:00
2015-08-04 21:08:13 +00:00
bool ROUTER_TOOL : : finishInteractive ( )
2015-02-18 00:29:54 +00:00
{
m_router - > StopRouting ( ) ;
2021-06-06 12:52:29 +00:00
m_startItem = nullptr ;
m_endItem = nullptr ;
2021-07-03 17:21:51 +00:00
updateMessagePanel ( ) ;
2020-11-19 20:08:58 +00:00
frame ( ) - > GetCanvas ( ) - > SetCurrentCursor ( KICURSOR : : ARROW ) ;
2017-08-03 15:53:07 +00:00
controls ( ) - > SetAutoPan ( false ) ;
controls ( ) - > ForceCursorPosition ( false ) ;
frame ( ) - > UndoRedoBlock ( false ) ;
2015-02-18 00:29:54 +00:00
highlightNet ( false ) ;
return true ;
}
2015-05-18 11:48:11 +00:00
2015-02-18 00:29:54 +00:00
void ROUTER_TOOL : : performRouting ( )
{
2021-01-04 17:51:50 +00:00
m_router - > ClearViewDecorations ( ) ;
2015-07-10 21:42:05 +00:00
if ( ! prepareInteractive ( ) )
2015-02-18 00:29:54 +00:00
return ;
2020-10-20 19:05:04 +00:00
auto setCursor =
[ & ] ( )
{
2020-10-08 02:47:01 +00:00
frame ( ) - > GetCanvas ( ) - > SetCurrentCursor ( KICURSOR : : PENCIL ) ;
} ;
// Set initial cursor
setCursor ( ) ;
2019-06-17 13:43:22 +00:00
while ( TOOL_EVENT * evt = Wait ( ) )
2013-09-18 17:55:16 +00:00
{
2020-10-08 02:47:01 +00:00
setCursor ( ) ;
2019-06-27 21:33:48 +00:00
2020-12-11 18:29:52 +00:00
// Don't crash if we missed an operation that canceled routing.
2020-06-04 22:46:56 +00:00
if ( ! m_router - > RoutingInProgress ( ) )
{
if ( evt - > IsCancelInteractive ( ) )
m_cancelled = true ;
break ;
}
2017-03-07 12:56:44 +00:00
2019-02-03 10:21:48 +00:00
handleCommonEvents ( * evt ) ;
2016-09-23 11:58:33 +00:00
if ( evt - > IsMotion ( ) )
2013-09-26 21:53:54 +00:00
{
2015-11-03 16:19:42 +00:00
updateEndItem ( * evt ) ;
2013-09-26 21:53:54 +00:00
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
}
2021-06-19 10:36:37 +00:00
else if ( evt - > IsAction ( & PCB_ACTIONS : : routerUndoLastSegment ) )
2020-02-07 19:57:24 +00:00
{
m_router - > UndoLastSegment ( ) ;
updateEndItem ( * evt ) ;
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
}
2019-06-24 15:27:05 +00:00
else if ( evt - > IsClick ( BUT_LEFT ) | | evt - > IsAction ( & PCB_ACTIONS : : routeSingleTrack ) )
2013-09-26 21:53:54 +00:00
{
2013-09-18 17:55:16 +00:00
updateEndItem ( * evt ) ;
2014-11-14 18:15:58 +00:00
bool needLayerSwitch = m_router - > IsPlacingVia ( ) ;
2018-06-19 17:29:36 +00:00
bool forceFinish = evt - > Modifier ( MD_SHIFT ) ;
2013-09-26 21:53:54 +00:00
2018-06-19 17:29:36 +00:00
if ( m_router - > FixRoute ( m_endSnapPoint , m_endItem , forceFinish ) )
2020-02-07 19:57:24 +00:00
{
2018-06-19 17:29:36 +00:00
break ;
2020-02-07 19:57:24 +00:00
}
2018-09-04 07:10:15 +00:00
2014-11-14 19:19:00 +00:00
if ( needLayerSwitch )
2014-11-14 18:15:58 +00:00
switchLayerOnViaPlacement ( ) ;
2014-07-09 14:50:31 +00:00
// Synchronize the indicated layer
2021-05-16 10:17:44 +00:00
PCB_LAYER_ID routingLayer = ToLAYER_ID ( m_router - > GetCurrentLayer ( ) ) ;
PCB_EDIT_FRAME * editFrame = getEditFrame < PCB_EDIT_FRAME > ( ) ;
editFrame - > SetActiveLayer ( routingLayer ) ;
if ( ! getView ( ) - > IsLayerVisible ( routingLayer ) )
{
editFrame - > GetAppearancePanel ( ) - > SetLayerVisible ( routingLayer , true ) ;
editFrame - > GetCanvas ( ) - > Refresh ( ) ;
}
2015-11-03 16:19:42 +00:00
updateEndItem ( * evt ) ;
2013-09-26 21:53:54 +00:00
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
2019-06-09 21:57:23 +00:00
m_startItem = nullptr ;
2014-05-16 11:37:31 +00:00
}
2019-05-17 00:13:21 +00:00
else if ( evt - > IsAction ( & ACT_SwitchRounding ) )
{
m_router - > ToggleRounded ( ) ;
updateEndItem ( * evt ) ;
m_router - > Move ( m_endSnapPoint , m_endItem ) ; // refresh
}
2014-05-14 13:53:54 +00:00
else if ( evt - > IsAction ( & ACT_SwitchPosture ) )
2013-09-26 21:53:54 +00:00
{
2014-05-14 13:53:54 +00:00
m_router - > FlipPosture ( ) ;
2015-11-03 16:19:42 +00:00
updateEndItem ( * evt ) ;
2014-07-09 14:50:31 +00:00
m_router - > Move ( m_endSnapPoint , m_endItem ) ; // refresh
2014-05-14 13:53:54 +00:00
}
2021-01-14 15:17:24 +00:00
else if ( evt - > IsAction ( & PCB_ACTIONS : : properties ) )
{
2021-01-20 18:19:06 +00:00
frame ( ) - > GetCanvas ( ) - > SetCurrentCursor ( KICURSOR : : ARROW ) ;
controls ( ) - > SetAutoPan ( false ) ;
{
m_toolMgr - > RunAction ( ACT_CustomTrackWidth , true ) ;
}
controls ( ) - > SetAutoPan ( true ) ;
setCursor ( ) ;
2021-07-08 01:26:21 +00:00
updateMessagePanel ( ) ;
2021-01-14 15:17:24 +00:00
}
2020-04-02 08:40:10 +00:00
else if ( evt - > IsAction ( & ACT_EndTrack ) | | evt - > IsDblClick ( BUT_LEFT ) )
2014-05-14 13:53:54 +00:00
{
2020-04-02 08:40:10 +00:00
// Stop current routing:
m_router - > FixRoute ( m_endSnapPoint , m_endItem , true ) ;
2016-02-12 02:26:40 +00:00
break ;
2013-09-26 21:53:54 +00:00
}
2019-07-01 21:01:33 +00:00
else if ( evt - > IsCancelInteractive ( ) | | evt - > IsActivate ( )
2017-03-07 12:56:44 +00:00
| | evt - > IsUndoRedo ( )
| | evt - > IsAction ( & PCB_ACTIONS : : routerInlineDrag ) )
2019-07-01 21:01:33 +00:00
{
if ( evt - > IsCancelInteractive ( ) & & ! m_router - > RoutingInProgress ( ) )
m_cancelled = true ;
if ( evt - > IsActivate ( ) & & ! evt - > IsMoveTool ( ) )
m_cancelled = true ;
2016-09-23 11:58:33 +00:00
break ;
2019-07-01 21:01:33 +00:00
}
2020-09-24 22:48:46 +00:00
else if ( evt - > IsClick ( BUT_RIGHT ) )
{
m_menu . ShowContextMenu ( selection ( ) ) ;
}
2020-09-19 10:15:25 +00:00
else
2019-11-10 17:47:51 +00:00
{
evt - > SetPassEvent ( ) ;
}
2013-09-18 17:55:16 +00:00
}
2020-02-07 19:57:24 +00:00
m_router - > CommitRouting ( ) ;
m_router - > StopRouting ( ) ;
2015-08-04 21:08:13 +00:00
finishInteractive ( ) ;
2015-02-18 00:29:54 +00:00
}
2013-09-26 21:53:54 +00:00
2015-05-18 11:48:11 +00:00
2015-02-18 00:29:54 +00:00
int ROUTER_TOOL : : DpDimensionsDialog ( const TOOL_EVENT & aEvent )
{
2016-08-29 17:31:13 +00:00
PNS : : SIZES_SETTINGS sizes = m_router - > Sizes ( ) ;
2017-08-03 15:53:07 +00:00
DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg ( frame ( ) , sizes ) ;
2015-02-18 00:29:54 +00:00
2018-06-15 15:12:15 +00:00
if ( settingsDlg . ShowModal ( ) = = wxID_OK )
2014-01-30 16:11:40 +00:00
{
2015-02-18 00:29:54 +00:00
m_router - > UpdateSizes ( sizes ) ;
m_savedSizes = sizes ;
2018-07-22 10:16:40 +00:00
BOARD_DESIGN_SETTINGS & bds = frame ( ) - > GetBoard ( ) - > GetDesignSettings ( ) ;
bds . SetCustomDiffPairWidth ( sizes . DiffPairWidth ( ) ) ;
bds . SetCustomDiffPairGap ( sizes . DiffPairGap ( ) ) ;
bds . SetCustomDiffPairViaGap ( sizes . DiffPairViaGap ( ) ) ;
2015-02-18 16:53:46 +00:00
}
2015-02-18 00:29:54 +00:00
return 0 ;
}
2015-05-18 11:48:11 +00:00
2015-02-18 00:29:54 +00:00
int ROUTER_TOOL : : SettingsDialog ( const TOOL_EVENT & aEvent )
{
2017-08-03 15:53:07 +00:00
DIALOG_PNS_SETTINGS settingsDlg ( frame ( ) , m_router - > Settings ( ) ) ;
2015-02-18 00:29:54 +00:00
2020-01-13 01:44:19 +00:00
settingsDlg . ShowModal ( ) ;
2017-01-18 08:04:11 +00:00
2015-02-18 00:29:54 +00:00
return 0 ;
}
2014-01-30 10:32:08 +00:00
2015-02-18 00:29:54 +00:00
2020-04-19 14:39:16 +00:00
int ROUTER_TOOL : : ChangeRouterMode ( const TOOL_EVENT & aEvent )
{
PNS : : PNS_MODE mode = aEvent . Parameter < PNS : : PNS_MODE > ( ) ;
PNS : : ROUTING_SETTINGS & settings = m_router - > Settings ( ) ;
settings . SetMode ( mode ) ;
return 0 ;
}
2020-06-23 10:44:39 +00:00
PNS : : PNS_MODE ROUTER_TOOL : : GetRouterMode ( )
{
return m_router - > Settings ( ) . Mode ( ) ;
}
2017-08-03 15:53:07 +00:00
void ROUTER_TOOL : : breakTrack ( )
{
2018-02-27 03:15:58 +00:00
if ( m_startItem & & m_startItem - > OfKind ( PNS : : ITEM : : SEGMENT_T ) )
2017-08-03 15:53:07 +00:00
m_router - > BreakSegment ( m_startItem , m_startSnapPoint ) ;
}
2015-05-18 11:48:11 +00:00
2018-02-27 03:15:58 +00:00
2019-06-24 15:27:05 +00:00
int ROUTER_TOOL : : MainLoop ( const TOOL_EVENT & aEvent )
2013-09-18 17:55:16 +00:00
{
2019-06-24 15:27:05 +00:00
PNS : : ROUTER_MODE mode = aEvent . Parameter < PNS : : ROUTER_MODE > ( ) ;
PCB_EDIT_FRAME * frame = getEditFrame < PCB_EDIT_FRAME > ( ) ;
2021-09-13 12:23:10 +00:00
VIEW_CONTROLS * controls = getViewControls ( ) ;
2013-09-18 17:55:16 +00:00
2020-12-07 23:58:51 +00:00
if ( m_router - > RoutingInProgress ( ) )
{
if ( m_router - > Mode ( ) = = mode )
return 0 ;
else
m_router - > StopRouting ( ) ;
}
2014-05-14 17:15:25 +00:00
// Deselect all items
2017-02-21 12:42:08 +00:00
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionClear , true ) ;
2014-05-14 17:15:25 +00:00
2019-07-15 12:15:58 +00:00
std : : string tool = aEvent . GetCommandStr ( ) . get ( ) ;
frame - > PushTool ( tool ) ;
2019-06-24 15:27:05 +00:00
2020-10-20 19:05:04 +00:00
auto setCursor =
[ & ] ( )
{
2020-10-08 02:47:01 +00:00
frame - > GetCanvas ( ) - > SetCurrentCursor ( KICURSOR : : PENCIL ) ;
} ;
2021-09-13 12:23:10 +00:00
Activate ( ) ;
// Must be done after Activate() so that it gets set into the correct context
controls - > ShowCursor ( true ) ;
controls - > ForceCursorPosition ( false ) ;
2020-10-08 02:47:01 +00:00
// Set initial cursor
setCursor ( ) ;
2021-09-13 12:23:10 +00:00
m_router - > SetMode ( mode ) ;
m_cancelled = false ;
// Prime the pump
if ( aEvent . HasPosition ( ) )
m_toolMgr - > PrimeTool ( controls - > GetCursorPosition ( false ) ) ;
2013-09-18 17:55:16 +00:00
// Main loop: keep receiving events
2019-06-17 13:43:22 +00:00
while ( TOOL_EVENT * evt = Wait ( ) )
2013-09-18 17:55:16 +00:00
{
2020-10-08 02:47:01 +00:00
setCursor ( ) ;
2019-06-27 21:33:48 +00:00
2019-07-01 21:01:33 +00:00
if ( evt - > IsCancelInteractive ( ) )
2016-08-15 15:16:50 +00:00
{
2019-07-15 12:15:58 +00:00
frame - > PopTool ( tool ) ;
2019-07-01 21:01:33 +00:00
break ;
}
else if ( evt - > IsActivate ( ) )
{
if ( evt - > IsMoveTool ( ) )
{
// leave ourselves on the stack so we come back after the move
break ;
}
else
{
2019-07-15 12:15:58 +00:00
frame - > PopTool ( tool ) ;
2019-07-01 21:01:33 +00:00
break ;
}
2016-08-15 15:16:50 +00:00
}
2016-09-23 09:31:36 +00:00
else if ( evt - > Action ( ) = = TA_UNDO_REDO_PRE )
{
m_router - > ClearWorld ( ) ;
}
2016-11-28 14:45:37 +00:00
else if ( evt - > Action ( ) = = TA_UNDO_REDO_POST | | evt - > Action ( ) = = TA_MODEL_CHANGE )
2016-08-15 15:16:50 +00:00
{
m_router - > SyncWorld ( ) ;
}
2013-09-26 21:53:54 +00:00
else if ( evt - > IsMotion ( ) )
2016-08-15 15:16:50 +00:00
{
2013-09-18 17:55:16 +00:00
updateStartItem ( * evt ) ;
2016-08-15 15:16:50 +00:00
}
2017-08-03 15:53:07 +00:00
else if ( evt - > IsAction ( & PCB_ACTIONS : : dragFreeAngle ) )
{
2018-03-16 18:00:57 +00:00
updateStartItem ( * evt , true ) ;
2017-08-03 15:53:07 +00:00
performDragging ( PNS : : DM_ANY | PNS : : DM_FREE_ANGLE ) ;
}
else if ( evt - > IsAction ( & PCB_ACTIONS : : drag45Degree ) )
{
2018-03-16 18:00:57 +00:00
updateStartItem ( * evt , true ) ;
2017-08-03 15:53:07 +00:00
performDragging ( PNS : : DM_ANY ) ;
}
else if ( evt - > IsAction ( & PCB_ACTIONS : : breakTrack ) )
{
2018-03-16 18:00:57 +00:00
updateStartItem ( * evt , true ) ;
2017-08-03 15:53:07 +00:00
breakTrack ( ) ;
}
2019-06-24 15:27:05 +00:00
else if ( evt - > IsClick ( BUT_LEFT )
| | evt - > IsAction ( & PCB_ACTIONS : : routeSingleTrack )
| | evt - > IsAction ( & PCB_ACTIONS : : routeDiffPair ) )
2013-09-18 17:55:16 +00:00
{
updateStartItem ( * evt ) ;
2019-07-01 21:01:33 +00:00
if ( evt - > HasPosition ( ) )
{
2021-05-09 19:17:01 +00:00
if ( evt - > Modifier ( MD_SHIFT ) )
2019-07-01 21:01:33 +00:00
performDragging ( PNS : : DM_ANY ) ;
else
performRouting ( ) ;
}
2014-07-09 11:50:27 +00:00
}
2015-09-03 16:25:48 +00:00
else if ( evt - > IsAction ( & ACT_PlaceThroughVia ) )
{
2017-02-21 12:42:08 +00:00
m_toolMgr - > RunAction ( PCB_ACTIONS : : layerToggle , true ) ;
2015-09-03 16:25:48 +00:00
}
2019-07-26 18:16:44 +00:00
else if ( evt - > IsAction ( & PCB_ACTIONS : : layerChanged ) )
{
m_router - > SwitchLayer ( frame - > GetActiveLayer ( ) ) ;
updateStartItem ( * evt ) ;
}
else if ( evt - > IsKeyPressed ( ) )
{
// wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
// event so we need to process the wxEVT_CHAR event that will follow as long as we
// pass the event.
evt - > SetPassEvent ( ) ;
}
2020-09-24 22:48:46 +00:00
else if ( evt - > IsClick ( BUT_RIGHT ) )
{
m_menu . ShowContextMenu ( selection ( ) ) ;
}
2020-10-05 22:16:37 +00:00
else
{
evt - > SetPassEvent ( ) ;
}
2019-07-01 21:01:33 +00:00
if ( m_cancelled )
{
2019-07-15 12:15:58 +00:00
frame - > PopTool ( tool ) ;
2019-07-01 21:01:33 +00:00
break ;
}
2014-05-14 13:53:54 +00:00
}
2013-09-18 17:55:16 +00:00
2014-05-14 16:45:59 +00:00
// Store routing settings till the next invocation
2015-02-18 00:29:54 +00:00
m_savedSizes = m_router - > Sizes ( ) ;
2021-01-04 17:51:50 +00:00
m_router - > ClearViewDecorations ( ) ;
2014-05-14 13:53:54 +00:00
2013-09-18 17:55:16 +00:00
return 0 ;
}
2014-05-14 13:53:54 +00:00
2015-05-18 11:48:11 +00:00
2017-08-03 15:53:07 +00:00
void ROUTER_TOOL : : performDragging ( int aMode )
2014-05-14 13:53:54 +00:00
{
2021-01-04 17:51:50 +00:00
m_router - > ClearViewDecorations ( ) ;
2014-05-14 13:53:54 +00:00
VIEW_CONTROLS * ctls = getViewControls ( ) ;
2016-08-15 15:16:53 +00:00
if ( m_startItem & & m_startItem - > IsLocked ( ) )
2016-08-15 15:16:50 +00:00
{
2018-07-10 14:33:04 +00:00
KIDIALOG dlg ( frame ( ) , _ ( " The selected item is locked. " ) , _ ( " Confirmation " ) ,
wxOK | wxCANCEL | wxICON_WARNING ) ;
dlg . SetOKLabel ( _ ( " Drag Anyway " ) ) ;
2018-08-29 22:37:20 +00:00
dlg . DoNotShowCheckbox ( __FILE__ , __LINE__ ) ;
2018-07-10 14:33:04 +00:00
if ( dlg . ShowModal ( ) = = wxID_CANCEL )
2016-08-15 15:16:50 +00:00
return ;
}
2017-08-03 15:53:07 +00:00
bool dragStarted = m_router - > StartDragging ( m_startSnapPoint , m_startItem , aMode ) ;
2014-06-24 16:17:18 +00:00
2014-05-16 11:37:31 +00:00
if ( ! dragStarted )
2014-05-14 13:53:54 +00:00
return ;
2021-03-29 21:45:07 +00:00
if ( m_startItem & & m_startItem - > Net ( ) > 0 )
2014-05-14 13:53:54 +00:00
highlightNet ( true , m_startItem - > Net ( ) ) ;
ctls - > SetAutoPan ( true ) ;
2019-07-15 23:44:01 +00:00
m_gridHelper - > SetAuxAxes ( true , m_startSnapPoint ) ;
2017-08-03 15:53:07 +00:00
frame ( ) - > UndoRedoBlock ( true ) ;
2016-09-29 16:59:11 +00:00
2019-06-17 13:43:22 +00:00
while ( TOOL_EVENT * evt = Wait ( ) )
2014-05-14 13:53:54 +00:00
{
2015-11-03 16:19:42 +00:00
ctls - > ForceCursorPosition ( false ) ;
2016-09-23 11:58:33 +00:00
if ( evt - > IsMotion ( ) )
2014-05-14 13:53:54 +00:00
{
updateEndItem ( * evt ) ;
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
}
else if ( evt - > IsClick ( BUT_LEFT ) )
{
if ( m_router - > FixRoute ( m_endSnapPoint , m_endItem ) )
break ;
}
2020-09-24 22:48:46 +00:00
else if ( evt - > IsClick ( BUT_RIGHT ) )
{
m_menu . ShowContextMenu ( selection ( ) ) ;
}
2019-07-01 21:01:33 +00:00
else if ( evt - > IsCancelInteractive ( ) | | evt - > IsActivate ( ) | | evt - > IsUndoRedo ( ) )
2018-11-19 15:54:36 +00:00
{
2019-07-01 21:01:33 +00:00
if ( evt - > IsCancelInteractive ( ) & & ! m_startItem )
m_cancelled = true ;
if ( evt - > IsActivate ( ) & & ! evt - > IsMoveTool ( ) )
m_cancelled = true ;
2016-09-23 11:58:33 +00:00
break ;
2018-11-19 15:54:36 +00:00
}
2020-10-05 22:16:37 +00:00
else
{
evt - > SetPassEvent ( ) ;
}
2014-05-16 11:37:31 +00:00
handleCommonEvents ( * evt ) ;
2014-05-14 13:53:54 +00:00
}
if ( m_router - > RoutingInProgress ( ) )
m_router - > StopRouting ( ) ;
2017-08-29 16:47:55 +00:00
m_startItem = nullptr ;
2015-08-04 09:37:16 +00:00
2019-04-01 13:22:51 +00:00
m_gridHelper - > SetAuxAxes ( false ) ;
2017-08-03 15:53:07 +00:00
frame ( ) - > UndoRedoBlock ( false ) ;
2014-05-14 13:53:54 +00:00
ctls - > SetAutoPan ( false ) ;
ctls - > ForceCursorPosition ( false ) ;
highlightNet ( false ) ;
}
2015-02-18 00:29:54 +00:00
2015-05-18 11:48:11 +00:00
2018-01-05 23:44:37 +00:00
void ROUTER_TOOL : : NeighboringSegmentFilter ( const VECTOR2I & aPt , GENERAL_COLLECTOR & aCollector )
{
2018-09-23 22:35:37 +00:00
/*
* If the collection contains a trivial line corner ( two connected segments )
2018-01-05 23:44:37 +00:00
* or a non - fanout - via ( a via with no more than two connected segments ) , then
* trim the collection down to a single item ( which one won ' t matter since
* they ' re all connected ) .
*/
// First make sure we've got something that *might* match.
int vias = aCollector . CountType ( PCB_VIA_T ) ;
int traces = aCollector . CountType ( PCB_TRACE_T ) ;
2019-05-17 00:13:21 +00:00
int arcs = aCollector . CountType ( PCB_ARC_T ) ;
2018-01-05 23:44:37 +00:00
2019-05-17 00:13:21 +00:00
if ( arcs > 0 | | vias > 1 | | traces > 2 | | vias + traces < 1 )
2018-01-05 23:44:37 +00:00
return ;
2021-06-11 21:07:02 +00:00
// Fetch first PCB_TRACK (via or trace) as our reference
PCB_TRACK * reference = nullptr ;
2018-01-05 23:44:37 +00:00
for ( int i = 0 ; ! reference & & i < aCollector . GetCount ( ) ; i + + )
2021-06-11 21:07:02 +00:00
reference = dynamic_cast < PCB_TRACK * > ( aCollector [ i ] ) ;
2018-01-05 23:44:37 +00:00
int refNet = reference - > GetNetCode ( ) ;
2018-09-23 22:35:37 +00:00
wxPoint refPoint ( aPt . x , aPt . y ) ;
2021-06-08 03:06:11 +00:00
EDA_ITEM_FLAGS flags = reference - > IsPointOnEnds ( refPoint , - 1 ) ;
2018-01-05 23:44:37 +00:00
if ( flags & STARTPOINT )
refPoint = reference - > GetStart ( ) ;
else if ( flags & ENDPOINT )
refPoint = reference - > GetEnd ( ) ;
2018-09-23 22:35:37 +00:00
// Check all items to ensure that any TRACKs are co-terminus with the reference and on
// the same net.
2018-01-05 23:44:37 +00:00
for ( int i = 0 ; i < aCollector . GetCount ( ) ; i + + )
{
2021-06-11 21:07:02 +00:00
PCB_TRACK * neighbor = dynamic_cast < PCB_TRACK * > ( aCollector [ i ] ) ;
2018-01-05 23:44:37 +00:00
2018-09-23 22:35:37 +00:00
if ( neighbor & & neighbor ! = reference )
{
if ( neighbor - > GetNetCode ( ) ! = refNet )
return ;
2018-01-05 23:44:37 +00:00
2018-09-23 22:35:37 +00:00
if ( neighbor - > GetStart ( ) ! = refPoint & & neighbor - > GetEnd ( ) ! = refPoint )
return ;
}
2018-01-05 23:44:37 +00:00
}
// Selection meets criteria; trim it to the reference item.
2018-09-23 22:35:37 +00:00
aCollector . Empty ( ) ;
aCollector . Append ( reference ) ;
2018-01-05 23:44:37 +00:00
}
2021-01-27 19:55:42 +00:00
bool ROUTER_TOOL : : CanInlineDrag ( int aDragMode )
2018-01-05 23:44:37 +00:00
{
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionCursor , true , NeighboringSegmentFilter ) ;
2020-12-16 13:31:32 +00:00
const PCB_SELECTION & selection = m_toolMgr - > GetTool < PCB_SELECTION_TOOL > ( ) - > GetSelection ( ) ;
2018-01-05 23:44:37 +00:00
if ( selection . Size ( ) = = 1 )
{
2020-02-28 22:16:55 +00:00
const BOARD_ITEM * item = static_cast < const BOARD_ITEM * > ( selection . Front ( ) ) ;
2018-02-14 14:33:15 +00:00
2021-01-27 19:55:42 +00:00
// Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using
// DragArcTrack(), so PCB_ARC_T should never occur here.
if ( item - > IsType ( GENERAL_COLLECTOR : : DraggableItems ) )
2020-11-13 12:21:02 +00:00
{
2021-01-27 19:55:42 +00:00
static const KICAD_T footprints [ ] = { PCB_FOOTPRINT_T , EOT } ;
// Footprints cannot be dragged freely.
if ( item - > IsType ( footprints ) )
return ! ( aDragMode & PNS : : DM_FREE_ANGLE ) ;
else
return true ;
2020-11-13 12:21:02 +00:00
}
2018-01-05 23:44:37 +00:00
}
return false ;
}
2015-05-18 11:48:11 +00:00
int ROUTER_TOOL : : InlineDrag ( const TOOL_EVENT & aEvent )
2015-02-18 00:29:54 +00:00
{
2020-12-16 13:31:32 +00:00
const PCB_SELECTION & selection = m_toolMgr - > GetTool < PCB_SELECTION_TOOL > ( ) - > GetSelection ( ) ;
2015-07-02 14:09:56 +00:00
2018-02-14 14:33:15 +00:00
if ( selection . Empty ( ) )
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionCursor , true , NeighboringSegmentFilter ) ;
2017-02-09 11:03:07 +00:00
if ( selection . Size ( ) ! = 1 )
return 0 ;
2021-09-22 02:38:53 +00:00
BOARD_ITEM * item = static_cast < BOARD_ITEM * > ( selection . Front ( ) ) ;
2017-02-09 11:03:07 +00:00
2020-11-13 12:21:02 +00:00
if ( item - > Type ( ) ! = PCB_TRACE_T
& & item - > Type ( ) ! = PCB_VIA_T
& & item - > Type ( ) ! = PCB_FOOTPRINT_T )
{
2017-02-09 11:03:07 +00:00
return 0 ;
2020-11-13 12:21:02 +00:00
}
2015-07-02 14:09:56 +00:00
2021-09-22 02:38:53 +00:00
// If we overrode locks, we want to clear the flag from the source item before SyncWorld is
// called so that virtual vias are not generated for the (now unlocked) track segment. Note in
// this case the lock can't be reliably re-applied, because there is no guarantee that the end
// state of the drag results in the same number of segments so it's not clear which segment to
// apply the lock state to.
bool wasLocked = false ;
if ( item - > IsLocked ( ) )
{
wasLocked = true ;
item - > SetLocked ( false ) ;
}
2015-07-02 14:09:56 +00:00
Activate ( ) ;
2017-02-21 12:42:08 +00:00
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionClear , true ) ;
2015-07-02 14:09:56 +00:00
m_router - > SyncWorld ( ) ;
2020-02-28 22:16:55 +00:00
m_startItem = nullptr ;
2015-07-02 14:09:56 +00:00
2020-02-28 22:16:55 +00:00
PNS : : ITEM * startItem = nullptr ;
PNS : : ITEM_SET itemsToDrag ;
2020-11-13 15:15:52 +00:00
const FOOTPRINT * footprint = nullptr ;
2020-02-28 22:16:55 +00:00
2020-11-13 12:21:02 +00:00
if ( item - > Type ( ) = = PCB_FOOTPRINT_T )
2020-02-28 22:16:55 +00:00
{
2020-11-13 15:15:52 +00:00
footprint = static_cast < const FOOTPRINT * > ( item ) ;
2020-08-01 13:20:08 +00:00
2020-11-13 15:15:52 +00:00
for ( const PAD * pad : footprint - > Pads ( ) )
2020-02-28 22:16:55 +00:00
{
2020-08-01 13:20:08 +00:00
PNS : : ITEM * solid = m_router - > GetWorld ( ) - > FindItemByParent ( pad ) ;
2020-03-02 15:26:46 +00:00
if ( solid )
itemsToDrag . Add ( solid ) ;
2020-02-28 22:16:55 +00:00
}
}
else
{
2020-10-17 12:52:18 +00:00
startItem = m_router - > GetWorld ( ) - > FindItemByParent ( item ) ;
2020-03-02 15:26:46 +00:00
2020-12-20 16:13:01 +00:00
if ( startItem )
2020-03-02 15:26:46 +00:00
itemsToDrag . Add ( startItem ) ;
2020-02-28 22:16:55 +00:00
}
2020-12-11 13:11:20 +00:00
GAL * gal = m_toolMgr - > GetView ( ) - > GetGAL ( ) ;
2019-01-28 05:14:34 +00:00
VECTOR2I p0 = controls ( ) - > GetCursorPosition ( false ) ;
2020-02-28 22:16:55 +00:00
VECTOR2I p = p0 ;
2021-05-09 19:17:01 +00:00
m_gridHelper - > SetUseGrid ( gal - > GetGridSnapping ( ) & & ! aEvent . DisableGridSnapping ( ) ) ;
2020-12-11 13:11:20 +00:00
m_gridHelper - > SetSnap ( ! aEvent . Modifier ( MD_SHIFT ) ) ;
2020-02-28 22:16:55 +00:00
if ( startItem )
2020-12-20 16:13:01 +00:00
{
2020-12-11 13:11:20 +00:00
p = snapToItem ( startItem , p0 ) ;
2020-12-20 16:13:01 +00:00
m_startItem = startItem ;
}
2020-12-20 20:15:48 +00:00
else if ( footprint )
{
2020-12-27 17:43:52 +00:00
// The mouse is going to be moved on grid before dragging begins.
VECTOR2I tweakedMousePos ;
PCB_BASE_EDIT_FRAME * editFrame = getEditFrame < PCB_BASE_EDIT_FRAME > ( ) ;
// Check if user wants to warp the mouse to origin of moved object
if ( editFrame - > GetMoveWarpsCursor ( ) )
tweakedMousePos = footprint - > GetPosition ( ) ; // Use footprint anchor to warp mouse
else
tweakedMousePos = controls ( ) - > GetCursorPosition ( ) ; // Just use current mouse pos
// We tweak the mouse position using the value from above, and then use that as the
// start position to prevent the footprint from jumping when we start dragging.
2021-01-27 22:15:38 +00:00
// First we move the visual cross hair cursor...
2020-12-27 17:43:52 +00:00
controls ( ) - > ForceCursorPosition ( true , tweakedMousePos ) ;
controls ( ) - > SetCursorPosition ( tweakedMousePos ) ; // ...then the mouse pointer
// Now that the mouse is in the right position, get a copy of the position to use later
p = controls ( ) - > GetCursorPosition ( ) ;
2020-12-20 20:15:48 +00:00
}
2020-02-28 22:16:55 +00:00
2017-08-03 15:53:07 +00:00
int dragMode = aEvent . Parameter < int64_t > ( ) ;
2015-07-02 14:09:56 +00:00
2020-02-28 22:16:55 +00:00
bool dragStarted = m_router - > StartDragging ( p , itemsToDrag , dragMode ) ;
2015-07-02 14:09:56 +00:00
if ( ! dragStarted )
2021-09-22 02:38:53 +00:00
{
if ( wasLocked )
item - > SetLocked ( true ) ;
2015-07-02 14:09:56 +00:00
return 0 ;
2021-09-22 02:38:53 +00:00
}
2015-07-02 14:09:56 +00:00
2019-07-15 23:44:01 +00:00
m_gridHelper - > SetAuxAxes ( true , p ) ;
2017-08-03 15:53:07 +00:00
controls ( ) - > ShowCursor ( true ) ;
controls ( ) - > SetAutoPan ( true ) ;
frame ( ) - > UndoRedoBlock ( true ) ;
2015-07-02 14:09:56 +00:00
2020-08-15 20:13:08 +00:00
view ( ) - > ClearPreview ( ) ;
view ( ) - > InitPreview ( ) ;
2020-10-20 19:05:04 +00:00
auto setCursor =
[ & ] ( )
{
2020-10-08 02:47:01 +00:00
frame ( ) - > GetCanvas ( ) - > SetCurrentCursor ( KICURSOR : : ARROW ) ;
} ;
// Set initial cursor
setCursor ( ) ;
2021-04-10 20:13:01 +00:00
// Set the initial visible area
BOX2D viewAreaD = getView ( ) - > GetGAL ( ) - > GetVisibleWorldExtents ( ) ;
m_router - > SetVisibleViewArea ( BOX2I ( viewAreaD . GetOrigin ( ) , viewAreaD . GetSize ( ) ) ) ;
2021-03-29 23:41:17 +00:00
// Send an initial movement to prime the collision detection
m_router - > Move ( p , nullptr ) ;
2021-07-05 19:25:04 +00:00
bool hasMouseMoved = false ;
2019-06-17 13:43:22 +00:00
while ( TOOL_EVENT * evt = Wait ( ) )
2015-07-02 14:09:56 +00:00
{
2020-10-08 02:47:01 +00:00
setCursor ( ) ;
2019-06-27 21:33:48 +00:00
2019-07-01 21:01:33 +00:00
if ( evt - > IsCancelInteractive ( ) )
2015-07-02 14:09:56 +00:00
{
2021-09-22 02:38:53 +00:00
if ( wasLocked )
item - > SetLocked ( true ) ;
2015-07-02 14:09:56 +00:00
break ;
}
else if ( evt - > IsMotion ( ) | | evt - > IsDrag ( BUT_LEFT ) )
{
2021-07-05 19:25:04 +00:00
hasMouseMoved = true ;
2016-09-29 16:59:11 +00:00
updateEndItem ( * evt ) ;
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
2020-08-01 13:20:08 +00:00
2020-11-13 15:15:52 +00:00
if ( footprint )
2020-08-01 13:20:08 +00:00
{
VECTOR2I offset = m_endSnapPoint - p ;
BOARD_ITEM * previewItem ;
view ( ) - > ClearPreview ( ) ;
2020-11-13 15:15:52 +00:00
for ( BOARD_ITEM * drawing : footprint - > GraphicalItems ( ) )
2020-08-01 13:20:08 +00:00
{
previewItem = static_cast < BOARD_ITEM * > ( drawing - > Clone ( ) ) ;
2020-08-02 11:01:17 +00:00
2020-10-04 14:19:33 +00:00
if ( drawing - > Type ( ) = = PCB_FP_SHAPE_T )
2020-08-03 22:49:12 +00:00
{
2020-10-04 23:34:59 +00:00
FP_SHAPE * shape = static_cast < FP_SHAPE * > ( previewItem ) ;
2021-02-19 00:31:31 +00:00
wxPoint fp_offset = wxPoint ( offset . Rotate ( footprint - > GetOrientationRadians ( ) ) ) ;
shape - > FP_SHAPE : : Move ( fp_offset ) ;
2020-08-03 22:49:12 +00:00
}
2020-08-02 11:01:17 +00:00
else
2020-08-03 22:49:12 +00:00
{
2020-08-02 11:01:17 +00:00
previewItem - > Move ( offset ) ;
2020-08-03 22:49:12 +00:00
}
2020-08-02 11:01:17 +00:00
2020-08-01 13:20:08 +00:00
view ( ) - > AddToPreview ( previewItem ) ;
view ( ) - > Hide ( drawing , true ) ;
}
2020-11-13 15:15:52 +00:00
previewItem = static_cast < BOARD_ITEM * > ( footprint - > Reference ( ) . Clone ( ) ) ;
2020-08-01 13:20:08 +00:00
previewItem - > Move ( offset ) ;
view ( ) - > AddToPreview ( previewItem ) ;
2020-11-13 15:15:52 +00:00
view ( ) - > Hide ( & footprint - > Reference ( ) ) ;
2020-08-01 13:20:08 +00:00
2020-11-13 15:15:52 +00:00
previewItem = static_cast < BOARD_ITEM * > ( footprint - > Value ( ) . Clone ( ) ) ;
2020-08-01 13:20:08 +00:00
previewItem - > Move ( offset ) ;
view ( ) - > AddToPreview ( previewItem ) ;
2020-11-13 15:15:52 +00:00
view ( ) - > Hide ( & footprint - > Value ( ) ) ;
2020-08-26 21:51:19 +00:00
2020-11-13 15:15:52 +00:00
for ( ZONE * zone : footprint - > Zones ( ) )
2020-08-26 21:51:19 +00:00
{
previewItem = static_cast < BOARD_ITEM * > ( zone - > Clone ( ) ) ;
previewItem - > Move ( offset ) ;
view ( ) - > AddToPreview ( previewItem ) ;
view ( ) - > Hide ( zone , true ) ;
}
2020-08-01 13:20:08 +00:00
}
2015-07-02 14:09:56 +00:00
}
2021-07-05 19:39:42 +00:00
else if ( hasMouseMoved & & ( evt - > IsMouseUp ( BUT_LEFT ) | | evt - > IsClick ( BUT_LEFT ) ) )
2015-07-02 14:09:56 +00:00
{
2016-09-29 16:59:11 +00:00
updateEndItem ( * evt ) ;
m_router - > FixRoute ( m_endSnapPoint , m_endItem ) ;
2015-07-02 14:09:56 +00:00
break ;
}
2020-08-04 13:31:31 +00:00
else if ( evt - > Category ( ) = = TC_COMMAND )
{
2020-08-05 15:01:10 +00:00
// disallow editing commands
if ( evt - > IsAction ( & ACTIONS : : cut )
2020-08-04 13:31:31 +00:00
| | evt - > IsAction ( & ACTIONS : : copy )
| | evt - > IsAction ( & ACTIONS : : paste )
2020-08-05 15:01:10 +00:00
| | evt - > IsAction ( & ACTIONS : : pasteSpecial ) )
2020-08-04 13:31:31 +00:00
{
wxBell ( ) ;
}
2020-12-06 12:22:17 +00:00
else
{
evt - > SetPassEvent ( ) ;
}
}
else
{
evt - > SetPassEvent ( ) ;
2020-08-04 13:31:31 +00:00
}
2021-02-11 22:08:46 +00:00
handleCommonEvents ( * evt ) ;
2015-07-02 14:09:56 +00:00
}
2020-11-13 15:15:52 +00:00
if ( footprint )
2020-08-01 13:20:08 +00:00
{
2020-11-13 15:15:52 +00:00
for ( BOARD_ITEM * drawing : footprint - > GraphicalItems ( ) )
2020-08-01 13:20:08 +00:00
view ( ) - > Hide ( drawing , false ) ;
2020-11-13 15:15:52 +00:00
view ( ) - > Hide ( & footprint - > Reference ( ) , false ) ;
view ( ) - > Hide ( & footprint - > Value ( ) , false ) ;
2020-08-01 13:20:08 +00:00
2020-11-13 15:15:52 +00:00
for ( ZONE * zone : footprint - > Zones ( ) )
2020-08-26 21:51:19 +00:00
view ( ) - > Hide ( zone , false ) ;
2020-08-01 13:20:08 +00:00
view ( ) - > ClearPreview ( ) ;
view ( ) - > ShowPreview ( false ) ;
}
2015-07-10 10:14:27 +00:00
if ( m_router - > RoutingInProgress ( ) )
m_router - > StopRouting ( ) ;
2019-04-01 13:22:51 +00:00
m_gridHelper - > SetAuxAxes ( false ) ;
2018-06-13 04:11:21 +00:00
controls ( ) - > SetAutoPan ( false ) ;
controls ( ) - > ForceCursorPosition ( false ) ;
2017-08-03 15:53:07 +00:00
frame ( ) - > UndoRedoBlock ( false ) ;
2015-07-02 14:09:56 +00:00
2015-02-18 00:29:54 +00:00
return 0 ;
}
2017-01-18 08:04:11 +00:00
2018-12-14 03:43:51 +00:00
int ROUTER_TOOL : : InlineBreakTrack ( const TOOL_EVENT & aEvent )
{
2020-12-16 13:31:32 +00:00
const SELECTION & selection = m_toolMgr - > GetTool < PCB_SELECTION_TOOL > ( ) - > GetSelection ( ) ;
2018-12-14 03:43:51 +00:00
if ( selection . Size ( ) ! = 1 )
return 0 ;
2021-01-27 22:15:38 +00:00
const BOARD_CONNECTED_ITEM * item =
static_cast < const BOARD_CONNECTED_ITEM * > ( selection . Front ( ) ) ;
2018-12-14 03:43:51 +00:00
if ( item - > Type ( ) ! = PCB_TRACE_T )
return 0 ;
Activate ( ) ;
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionClear , true ) ;
m_router - > SyncWorld ( ) ;
m_startItem = m_router - > GetWorld ( ) - > FindItemByParent ( item ) ;
2020-09-26 06:44:14 +00:00
TOOL_MANAGER * toolManager = frame ( ) - > GetToolManager ( ) ;
2020-12-11 13:11:20 +00:00
GAL * gal = toolManager - > GetView ( ) - > GetGAL ( ) ;
2021-05-09 19:17:01 +00:00
m_gridHelper - > SetUseGrid ( gal - > GetGridSnapping ( ) & & ! aEvent . DisableGridSnapping ( ) ) ;
2020-12-11 13:11:20 +00:00
m_gridHelper - > SetSnap ( ! aEvent . Modifier ( MD_SHIFT ) ) ;
2020-09-26 06:44:14 +00:00
if ( toolManager - > IsContextMenuActive ( ) )
{
// If we're here from a context menu then we need to get the position of the
// cursor when the context menu was invoked. This is used to figure out the
// break point on the track.
2020-12-11 13:11:20 +00:00
m_startSnapPoint = snapToItem ( m_startItem , toolManager - > GetMenuCursorPos ( ) ) ;
2020-09-26 06:44:14 +00:00
}
else
{
// If we're here from a hotkey, then get the current mouse position so we know
// where to break the track.
2020-12-11 13:11:20 +00:00
m_startSnapPoint = snapToItem ( m_startItem , controls ( ) - > GetCursorPosition ( ) ) ;
2020-09-26 06:44:14 +00:00
}
2018-12-14 03:43:51 +00:00
if ( m_startItem & & m_startItem - > IsLocked ( ) )
{
KIDIALOG dlg ( frame ( ) , _ ( " The selected item is locked. " ) , _ ( " Confirmation " ) ,
wxOK | wxCANCEL | wxICON_WARNING ) ;
dlg . SetOKLabel ( _ ( " Break Track " ) ) ;
dlg . DoNotShowCheckbox ( __FILE__ , __LINE__ ) ;
if ( dlg . ShowModal ( ) = = wxID_CANCEL )
return 0 ;
}
frame ( ) - > UndoRedoBlock ( true ) ;
breakTrack ( ) ;
if ( m_router - > RoutingInProgress ( ) )
m_router - > StopRouting ( ) ;
frame ( ) - > UndoRedoBlock ( false ) ;
return 0 ;
}
2017-01-18 08:04:11 +00:00
int ROUTER_TOOL : : CustomTrackWidthDialog ( const TOOL_EVENT & aEvent )
{
2017-08-03 15:53:07 +00:00
BOARD_DESIGN_SETTINGS & bds = board ( ) - > GetDesignSettings ( ) ;
DIALOG_TRACK_VIA_SIZE sizeDlg ( frame ( ) , bds ) ;
2017-01-18 08:04:11 +00:00
2021-02-08 17:39:40 +00:00
if ( sizeDlg . ShowModal ( ) = = wxID_OK )
2017-01-18 08:04:11 +00:00
{
bds . UseCustomTrackViaSize ( true ) ;
2020-08-05 18:36:02 +00:00
TOOL_EVENT dummy ;
onTrackViaSizeChanged ( dummy ) ;
2017-01-18 08:04:11 +00:00
}
return 0 ;
}
int ROUTER_TOOL : : onTrackViaSizeChanged ( const TOOL_EVENT & aEvent )
{
PNS : : SIZES_SETTINGS sizes ( m_router - > Sizes ( ) ) ;
2020-10-09 13:14:54 +00:00
2020-10-09 13:30:55 +00:00
if ( ! m_router - > GetCurrentNets ( ) . empty ( ) )
2021-06-07 00:18:09 +00:00
m_iface - > ImportSizes ( sizes , m_startItem , m_router - > GetCurrentNets ( ) [ 0 ] ) ;
2020-10-09 13:14:54 +00:00
2017-01-18 08:04:11 +00:00
m_router - > UpdateSizes ( sizes ) ;
2019-01-14 12:12:20 +00:00
// Changing the track width can affect the placement, so call the
2018-11-24 19:50:51 +00:00
// move routine without changing the destination
m_router - > Move ( m_endSnapPoint , m_endItem ) ;
2021-07-08 01:26:21 +00:00
updateMessagePanel ( ) ;
2017-01-18 08:04:11 +00:00
return 0 ;
}
2019-06-24 15:27:05 +00:00
2021-07-03 17:21:51 +00:00
void ROUTER_TOOL : : updateMessagePanel ( )
{
if ( ! m_router - > RoutingInProgress ( ) )
{
frame ( ) - > SetMsgPanel ( board ( ) ) ;
return ;
}
2021-09-26 23:22:32 +00:00
std : : vector < MSG_PANEL_ITEM > items ;
2021-07-03 17:21:51 +00:00
PNS : : SIZES_SETTINGS sizes ( m_router - > Sizes ( ) ) ;
PNS : : RULE_RESOLVER * resolver = m_iface - > GetRuleResolver ( ) ;
bool isDiffPair = m_router - > Mode ( ) = = PNS : : ROUTER_MODE : : PNS_MODE_ROUTE_DIFF_PAIR ;
if ( m_startItem & & m_startItem - > Net ( ) > 0 )
{
wxString description = isDiffPair ? _ ( " Routing Diff Pair: %s " ) : _ ( " Routing Track: %s " ) ;
NETINFO_ITEM * netInfo = board ( ) - > FindNet ( m_startItem - > Net ( ) ) ;
wxASSERT ( netInfo ) ;
items . emplace_back ( wxString : : Format ( description , netInfo - > GetNetname ( ) ) ,
wxString : : Format ( _ ( " Net Class: %s " ) , netInfo - > GetNetClassName ( ) ) ) ;
}
else
{
items . emplace_back ( _ ( " Routing Track " ) , _ ( " (no net) " ) ) ;
}
EDA_UNITS units = frame ( ) - > GetUserUnits ( ) ;
int width = isDiffPair ? sizes . DiffPairWidth ( ) : sizes . TrackWidth ( ) ;
items . emplace_back ( wxString : : Format ( _ ( " Track Width: %s " ) ,
MessageTextFromValue ( units , width ) ) ,
wxString : : Format ( _ ( " (from %s) " ) , sizes . GetWidthSource ( ) ) ) ;
if ( m_startItem )
{
PNS : : SEGMENT dummy ;
dummy . SetNet ( m_startItem - > Net ( ) ) ;
PNS : : CONSTRAINT constraint ;
if ( resolver - > QueryConstraint ( PNS : : CONSTRAINT_TYPE : : CT_CLEARANCE , & dummy , nullptr ,
m_router - > GetCurrentLayer ( ) , & constraint ) )
{
items . emplace_back ( wxString : : Format ( _ ( " Min Clearance: %s " ) ,
MessageTextFromValue ( units , constraint . m_Value . Min ( ) ) ) ,
wxString : : Format ( _ ( " (from %s) " ) , constraint . m_RuleName ) ) ;
}
}
if ( isDiffPair )
{
items . emplace_back ( _ ( " Diff Pair Gap " ) ,
MessageTextFromValue ( units , sizes . DiffPairGap ( ) ) ) ;
}
frame ( ) - > SetMsgPanel ( items ) ;
}
2019-06-24 15:27:05 +00:00
void ROUTER_TOOL : : setTransitions ( )
{
Go ( & ROUTER_TOOL : : SelectCopperLayerPair , PCB_ACTIONS : : selectLayerPair . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : MainLoop , PCB_ACTIONS : : routeSingleTrack . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : MainLoop , PCB_ACTIONS : : routeDiffPair . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : DpDimensionsDialog , PCB_ACTIONS : : routerDiffPairDialog . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : SettingsDialog , PCB_ACTIONS : : routerSettingsDialog . MakeEvent ( ) ) ;
2020-04-19 14:39:16 +00:00
Go ( & ROUTER_TOOL : : ChangeRouterMode , PCB_ACTIONS : : routerHighlightMode . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : ChangeRouterMode , PCB_ACTIONS : : routerShoveMode . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : ChangeRouterMode , PCB_ACTIONS : : routerWalkaroundMode . MakeEvent ( ) ) ;
2019-06-24 15:27:05 +00:00
Go ( & ROUTER_TOOL : : InlineDrag , PCB_ACTIONS : : routerInlineDrag . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : InlineBreakTrack , PCB_ACTIONS : : inlineBreakTrack . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onViaCommand , ACT_PlaceThroughVia . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onViaCommand , ACT_PlaceBlindVia . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onViaCommand , ACT_PlaceMicroVia . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onViaCommand , ACT_SelLayerAndPlaceThroughVia . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onViaCommand , ACT_SelLayerAndPlaceBlindVia . MakeEvent ( ) ) ;
2021-06-28 18:16:33 +00:00
Go ( & ROUTER_TOOL : : onViaCommand , ACT_SelLayerAndPlaceMicroVia . MakeEvent ( ) ) ;
2019-06-24 15:27:05 +00:00
2020-12-02 21:16:48 +00:00
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerTop . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner1 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner2 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner3 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner4 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner5 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner6 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner7 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner8 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner9 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner10 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner11 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner12 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner13 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner14 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner15 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner16 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner17 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner18 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner19 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner20 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner21 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner22 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner23 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner24 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner25 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner26 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner27 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner28 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner29 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerInner30 . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerBottom . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerNext . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onLayerCommand , PCB_ACTIONS : : layerPrev . MakeEvent ( ) ) ;
2020-07-03 23:49:19 +00:00
2019-06-24 15:27:05 +00:00
Go ( & ROUTER_TOOL : : CustomTrackWidthDialog , ACT_CustomTrackWidth . MakeEvent ( ) ) ;
Go ( & ROUTER_TOOL : : onTrackViaSizeChanged , PCB_ACTIONS : : trackViaSizeChanged . MakeEvent ( ) ) ;
}