23#include <wx/filedlg.h>
25#include <wx/hyperlink.h>
34using namespace std::placeholders;
103class UI_UPDATE_INTERVAL_GUARD
106 UI_UPDATE_INTERVAL_GUARD(
long aNewInterval ) :
107 m_saved( wxUpdateUIEvent::GetUpdateInterval() )
109 wxUpdateUIEvent::SetUpdateInterval( aNewInterval );
112 ~UI_UPDATE_INTERVAL_GUARD()
114 wxUpdateUIEvent::SetUpdateInterval( m_saved );
149 .Name(
"pcbnew.InteractiveRouter.PlaceVia" )
151 .DefaultHotkey(
'V' )
152 .LegacyHotkeyName(
"Add Through Via" )
153 .FriendlyName(
_(
"Place Through Via" ) )
154 .Tooltip(
_(
"Adds a through-hole via at the end of currently routed track." ) )
160 .Name(
"pcbnew.InteractiveRouter.PlaceBlindVia" )
163 .LegacyHotkeyName(
"Add Blind/Buried Via" )
164 .FriendlyName(
_(
"Place Blind/Buried Via" ) )
165 .Tooltip(
_(
"Adds a blind or buried via at the end of currently routed track.") )
171 .Name(
"pcbnew.InteractiveRouter.PlaceMicroVia" )
173 .DefaultHotkey(
MD_CTRL +
'V' )
174 .LegacyHotkeyName(
"Add MicroVia" )
175 .FriendlyName(
_(
"Place Microvia" ) )
176 .Tooltip(
_(
"Adds a microvia at the end of currently routed track." ) )
182 .Name(
"pcbnew.InteractiveRouter.SelLayerAndPlaceVia" )
184 .DefaultHotkey(
'<' )
185 .LegacyHotkeyName(
"Select Layer and Add Through Via" )
186 .FriendlyName(
_(
"Select Layer and Place Through Via..." ) )
187 .Tooltip(
_(
"Select a layer, then add a through-hole via at the end of currently routed track." ) )
193 .Name(
"pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia" )
195 .DefaultHotkey(
MD_ALT +
'<' )
196 .LegacyHotkeyName(
"Select Layer and Add Blind/Buried Via" )
197 .FriendlyName(
_(
"Select Layer and Place Blind/Buried Via..." ) )
198 .Tooltip(
_(
"Select a layer, then add a blind or buried via at the end of currently routed track." ) )
204 .Name(
"pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia" )
206 .FriendlyName(
_(
"Select Layer and Place Micro Via..." ) )
207 .Tooltip(
_(
"Select a layer, then add a micro via at the end of currently routed track." ) )
213 .Name(
"pcbnew.InteractiveRouter.CustomTrackViaSize" )
215 .DefaultHotkey(
'Q' )
216 .LegacyHotkeyName(
"Custom Track/Via Size" )
217 .FriendlyName(
_(
"Custom Track/Via Size..." ) )
218 .Tooltip(
_(
"Shows a dialog for changing the track width and via size." ) )
222 .Name(
"pcbnew.InteractiveRouter.SwitchPosture" )
224 .DefaultHotkey(
'/' )
225 .LegacyHotkeyName(
"Switch Track Posture" )
226 .FriendlyName(
_(
"Switch Track Posture" ) )
227 .Tooltip(
_(
"Switches posture of the currently routed track." ) )
232 .Name(
"pcbnew.InteractiveRouter.SwitchRoundingToNext" )
234 .DefaultHotkey(
MD_CTRL +
'/' )
235 .FriendlyName(
_(
"Track Corner Mode Switch" ) )
236 .Tooltip(
_(
"Switches between sharp/rounded and 45°/90° corners when routing tracks." ) )
241 .Name(
"pcbnew.InteractiveRouter.SwitchRounding45" )
243 .DefaultHotkey(
MD_CTRL +
'W' )
244 .FriendlyName(
_(
"Track Corner Mode 45" ) )
245 .Tooltip(
_(
"Switch to 45° corner when routing tracks." ) ) );
248 .Name(
"pcbnew.InteractiveRouter.SwitchRounding90" )
251 .FriendlyName(
_(
"Track Corner Mode 90" ) )
252 .Tooltip(
_(
"Switch to 90° corner when routing tracks." ) ) );
255 .Name(
"pcbnew.InteractiveRouter.SwitchRoundingArc45" )
258 .FriendlyName(
_(
"Track Corner Mode Arc 45" ) )
259 .Tooltip(
_(
"Switch to arc 45° corner when routing tracks." ) ) );
262 .Name(
"pcbnew.InteractiveRouter.SwitchRoundingArc90" )
264 .DefaultHotkey(
MD_ALT +
'W' )
265 .FriendlyName(
_(
"Track Corner Mode Arc 90" ) )
266 .Tooltip(
_(
"Switch to arc 90° corner when routing tracks." ) ) );
269#define _(s) wxGetTranslation((s))
291 SetTitle(
_(
"Select Track/Via Width" ) );
310 _(
"Route using the width of the starting track." ), wxITEM_CHECK );
315 _(
"Use track and via sizes from the net class" ), wxITEM_CHECK );
320 _(
"Specify custom track and via sizes" ), wxITEM_CHECK );
331 msg =
_(
"Track netclass width" );
333 msg.Printf(
_(
"Track %s" ),
m_frame.MessageTextFromValue( width ) );
336 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
347 msg =
_(
"Via netclass values" );
350 if(
via.m_Drill > 0 )
352 msg.Printf(
_(
"Via %s, hole %s" ),
353 m_frame.MessageTextFromValue(
via.m_Diameter ),
354 m_frame.MessageTextFromValue(
via.m_Drill ) );
358 msg.Printf(
_(
"Via %s" ),
359 m_frame.MessageTextFromValue(
via.m_Diameter ) );
364 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
372 int id = aEvent.GetId();
424 SetTitle(
_(
"Select Differential Pair Dimensions" ) );
440 _(
"Use differential pair dimensions from the net class" ), wxITEM_CHECK );
445 _(
"Specify custom differential pair dimensions" ), wxITEM_CHECK );
458 if( diffPair.
m_Gap <= 0 )
462 msg.Printf(
_(
"Width %s" ),
467 msg.Printf(
_(
"Width %s, via gap %s" ),
476 msg.Printf(
_(
"Width %s, gap %s" ),
482 msg.Printf(
_(
"Width %s, gap %s, via gap %s" ),
490 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
498 int id = aEvent.GetId();
542 auto& menu =
m_menu->GetMenu();
543 menu.SetUntranslatedTitle(
_HKI(
"Interactive Router" ) );
563 auto notRoutingCond =
566 return !
m_router->RoutingInProgress();
569 auto inRouteSelected =
578 std::vector<PNS::NET_HANDLE> currentNets =
m_router->GetCurrentNets();
580 if( currentNets.empty() || currentNets[0] ==
nullptr )
587 RN_NET* ratsnest =
board->GetConnectivity()->GetRatsnestForNet( currentNet );
589 return ratsnest && !ratsnest->
GetEdges().empty();
594 menu.AddSeparator( 1 );
597 menu.AddSeparator( haveHighlight, 2 );
622 submenuCornerMode->
SetTitle(
_(
"Track Corner Mode" ) );
632 menu.AddMenu( submenuCornerMode );
635 auto cornerMode45Cond =
641 auto cornerMode90Cond =
647 auto cornerModeArc45Cond =
653 auto cornerModeArc90Cond =
659#define CHECK( x ) ACTION_CONDITIONS().Check( x )
699 static size_t lastLoggerSize = 0;
700 static wxString mruPath;
705 if( !logger || logger->GetEvents().size() == 0
706 || logger->GetEvents().size() == lastLoggerSize )
711 if( !testCaseDir.IsEmpty() )
718 wxFileName
path = wxFileName::DirName( testCaseDir );
722 if(
path.DirExists() )
724 doExit = !
IsOK(
frame(), wxString::Format(
_(
"Test case in directory %s already exists. Overwrite?"),
path.GetFullPath() ) );
728 path.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
731 path.SetName( wxT(
"pns") );
732 logPath =
path.GetFullPath();
741 lastLoggerSize = logger->GetEvents().size();
747 if ( mruPath.IsEmpty() )
752 wxFileDialog dlg(
frame(),
_(
"Save router log" ), mruPath,
"pns.log",
754 wxFD_OVERWRITE_PROMPT | wxFD_SAVE );
758 if( dlg.ShowModal() != wxID_OK )
760 lastLoggerSize = logger->GetEvents().size();
764 logPath = dlg.GetPath();
768 wxFileName fname_log( logPath );
769 mruPath = fname_log.GetPath();
770 fname_log.SetExt(
"log" );
771 wxLogTrace( wxT(
"PNS" ), wxT(
"save log to: %s" ), fname_log.GetFullPath() );
773 wxFileName fname_dump( fname_log );
774 fname_dump.SetExt(
"dump" );
776 wxFileName fname_settings( fname_log );
777 fname_settings.SetExt(
"settings" );
779 FILE* settings_f = wxFopen( fname_settings.GetAbsolutePath(),
"wb" );
783 DisplayError(
frame(), wxString::Format(
_(
"Unable to write '%s'." ), fname_settings.GetAbsolutePath() ) );
787 std::string settingsStr =
m_router->Settings().FormatAsString();
788 fprintf( settings_f,
"%s\n", settingsStr.c_str() );
789 fclose( settings_f );
796 pcb_io.
SaveBoard( fname_dump.GetAbsolutePath(),
m_iface->GetBoard(),
nullptr );
805 wxString srcRules = editFrame->GetBoard()->GetDesignRulesPath();
807 if( !srcRules.IsEmpty() && wxFileName::FileExists( srcRules ) )
809 wxFileName fname_rules( fname_dump );
811 wxCopyFile( srcRules, fname_rules.GetAbsolutePath() );
816 std::vector<PNS::ITEM*> removed;
820 for(
auto item : removed )
825 wxASSERT_MSG( item->Parent() !=
nullptr,
"removed an item with no parent uuid?" );
837 logData.
m_Events = logger->GetEvents();
839 FILE* log_f = wxFopen( fname_log.GetAbsolutePath(),
"wb" );
845 fname_log.GetAbsolutePath() ) );
849 fprintf( log_f,
"%s\n", logString.c_str().AsChar() );
885 bool asChanged =
false;
940 int startLayer =
m_iface->GetPNSLayerFromBoardLayer( tl );
946 return m_iface->GetBoardLayerFromPNSLayer( ls.
Start() );
955 int activeLayer =
m_iface->GetPNSLayerFromBoardLayer(
frame()->GetActiveLayer() );
956 int currentLayer =
m_router->GetCurrentLayer();
958 if( currentLayer != activeLayer )
959 m_router->SwitchLayer( activeLayer );
961 std::optional<int> newLayer =
m_router->Sizes().PairedLayer( currentLayer );
964 newLayer =
m_router->Sizes().GetLayerTop();
977 std::vector<PNS::NET_HANDLE> nets =
m_router->GetCurrentNets();
981 std::shared_ptr<DRC_ENGINE>& drcEngine = bds.
m_DRCEngine;
1010 if( !constraint.
IsNull() )
1038 dummyTrackB.
SetLayer( targetLayer );
1046 if( !constraint.
IsNull() )
1065 if( !constraint.
IsNull() )
1099 wxASSERT_MSG(
false, wxT(
"Unhandled via type" ) );
1123 frame()->SetActiveLayer(
1157 size_t target_idx = 0;
1159 for(
size_t i = 0; i < layers.size(); i++ )
1161 if( layers[i] == currentLayer )
1168 target_idx = ( idx + 1 ) % layers.size();
1171 for(
size_t i = 0; i < layers.size() - 1; i++ )
1175 targetLayer = layers[target_idx];
1180 if( target_idx >= layers.size() )
1195 size_t target_idx = 0;
1197 for(
size_t i = 0; i < layers.size(); i++ )
1199 if( layers[i] == currentLayer )
1206 target_idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers.size() - 1 );
1208 for(
size_t i = 0; i < layers.size() - 1; i++ )
1212 targetLayer = layers[target_idx];
1216 if( target_idx > 0 )
1219 target_idx = layers.size() - 1;
1241 if( !enabledLayers.test( targetLayer ) )
1247 if( targetLayer == currentLayer )
1267 bool selectLayer =
false;
1272 const int actViaFlags = aEvent.
Parameter<
int>();
1287 endPoint =
frame()->GetCanvas()->ClientToScreen( endPoint );
1293 not_allowed_ly.
set( currentLayer );
1295 targetLayer =
frame()->SelectOneLayer(
static_cast<PCB_LAYER_ID>( currentLayer ),
1296 not_allowed_ly, endPoint );
1307 if( currentLayer == targetLayer )
1318 && ( ( targetLayer ==
B_Cu && currentLayer ==
F_Cu )
1319 || ( targetLayer ==
F_Cu && currentLayer ==
B_Cu ) ) )
1334 if( !
m_router->GetNearestRatnestAnchor( otherEnd, otherEndLayers, otherEndItem ) )
1337 currentLayer = pairTop;
1338 targetLayer = pairBottom;
1345 const std::optional<int> pairedLayerPns =
m_router->Sizes().PairedLayer(
m_router->GetCurrentLayer() );
1353 const bool otherEndIsThrough =
1354 otherEndLayers == allCopperLayers
1355 || ( otherEndItem && otherEndItem->
HasHole()
1356 && otherEndItem->
Hole()->
Layers() == allCopperLayers );
1358 if( otherEndIsThrough )
1362 if( currentLayer == pairBottom )
1363 targetLayer = pairTop;
1364 else if( currentLayer == pairTop )
1365 targetLayer = pairBottom;
1367 targetLayer = pairTop;
1369 else if( currentLayer == otherEndLayerPcbId && pairedLayerPns.has_value() )
1373 targetLayer =
m_iface->GetBoardLayerFromPNSLayer( *pairedLayerPns );
1377 targetLayer =
m_iface->GetBoardLayerFromPNSLayer( otherEndLayers.
Start() );
1383 if( currentLayer == pairTop || currentLayer == pairBottom )
1387 currentLayer = pairTop;
1388 targetLayer = pairBottom;
1394 targetLayer = pairTop;
1398 if( currentLayer == targetLayer )
1403 WX_INFOBAR::MESSAGE_TYPE::DRC_VIOLATION );
1418 if( !
m_router->GetCurrentNets().empty() )
1426 if( !constraint.
IsNull() )
1432 if( !constraint.
IsNull() )
1443 m_iface->GetPNSLayerFromBoardLayer( targetLayer ) );
1450 if(
m_router->RoutingInProgress() )
1468 int pnsLayer =
m_iface->GetPNSLayerFromBoardLayer( pcbLayer );
1479 if( !
getView()->IsLayerVisible( pcbLayer ) )
1487 m_iface->SetStartLayerFromPCBNew( pcbLayer );
1489 frame()->GetBoard()->GetDesignSettings().m_TempOverrideTrackWidth =
false;
1492 m_iface->GetPNSLayerFromBoardLayer(
frame()->GetScreen()->m_Route_Layer_BOTTOM ) );
1522 m_router->ClearViewDecorations();
1533 frame()->UndoRedoBlock(
true );
1551 frame()->UndoRedoBlock(
false );
1571 auto syncRouterAndFrameLayer =
1574 int pnsLayer =
m_router->GetCurrentLayer();
1580 if( !
getView()->IsLayerVisible( pcbLayer ) )
1599 UI_UPDATE_INTERVAL_GUARD uiGuard( 200 );
1606 if( !
m_router->RoutingInProgress() )
1608 if( evt->IsCancelInteractive() )
1616 if( evt->IsMotion() )
1625 if( std::optional<VECTOR2I> last =
m_router->UndoLastSegment() )
1628 evt->SetMousePosition( last.value() );
1639 bool* autoRouted = evt->Parameter<
bool*>();
1646 if( autoRouted !=
nullptr )
1655 if( autoRouted !=
nullptr )
1657 *autoRouted =
false;
1667 bool needsAppend =
m_router->Placer()->HasPlacedAnything();
1671 syncRouterAndFrameLayer();
1683 frame()->ShowInfoBarError(
m_router->FailureReason(),
true );
1691 bool needLayerSwitch =
m_router->IsPlacingVia();
1692 bool forceCommit =
false;
1697 if( needLayerSwitch )
1707 syncRouterAndFrameLayer();
1733 bool forceFinish =
true;
1734 bool forceCommit =
false;
1740 || evt->IsActivate()
1746 if( evt->IsActivate() && !evt->IsMoveTool() )
1751 else if( evt->IsUndoRedo() )
1769 evt->SetPassEvent();
1786 if( settingsDlg.
ShowModal() == wxID_OK )
1818 settings.SetMode( mode );
1846 return m_router->Settings().Mode();
1852 return m_router->RoutingInProgress();
1875 if(
m_router->RoutingInProgress() )
1887 frame->PushTool( aEvent );
1900 controls->ForceCursorPosition(
false );
1905 std::vector<BOARD_CONNECTED_ITEM*> itemList;
1912 itemList.push_back(
pad );
1920 std::shared_ptr<CONNECTIVITY_DATA> connectivity =
frame->GetBoard()->GetConnectivity();
1923 bool groupStart =
true;
1931 RN_NET* net = connectivity->GetRatsnestForNet( item->GetNetCode() );
1936 std::vector<std::shared_ptr<const CN_ANCHOR>> anchors;
1940 std::shared_ptr<const CN_ANCHOR> target = edge.GetTargetNode();
1941 std::shared_ptr<const CN_ANCHOR> source = edge.GetSourceNode();
1943 if( !source || source->Dirty() || !target || target->Dirty() )
1946 if( source->Parent() == item )
1947 anchors.push_back( source );
1948 else if( target->Parent() == item )
1949 anchors.push_back( target );
1953 for( std::shared_ptr<const CN_ANCHOR>
anchor : anchors )
1962 if(
frame->GetActiveLayer() != originalLayer )
1963 frame->SetActiveLayer( originalLayer );
1970 bool autoRouted =
false;
2002 frame->PopTool( pushedEvent );
2019 if(
m_router->RoutingInProgress() )
2031 frame->PushTool( aEvent );
2042 controls->ForceCursorPosition(
false );
2056 if( !evt->IsDrag() )
2059 if( evt->IsCancelInteractive() )
2061 frame->PopTool( pushedEvent );
2064 else if( evt->IsActivate() )
2066 if( evt->IsMoveTool() || evt->IsEditorTool() )
2073 frame->PopTool( pushedEvent );
2085 else if( evt->IsMotion() )
2103 evt->SetPassEvent(
false );
2111 if( evt->HasPosition() )
2125 else if( evt->IsKeyPressed() )
2130 evt->SetPassEvent();
2138 evt->SetPassEvent();
2143 frame->PopTool( pushedEvent );
2167 KIDIALOG dlg(
frame(),
_(
"The selected item is locked." ),
_(
"Confirmation" ),
2168 wxOK | wxCANCEL | wxICON_WARNING );
2169 dlg.SetOKLabel(
_(
"Drag Anyway" ) );
2180 if( !
m_router->FailureReason().IsEmpty() )
2181 frame()->ShowInfoBarError(
m_router->FailureReason(),
true );
2191 frame()->UndoRedoBlock(
true );
2193 UI_UPDATE_INTERVAL_GUARD uiGuard( 200 );
2199 if( evt->IsMotion() )
2208 if( dragger->GetForceMarkObstaclesMode( &dragStatus ) )
2215 hint.Printf(
_(
"(%s to commit anyway.)" ),
2219 statusItem->
SetMessage(
_(
"Track violates DRC." ) );
2227 else if( evt->IsClick(
BUT_LEFT ) )
2229 bool forceFinish =
false;
2230 bool forceCommit = evt->Modifier(
MD_CTRL );
2240 || evt->IsActivate() )
2245 if( evt->IsActivate() && !evt->IsMoveTool() )
2250 else if( evt->IsUndoRedo() )
2278 evt->SetPassEvent();
2283 evt->SetPassEvent();
2292 if(
m_router->RoutingInProgress() )
2298 frame()->UndoRedoBlock(
false );
2325 if( vias + traces == 0 )
2339 for(
int i = 0; !reference && i < aCollector.
GetCount(); i++ )
2340 reference =
dynamic_cast<PCB_TRACK*
>( aCollector[i] );
2354 refPoint = reference->
GetEnd();
2358 for(
int i = 0; i < aCollector.
GetCount(); i++ )
2362 if( neighbor && neighbor != reference )
2367 if( neighbor->
GetStart() != refPoint && neighbor->
GetEnd() != refPoint )
2374 aCollector.
Append( reference );
2404 std::copy( aOriginalSelection.
Items().begin(), aOriginalSelection.
Items().end(), std::back_inserter( selItems ) );
2420 std::deque<EDA_ITEM*> selectedItems =
selection.GetItems();
2432 std::set<FOOTPRINT*> footprints;
2435 footprints.insert(
static_cast<FOOTPRINT*
>( item ) );
2440 for(
int idx = 1; idx <
selection.Size(); ++idx )
2442 if( !
selection.GetItem( idx )->IsBOARD_ITEM() )
2457 bool wasLocked =
false;
2468 frame()->PushTool( aEvent );
2475 bool showCourtyardConflicts =
frame()->GetPcbNewSettings()->m_ShowCourtyardCollisions;
2477 std::shared_ptr<DRC_ENGINE> drcEngine =
m_toolMgr->GetTool<
DRC_TOOL>()->GetDRCEngine();
2481 std::vector<BOARD_ITEM*> dynamicItems;
2482 std::unique_ptr<CONNECTIVITY_DATA> dynamicData =
nullptr;
2484 std::vector<PNS::ITEM*> leaderSegments;
2485 bool singleFootprintDrag =
false;
2491 if( !footprints.empty() )
2493 if( footprints.size() == 1 )
2494 singleFootprintDrag =
true;
2496 if( showCourtyardConflicts )
2506 itemsToDrag.
Add( solid );
2510 if( connectivityData->GetRatsnestForPad(
pad ).size() > 0 )
2511 dynamicItems.push_back(
pad );
2518 itemsToDrag.
Add( solid );
2524 || shape->GetLayer() ==
Margin
2528 itemsToDrag.
Add( solid );
2532 if( showCourtyardConflicts )
2536 dynamicData = std::make_unique<CONNECTIVITY_DATA>(
board()->GetConnectivity(),
2537 dynamicItems,
true );
2538 connectivityData->BlockRatsnestItems( dynamicItems );
2542 for(
const EDA_ITEM* selItem : selectedItems )
2544 if( !selItem->IsBOARD_ITEM() )
2557 itemsToDrag.
Add( pnsItem );
2569 if( itemsToDrag.
Count() >= 1 )
2575 int layer =
m_iface->GetPNSLayerFromBoardLayer( activeLayer );
2577 SEG::ecoord closestDistSq = std::numeric_limits<SEG::ecoord>::max();
2581 const SHAPE* shape = pitem->Shape( layer );
2588 if( distSq < closestDistSq )
2590 closestDistSq = distSq;
2591 closestItem = pitem;
2601 if( closestItem->
Net() )
2606 if( !footprints.empty() && singleFootprintDrag )
2617 tweakedMousePos =
footprint->GetPosition();
2632 int dragMode = aEvent.
Parameter<
int> ();
2634 bool dragStarted =
m_router->StartDragging( p, itemsToDrag, dragMode );
2641 if( !footprints.empty() )
2642 connectivityData->ClearLocalRatsnest();
2649 frame()->PopTool( pushedEvent );
2657 frame()->UndoRedoBlock(
true );
2678 UI_UPDATE_INTERVAL_GUARD uiGuard( 200 );
2680 bool hasMouseMoved =
false;
2681 bool hasMultidragCancelled =
false;
2688 || evt->IsActivate() )
2693 hasMultidragCancelled =
true;
2697 else if( evt->IsMotion() || evt->IsDrag(
BUT_LEFT ) )
2699 hasMouseMoved =
true;
2705 if( !footprints.empty() )
2714 previewItem =
static_cast<BOARD_ITEM*
>( drawing->Clone() );
2715 previewItem->
Move( offset );
2724 &&
pad->GetDrillSize().x == 0 )
2727 previewItem->
Move( offset );
2740 previewItem->
Move( offset );
2745 previewItem->
Move( offset );
2749 if( showCourtyardConflicts )
2753 if( showCourtyardConflicts )
2755 courtyardClearanceDRC.
Run();
2763 dynamicData->Move( offset - lastOffset );
2764 lastOffset = offset;
2765 connectivityData->ComputeLocalRatsnest( dynamicItems, dynamicData.get(), offset );
2772 if( dragger->GetForceMarkObstaclesMode( &dragStatus ) )
2777 hint.Printf(
_(
"(%s to commit anyway.)" ),
2781 statusItem->
SetMessage(
_(
"Track violates DRC." ) );
2789 else if( hasMouseMoved && ( evt->IsMouseUp(
BUT_LEFT ) || evt->IsClick(
BUT_LEFT ) ) )
2791 bool forceFinish =
false;
2792 bool forceCommit = evt->Modifier(
MD_CTRL );
2796 leaderSegments =
m_router->GetLastCommittedLeaderSegments();
2800 else if( evt->IsUndoRedo() )
2828 evt->SetPassEvent();
2833 evt->SetPassEvent();
2839 if( !footprints.empty() )
2856 connectivityData->ClearLocalRatsnest();
2862 if(
m_router->RoutingInProgress() )
2866 if( itemsToDrag.
Size() && hasMultidragCancelled )
2870 else if( leaderSegments.size() )
2872 std::vector<EDA_ITEM*> newItems;
2874 for(
auto lseg : leaderSegments )
2875 newItems.push_back( lseg->Parent() );
2883 frame()->UndoRedoBlock(
false );
2884 frame()->PopTool( pushedEvent );
2936 KIDIALOG dlg(
frame(),
_(
"The selected item is locked." ),
_(
"Confirmation" ),
2937 wxOK | wxCANCEL | wxICON_WARNING );
2938 dlg.SetOKLabel(
_(
"Break Track" ) );
2945 frame()->UndoRedoBlock(
true );
2948 if(
m_router->RoutingInProgress() )
2951 frame()->UndoRedoBlock(
false );
2979 if( !
m_router->GetCurrentNets().empty() )
2998 std::vector<MSG_PANEL_ITEM> items;
3005 std::vector<PNS::NET_HANDLE> nets =
m_router->GetCurrentNets();
3006 wxString description;
3012 wxASSERT( nets.size() >= 2 );
3019 description = wxString::Format(
_(
"Routing Diff Pair: %s" ),
3026 if( *netclassA == *netclassB )
3032 secondary = wxString::Format(
_(
"Resolved Netclass: %s" ),
3035 else if( !nets.empty() && nets[0] )
3039 description = wxString::Format(
_(
"Routing Track: %s" ),
3042 secondary = wxString::Format(
3043 _(
"Resolved Netclass: %s" ),
3048 description =
_(
"Routing Track" );
3049 secondary =
_(
"(no net)" );
3052 items.emplace_back( description, secondary );
3054 wxString cornerMode;
3056 if(
m_router->Settings().GetFreeAngleMode() )
3058 cornerMode =
_(
"Free-angle" );
3062 switch(
m_router->Settings().GetCornerMode() )
3072 items.emplace_back(
_(
"Corner Style" ), cornerMode );
3074 switch(
m_router->Settings().Mode() )
3082 items.emplace_back(
_(
"Mode" ), mode );
3084#define FORMAT_VALUE( x ) frame()->MessageTextFromValue( x )
3088 items.emplace_back( wxString::Format(
_(
"Track Width: %s" ),
3090 wxString::Format(
_(
"(from %s)" ),
3093 items.emplace_back( wxString::Format(
_(
"Min Clearance: %s" ),
3095 wxString::Format(
_(
"(from %s)" ),
3098 items.emplace_back( wxString::Format(
_(
"Diff Pair Gap: %s" ),
3100 wxString::Format(
_(
"(from %s)" ),
3104 wxASSERT( traces.
Count() == 2 );
3107 traces[1],
m_router->GetCurrentLayer(), &constraint ) )
3109 items.emplace_back( wxString::Format(
_(
"DP Max Uncoupled-length: %s" ),
3111 wxString::Format(
_(
"(from %s)" ),
3117 items.emplace_back( wxString::Format(
_(
"Track Width: %s" ),
3119 wxString::Format(
_(
"(from %s)" ),
3122 items.emplace_back( wxString::Format(
_(
"Min Clearance: %s" ),
3124 wxString::Format(
_(
"(from %s)" ),
3130 frame()->SetMsgPanel( items );
std::function< void(const VECTOR2I &, GENERAL_COLLECTOR &, PCB_SELECTION_TOOL *)> CLIENT_SELECTION_FILTER
@ switch_corner_rounding_shape
constexpr BOX2I BOX2ISafe(const BOX2D &aInput)
static TOOL_ACTION cancelInteractive
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
static TOOL_ACTION pasteSpecial
static TOOL_ACTION doDelete
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION finishInteractive
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Manage TOOL_ACTION objects.
void SetConditions(const TOOL_ACTION &aAction, const ACTION_CONDITIONS &aConditions)
Set the conditions the UI elements for activating a specific tool action should use for determining t...
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void SetLayerVisible(int aLayer, bool isVisible)
BASE_SET & set(size_t pos)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Container for design settings for a BOARD object.
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
void SetCustomDiffPairWidth(int aWidth)
Sets custom track width for differential pairs (i.e.
int GetCurrentViaSize() const
void SetViaSizeIndex(int aIndex)
Set the current via size list index to aIndex.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
bool m_UseConnectedTrackWidth
int GetTrackWidthIndex() const
int GetViaSizeIndex() const
int GetDiffPairIndex() const
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
void SetDiffPairIndex(int aIndex)
bool m_TempOverrideTrackWidth
void SetCustomDiffPairGap(int aGap)
Sets custom gap for differential pairs (i.e.
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
bool UseNetClassTrack() const
Return true if netclass values should be used to obtain appropriate track width.
bool UseNetClassDiffPair() const
Return true if netclass values should be used to obtain appropriate diff pair dimensions.
void SetTrackWidthIndex(int aIndex)
Set the current track width list index to aIndex.
int GetCopperLayerCount() const
void UseCustomDiffPairDimensions(bool aEnabled)
Enables/disables custom differential pair dimensions.
std::vector< int > m_TrackWidthList
int GetCurrentViaDrill() const
std::vector< VIA_DIMENSION > m_ViasDimensionsList
void SetCustomDiffPairViaGap(int aGap)
Sets custom via gap for differential pairs (i.e.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void SetLocked(bool aLocked) override
bool IsLocked() const override
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Information pertinent to a Pcbnew printed circuit board.
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
void Empty()
Clear the list.
int GetCount() const
Return the number of objects in the list.
int CountType(KICAD_T aType)
Count the number of items matching aType.
void Append(EDA_ITEM *item)
Add an item to the end of the list.
PNS::LOGGER::TEST_CASE_TYPE getTestCaseType() const
const wxString & getTestCaseName() const
Implementing DIALOG_TRACK_VIA_SIZE_BASE.
@ ROUNDED_90
H/V with filleted corners.
@ MITERED_90
H/V only (90-degree corners)
@ ROUNDED_45
H/V/45 with filleted corners.
@ MITERED_45
H/V/45 with mitered corners (default)
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
std::vector< FOOTPRINT * > m_FpInMove
void ClearConflicts(KIGFX::VIEW *aView)
void UpdateConflicts(KIGFX::VIEW *aView, bool aHighlightMoved)
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, INFOBAR_MESSAGE_TYPE aType=INFOBAR_MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
void SetFlags(EDA_ITEM_FLAGS aMask)
KICAD_T Type() const
Returns the type of object.
Used when the right click button is pressed, or when the select tool is in effect.
static const std::vector< KICAD_T > DraggableItems
A scan list for items that can be dragged.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Abstract interface for drawing on a 2D-surface.
BOX2D GetVisibleWorldExtents() const
bool GetGridSnapping() const
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Move cursor to the requested position expressed in world coordinates.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
void ShowPreview(bool aShow=true)
virtual int GetTopLayer() const
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
A collection of nets and the parameters used to route or test these nets.
const wxString GetHumanReadableName() const
Gets the consolidated name of this netclass (which may be an aggregate).
Handle the data for a net.
const wxString & GetNetname() const
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
static TOOL_ACTION_GROUP layerDirectSwitchActions()
static TOOL_ACTION layerToggle
static TOOL_ACTION drag45Degree
static TOOL_ACTION layerInner12
static TOOL_ACTION routerUndoLastSegment
static TOOL_ACTION layerInner8
static TOOL_ACTION layerInner3
static TOOL_ACTION layerPrev
static TOOL_ACTION routerSettingsDialog
Activation of the Push and Shove settings dialogs.
static TOOL_ACTION layerInner2
static TOOL_ACTION routerAttemptFinish
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
static TOOL_ACTION trackViaSizeChanged
static TOOL_ACTION layerChanged
static TOOL_ACTION layerInner25
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
static TOOL_ACTION routerRouteSelectedFromEnd
static TOOL_ACTION routerHighlightMode
Actions to enable switching modes via hotkey assignments.
static TOOL_ACTION routerWalkaroundMode
static TOOL_ACTION routerShoveMode
static TOOL_ACTION layerInner24
static TOOL_ACTION properties
Activation of the edit tool.
static TOOL_ACTION layerInner29
static TOOL_ACTION routerAutorouteSelected
static TOOL_ACTION layerInner11
static TOOL_ACTION routerDiffPairDialog
static TOOL_ACTION routerContinueFromEnd
static TOOL_ACTION layerInner16
static TOOL_ACTION layerInner26
static TOOL_ACTION layerInner18
static TOOL_ACTION layerInner14
static TOOL_ACTION selectLayerPair
static TOOL_ACTION layerInner6
static TOOL_ACTION dragFreeAngle
static TOOL_ACTION clearHighlight
static TOOL_ACTION layerInner22
static TOOL_ACTION layerInner5
static TOOL_ACTION layerInner20
static TOOL_ACTION layerInner7
static TOOL_ACTION layerInner27
static TOOL_ACTION cancelCurrentItem
static TOOL_ACTION layerInner1
static TOOL_ACTION layerInner10
static TOOL_ACTION layerInner15
static TOOL_ACTION layerInner17
static TOOL_ACTION layerBottom
static TOOL_ACTION layerInner19
static TOOL_ACTION layerInner9
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
static TOOL_ACTION layerInner30
static TOOL_ACTION layerTop
static TOOL_ACTION cycleRouterMode
static TOOL_ACTION layerInner4
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
static TOOL_ACTION layerInner13
static TOOL_ACTION layerInner21
static TOOL_ACTION layerNext
static TOOL_ACTION routerRouteSelected
static TOOL_ACTION layerInner23
static TOOL_ACTION layerInner28
Common, abstract interface for edit frames.
APPEARANCE_CONTROLS * GetAppearancePanel()
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual PCB_LAYER_ID GetActiveLayer() const
The main frame for Pcbnew.
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
PCB_LAYER_ID m_Route_Layer_TOP
PCB_LAYER_ID m_Route_Layer_BOTTOM
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
EDA_ITEM_FLAGS IsPointOnEnds(const VECTOR2I &point, int min_dist=0) const
Return STARTPOINT if point if near (dist = min_dist) start point, ENDPOINT if point if near (dist = m...
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
void SetViaType(VIATYPE aViaType)
int Count(int aKindMask=-1) const
void Add(const LINE &aLine)
std::vector< ITEM * > & Items()
Base class for PNS router board items.
const PNS_LAYER_RANGE & Layers() const
virtual NET_HANDLE Net() const
bool OfKind(int aKindMask) const
virtual HOLE * Hole() const
virtual bool HasHole() const
static wxString FormatLogFileAsJSON(const LOG_DATA &aLogData)
Contain all persistent settings of the router, such as the mode, optimization effort,...
void SetMode(PNS_MODE aMode)
Return the optimizer effort. Bigger means cleaner traces, but slower routing.
PNS_MODE Mode() const
Set the routing mode.
void SetViaType(VIATYPE aViaType)
void SetTrackWidth(int aWidth)
int DiffPairWidth() const
void SetDiffPairWidth(int aWidth)
void SetDiffPairWidthSource(const wxString &aSource)
void SetDiffPairGapSource(const wxString &aSource)
void SetDiffPairGap(int aGap)
void SetViaDrill(int aDrill)
wxString GetClearanceSource() const
wxString GetDiffPairGapSource() const
wxString GetDiffPairWidthSource() const
void AddLayerPair(int aL1, int aL2)
void SetClearance(int aClearance)
bool TrackWidthIsExplicit() const
void SetViaDiameter(int aDiameter)
void SetClearanceSource(const wxString &aSource)
wxString GetWidthSource() const
void SetWidthSource(const wxString &aSource)
int DiffPairViaGap() const
Represent a contiguous set of PCB layers.
bool Overlaps(const PNS_LAYER_RANGE &aOther) const
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
Container for project specific data.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
virtual PROJECT_FILE & GetProjectFile() const
Describe ratsnest for a single net.
const std::vector< CN_EDGE > & GetEdges() const
void SetMessage(const wxString &aStatus)
void SetHint(const wxString &aHint)
void SetPosition(const VECTOR2I &aPos) override
VECTOR2I::extended_type ecoord
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
std::deque< EDA_ITEM * > & Items()
An abstract shape on 2D plane.
virtual SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) const
A modified version of the wxInfoBar class that allows us to:
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
Handle a list of polygons defining a copper zone.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
This file is part of the common library.
@ VIA_DIAMETER_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
#define ROUTER_TRANSIENT
transient items that should NOT be cached
#define ENDPOINT
ends. (Used to support dragging.)
std::uint32_t EDA_ITEM_FLAGS
#define STARTPOINT
When a line is selected, these flags indicate which.
static FILENAME_RESOLVER * resolver
a few functions useful in geometry calculations.
VECTOR2< ret_type > GetClampedCoords(const VECTOR2< in_type > &aCoords, pad_type aPadding=1u)
Clamps a vector to values that can be negated, respecting numeric limits of coordinates data type wit...
wxString m_RouterTestCaseDirectory
Router test case directory.
static const std::string DesignRulesFileExtension
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
std::optional< wxString > fileHashMMH3(const wxString &aFilePath)
Calculates an MMH3 hash of a given file.
The Cairo implementation of the graphics abstraction layer.
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
@ PNS_MODE_ROUTE_DIFF_PAIR
@ ID_POPUP_PCB_SELECT_WIDTH1
@ ID_POPUP_PCB_SELECT_DIFFPAIR16
@ ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES
@ ID_POPUP_PCB_SELECT_WIDTH16
@ ID_POPUP_PCB_SELECT_AUTO_WIDTH
@ ID_POPUP_PCB_SELECT_CUSTOM_WIDTH
@ ID_POPUP_PCB_SELECT_DIFFPAIR1
@ ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR
@ ID_POPUP_PCB_SELECT_VIASIZE1
@ ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR
@ ID_POPUP_PCB_SELECT_VIASIZE16
Class that computes missing connections on a PCB.
std::vector< EDA_ITEM * > EDA_ITEMS
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
Container to handle a stock of specific differential pairs each with unique track width,...
An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between...
std::optional< wxString > m_BoardHash
std::optional< TEST_CASE_TYPE > m_TestCaseType
std::vector< ITEM * > m_AddedItems
std::vector< EVENT_ENTRY > m_Events
std::set< KIID > m_RemovedItems
std::vector< ITEM * > m_Heads
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
HYPERLINK_DV_RENDERER::RUN RUN
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
wxPoint ToWxPoint(const VECTOR2I &aSize)
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.