KiCad PCB EDA Suite
Loading...
Searching...
No Matches
router_tool.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2017 CERN
5 * Copyright (C) 2017-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Tomasz Wlostowski <[email protected]>
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include "tool/tool_action.h"
24#include <wx/filedlg.h>
25#include <wx/hyperlink.h>
26#include <advanced_config.h>
27
28#include <functional>
29#include <iomanip>
30#include <utility>
31#include <sstream>
32
33using namespace std::placeholders;
34#include <board.h>
36#include <board_item.h>
37#include <footprint.h>
38#include <pad.h>
39#include <zone.h>
40#include <pcb_edit_frame.h>
41#include <pcbnew_id.h>
45#include <math/vector2wx.h>
46#include <paths.h>
47#include <widgets/wx_infobar.h>
51#include <confirm.h>
53#include <bitmaps.h>
54#include <string_utils.h>
55#include <gal/painter.h>
56#include <tool/action_menu.h>
57#include <tool/tool_manager.h>
58#include <tool/tool_menu.h>
59#include <tools/pcb_actions.h>
62#include <tools/drc_tool.h>
65
66#include <project.h>
69
70#include "router_tool.h"
72#include "pns_router.h"
73#include "pns_itemset.h"
74#include "pns_logger.h"
75#include "pns_placement_algo.h"
76#include "pns_drag_algo.h"
77
78#include "pns_kicad_iface.h"
79
81
83
84using namespace KIGFX;
85
90{
91 // Via type
92 VIA_MASK = 0x03,
93 VIA = 0x00,
94 BLIND_VIA = 0x01,
95 MICROVIA = 0x02,
96
97 // Select layer
99};
100
101
102// Actions, being statically-defined, require specialized I18N handling. We continue to
103// use the _() macro so that string harvesting by the I18N framework doesn't have to be
104// specialized, but we don't translate on initialization and instead do it in the getters.
105
106#undef _
107#define _(s) s
108
109// Pass all the parameters as int to allow combining flags
111 .Name( "pcbnew.InteractiveRouter.PlaceVia" )
112 .Scope( AS_CONTEXT )
113 .DefaultHotkey( 'V' )
114 .LegacyHotkeyName( "Add Through Via" )
115 .FriendlyName( _( "Place Through Via" ) )
116 .Tooltip( _( "Adds a through-hole via at the end of currently routed track." ) )
117 .Icon( BITMAPS::via )
118 .Flags( AF_NONE )
119 .Parameter<int>( VIA_ACTION_FLAGS::VIA ) );
120
122 .Name( "pcbnew.InteractiveRouter.PlaceBlindVia" )
123 .Scope( AS_CONTEXT )
124 .DefaultHotkey( MD_ALT + MD_SHIFT + 'V' )
125 .LegacyHotkeyName( "Add Blind/Buried Via" )
126 .FriendlyName( _( "Place Blind/Buried Via" ) )
127 .Tooltip( _( "Adds a blind or buried via at the end of currently routed track.") )
128 .Icon( BITMAPS::via_buried )
129 .Flags( AF_NONE )
130 .Parameter<int>( VIA_ACTION_FLAGS::BLIND_VIA ) );
131
133 .Name( "pcbnew.InteractiveRouter.PlaceMicroVia" )
134 .Scope( AS_CONTEXT )
135 .DefaultHotkey( MD_CTRL + 'V' )
136 .LegacyHotkeyName( "Add MicroVia" )
137 .FriendlyName( _( "Place Microvia" ) )
138 .Tooltip( _( "Adds a microvia at the end of currently routed track." ) )
139 .Icon( BITMAPS::via_microvia )
140 .Flags( AF_NONE )
141 .Parameter<int>( VIA_ACTION_FLAGS::MICROVIA ) );
142
144 .Name( "pcbnew.InteractiveRouter.SelLayerAndPlaceVia" )
145 .Scope( AS_CONTEXT )
146 .DefaultHotkey( '<' )
147 .LegacyHotkeyName( "Select Layer and Add Through Via" )
148 .FriendlyName( _( "Select Layer and Place Through Via..." ) )
149 .Tooltip( _( "Select a layer, then add a through-hole via at the end of currently routed track." ) )
151 .Flags( AF_NONE )
153
155 .Name( "pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia" )
156 .Scope( AS_CONTEXT )
157 .DefaultHotkey( MD_ALT + '<' )
158 .LegacyHotkeyName( "Select Layer and Add Blind/Buried Via" )
159 .FriendlyName( _( "Select Layer and Place Blind/Buried Via..." ) )
160 .Tooltip( _( "Select a layer, then add a blind or buried via at the end of currently routed track." ) )
162 .Flags( AF_NONE )
164
166 .Name( "pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia" )
167 .Scope( AS_CONTEXT )
168 .FriendlyName( _( "Select Layer and Place Micro Via..." ) )
169 .Tooltip( _( "Select a layer, then add a micro via at the end of currently routed track." ) )
171 .Flags( AF_NONE )
173
175 .Name( "pcbnew.InteractiveRouter.CustomTrackViaSize" )
176 .Scope( AS_CONTEXT )
177 .DefaultHotkey( 'Q' )
178 .LegacyHotkeyName( "Custom Track/Via Size" )
179 .FriendlyName( _( "Custom Track/Via Size..." ) )
180 .Tooltip( _( "Shows a dialog for changing the track width and via size." ) )
181 .Icon( BITMAPS::width_track ) );
182
184 .Name( "pcbnew.InteractiveRouter.SwitchPosture" )
185 .Scope( AS_CONTEXT )
186 .DefaultHotkey( '/' )
187 .LegacyHotkeyName( "Switch Track Posture" )
188 .FriendlyName( _( "Switch Track Posture" ) )
189 .Tooltip( _( "Switches posture of the currently routed track." ) )
191
193 .Name( "pcbnew.InteractiveRouter.SwitchRounding" )
194 .Scope( AS_CONTEXT )
195 .DefaultHotkey( MD_CTRL + '/' )
196 .FriendlyName( _( "Track Corner Mode" ) )
197 .Tooltip( _( "Switches between sharp/rounded and 45°/90° corners when routing tracks." ) )
199
200#undef _
201#define _(s) wxGetTranslation((s))
202
203
205 TOOL_BASE( "pcbnew.InteractiveRouter" ),
206 m_lastTargetLayer( UNDEFINED_LAYER ),
207 m_originalActiveLayer( UNDEFINED_LAYER ),
208 m_inRouterTool( false )
209{
210}
211
212
214{
215public:
217 ACTION_MENU( true ),
218 m_frame( aFrame )
219 {
220 SetIcon( BITMAPS::width_track_via );
221 SetTitle( _( "Select Track/Via Width" ) );
222 }
223
224protected:
225 ACTION_MENU* create() const override
226 {
227 return new TRACK_WIDTH_MENU( m_frame );
228 }
229
230 void update() override
231 {
233 bool useIndex = !bds.m_UseConnectedTrackWidth &&
235 wxString msg;
236
237 Clear();
238
239 Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
240 _( "Route using the width of the starting track." ), wxITEM_CHECK );
243
244 Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
245 _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
247 useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
248
249 Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
250 _( "Specify custom track and via sizes" ), wxITEM_CHECK );
252
253 AppendSeparator();
254
255 // Append the list of tracks & via sizes
256 for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
257 {
258 int width = bds.m_TrackWidthList[i];
259
260 if( i == 0 )
261 msg = _( "Track netclass width" );
262 else
263 msg.Printf( _( "Track %s" ), m_frame.MessageTextFromValue( width ) );
264
265 int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
266 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
267 Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
268 }
269
270 AppendSeparator();
271
272 for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
273 {
275
276 if( i == 0 )
277 msg = _( "Via netclass values" );
278 else
279 {
280 if( via.m_Drill > 0 )
281 {
282 msg.Printf( _("Via %s, hole %s" ),
283 m_frame.MessageTextFromValue( via.m_Diameter ),
284 m_frame.MessageTextFromValue( via.m_Drill ) );
285 }
286 else
287 {
288 msg.Printf( _( "Via %s" ),
289 m_frame.MessageTextFromValue( via.m_Diameter ) );
290 }
291 }
292
293 int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
294 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
295 Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
296 }
297 }
298
299 OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
300 {
302 int id = aEvent.GetId();
303
304 // On Windows, this handler can be called with an event ID not existing in any
305 // menuitem, so only set flags when we have an ID match.
306
308 {
309 bds.UseCustomTrackViaSize( true );
310 bds.m_TempOverrideTrackWidth = true;
312 }
313 else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
314 {
315 bds.UseCustomTrackViaSize( false );
316 bds.m_UseConnectedTrackWidth = true;
317 bds.m_TempOverrideTrackWidth = false;
318 }
320 {
321 bds.UseCustomTrackViaSize( false );
322 bds.m_UseConnectedTrackWidth = false;
323 bds.SetViaSizeIndex( 0 );
324 bds.SetTrackWidthIndex( 0 );
325 }
327 {
328 bds.UseCustomTrackViaSize( false );
330 }
332 {
333 bds.UseCustomTrackViaSize( false );
334 bds.m_TempOverrideTrackWidth = true;
336 }
337
339 }
340
341private:
343};
344
345
347{
348public:
350 ACTION_MENU( true ),
351 m_frame( aFrame )
352 {
353 SetIcon( BITMAPS::width_track_via );
354 SetTitle( _( "Select Differential Pair Dimensions" ) );
355 }
356
357protected:
358 ACTION_MENU* create() const override
359 {
360 return new DIFF_PAIR_MENU( m_frame );
361 }
362
363 void update() override
364 {
366
367 Clear();
368
369 Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
370 _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
372 !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
373
374 Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
375 _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
377
378 AppendSeparator();
379
380 // Append the list of differential pair dimensions
381
382 // Drop index 0 which is the current netclass dimensions (which are handled above)
383 for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
384 {
386 wxString msg;
387
388 if( diffPair.m_Gap <= 0 )
389 {
390 if( diffPair.m_ViaGap <= 0 )
391 {
392 msg.Printf( _( "Width %s" ),
394 }
395 else
396 {
397 msg.Printf( _( "Width %s, via gap %s" ),
400 }
401 }
402 else
403 {
404 if( diffPair.m_ViaGap <= 0 )
405 {
406 msg.Printf( _( "Width %s, gap %s" ),
408 m_frame.MessageTextFromValue( diffPair.m_Gap ) );
409 }
410 else
411 {
412 msg.Printf( _( "Width %s, gap %s, via gap %s" ),
416 }
417 }
418
419 int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
420 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
421 Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
422 }
423 }
424
425 OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
426 {
428 int id = aEvent.GetId();
429
430 // On Windows, this handler can be called with an event ID not existing in any
431 // menuitem, so only set flags when we have an ID match.
432
434 {
435 bds.UseCustomDiffPairDimensions( true );
436 TOOL_MANAGER* toolManager = m_frame.GetToolManager();
438 }
440 {
441 bds.UseCustomDiffPairDimensions( false );
442 bds.SetDiffPairIndex( 0 );
443 }
445 {
446 bds.UseCustomDiffPairDimensions( false );
447 // remember that the menu doesn't contain index 0 (which is the netclass values)
449 }
450
452 }
453
454private:
456};
457
458
460{
461}
462
463
465{
468
469 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
470
471 wxASSERT( frame );
472
473 auto& menu = m_menu.GetMenu();
474 menu.SetTitle( _( "Interactive Router" ) );
475
476 m_trackViaMenu = std::make_shared<TRACK_WIDTH_MENU>( *frame );
477 m_trackViaMenu->SetTool( this );
479
480 m_diffPairMenu = std::make_shared<DIFF_PAIR_MENU>( *frame );
481 m_diffPairMenu->SetTool( this );
483
484 auto haveHighlight =
485 [&]( const SELECTION& sel )
486 {
488
489 return !cfg->GetHighlightNetCodes().empty();
490 };
491
492 auto notRoutingCond =
493 [this]( const SELECTION& )
494 {
495 return !m_router->RoutingInProgress();
496 };
497
498 auto hasOtherEnd =
499 [&]( const SELECTION& )
500 {
501 std::vector<PNS::NET_HANDLE> currentNets = m_router->GetCurrentNets();
502
503 if( currentNets.empty() || currentNets[0] == nullptr )
504 return false;
505
506 // Need to have something unconnected to finish to
507 NETINFO_ITEM* netInfo = static_cast<NETINFO_ITEM*>( currentNets[0] );
508 int currentNet = netInfo->GetNetCode();
509 BOARD* board = getEditFrame<PCB_EDIT_FRAME>()->GetBoard();
510 RN_NET* ratsnest = board->GetConnectivity()->GetRatsnestForNet( currentNet );
511
512 return ratsnest && !ratsnest->GetEdges().empty();
513 };
514
516 menu.AddSeparator( 1 );
517
518 menu.AddItem( PCB_ACTIONS::clearHighlight, haveHighlight, 2 );
519 menu.AddSeparator( haveHighlight, 2 );
520
521 menu.AddItem( PCB_ACTIONS::routeSingleTrack, notRoutingCond );
522 menu.AddItem( PCB_ACTIONS::routeDiffPair, notRoutingCond );
525 menu.AddItem( PCB_ACTIONS::routerContinueFromEnd, hasOtherEnd );
526 menu.AddItem( PCB_ACTIONS::routerAttemptFinish, hasOtherEnd );
527 menu.AddItem( PCB_ACTIONS::breakTrack, notRoutingCond );
528
529 menu.AddItem( PCB_ACTIONS::drag45Degree, notRoutingCond );
530 menu.AddItem( PCB_ACTIONS::dragFreeAngle, notRoutingCond );
531
540
541 menu.AddSeparator();
542
543 auto diffPairCond =
544 [this]( const SELECTION& )
545 {
547 };
548
550 menu.AddMenu( m_diffPairMenu.get(), diffPairCond );
551
553
554 menu.AddSeparator();
555
557
558 return true;
559}
560
561
563{
565
566 if( aReason == RUN )
567 TOOL_BASE::Reset( aReason );
568}
569
570// Saves the complete event log and the dump of the PCB, allowing us to
571// recreate hard-to-find P&S quirks and bugs.
572
574{
575 static wxString mruPath = PATHS::GetDefaultUserProjectsPath();
576 static size_t lastLoggerSize = 0;
577
578 auto logger = m_router->Logger();
579
580 if( !logger || logger->GetEvents().size() == 0
581 || logger->GetEvents().size() == lastLoggerSize )
582 {
583 return;
584 }
585
586 wxFileDialog dlg( frame(), _( "Save router log" ), mruPath, "pns.log",
587 "PNS log files" + AddFileExtListToFilter( { "log" } ),
588 wxFD_OVERWRITE_PROMPT | wxFD_SAVE );
589
590 if( dlg.ShowModal() != wxID_OK )
591 {
592 lastLoggerSize = logger->GetEvents().size(); // prevent re-entry
593 return;
594 }
595
596 wxFileName fname_log( dlg.GetPath() );
597 mruPath = fname_log.GetPath();
598
599 wxFileName fname_dump( fname_log );
600 fname_dump.SetExt( "dump" );
601
602 wxFileName fname_settings( fname_log );
603 fname_settings.SetExt( "settings" );
604
605
606 FILE* settings_f = wxFopen( fname_settings.GetAbsolutePath(), "wb" );
607 std::string settingsStr = m_router->Settings().FormatAsString();
608 fprintf( settings_f, "%s\n", settingsStr.c_str() );
609 fclose( settings_f );
610
611 // Export as *.kicad_pcb format, using a strategy which is specifically chosen
612 // as an example on how it could also be used to send it to the system clipboard.
613
614 PCB_IO_KICAD_SEXPR pcb_io;
615
616 pcb_io.SaveBoard( fname_dump.GetAbsolutePath(), m_iface->GetBoard(), nullptr );
617
618 PROJECT* prj = m_iface->GetBoard()->GetProject();
619 prj->GetProjectFile().SaveAs( fname_dump.GetPath(), fname_dump.GetName() );
620 prj->GetLocalSettings().SaveAs( fname_dump.GetPath(), fname_dump.GetName() );
621
622 // Build log file:
623 std::vector<PNS::ITEM*> added, removed, heads;
624 m_router->GetUpdatedItems( removed, added, heads );
625
626 std::set<KIID> removedKIIDs;
627
628 for( auto item : removed )
629 {
630 wxASSERT_MSG( item->Parent() != nullptr, "removed an item with no parent uuid?" );
631
632 if( item->Parent() )
633 removedKIIDs.insert( item->Parent()->m_Uuid );
634 }
635
636 FILE* log_f = wxFopen( fname_log.GetAbsolutePath(), "wb" );
637 wxString logString = PNS::LOGGER::FormatLogFileAsString( m_router->Mode(),
638 added, removedKIIDs, heads,
639 logger->GetEvents() );
640
641 if( !log_f )
642 {
643 DisplayError( frame(), wxString::Format( _( "Unable to write '%s'." ),
644 fname_log.GetAbsolutePath() ) );
645 return;
646 }
647
648 fprintf( log_f, "%s\n", logString.c_str().AsChar() );
649 fclose( log_f );
650
651 logger->Clear(); // prevent re-entry
652 lastLoggerSize = 0;
653}
654
655
657{
658 if( aEvent.Category() == TC_VIEW || aEvent.Category() == TC_MOUSE )
659 {
660 BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
661 m_router->SetVisibleViewArea( BOX2I( viewAreaD.GetOrigin(), viewAreaD.GetSize() ) );
662 }
663
664 if( !ADVANCED_CFG::GetCfg().m_EnableRouterDump )
665 return;
666
667 if( !aEvent.IsKeyPressed() )
668 return;
669
670 switch( aEvent.KeyCode() )
671 {
672 case '0':
674 aEvent.SetPassEvent( false );
675 break;
676
677 default:
678 break;
679 }
680}
681
682
684{
685 int tl = getView()->GetTopLayer();
686
687 if( m_startItem )
688 {
689 const LAYER_RANGE& ls = m_startItem->Layers();
690
691 if( ls.Overlaps( tl ) )
692 return tl;
693 else
694 return ls.Start();
695 }
696
697 return tl;
698}
699
700
702{
703 int activeLayer = frame()->GetActiveLayer();
704 int currentLayer = m_router->GetCurrentLayer();
705
706 if( currentLayer != activeLayer )
707 m_router->SwitchLayer( activeLayer );
708
709 std::optional<int> newLayer = m_router->Sizes().PairedLayer( currentLayer );
710
711 if( !newLayer )
712 newLayer = m_router->Sizes().GetLayerTop();
713
714 m_router->SwitchLayer( *newLayer );
715 m_lastTargetLayer = *newLayer;
716
718}
719
720
722{
723 std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
724
727 std::shared_ptr<DRC_ENGINE>& drcEngine = bds.m_DRCEngine;
728 DRC_CONSTRAINT constraint;
729
730 PCB_TRACK dummyTrack( board() );
731 dummyTrack.SetFlags( ROUTER_TRANSIENT );
732 dummyTrack.SetLayer( targetLayer );
733 dummyTrack.SetNet( nets.empty() ? nullptr: static_cast<NETINFO_ITEM*>( nets[0] ) );
734 dummyTrack.SetStart( aPos );
735 dummyTrack.SetEnd( dummyTrack.GetStart() );
736
737 if( bds.UseNetClassTrack() || !sizes.TrackWidthIsExplicit() )
738 {
739 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, &dummyTrack, nullptr,
740 targetLayer );
741
742 if( !constraint.IsNull() )
743 {
744 int width = sizes.TrackWidth();
745
746 // Only change the size if we're explicitly using the net class, or we're out of range
747 // for our new constraints. Otherwise, just leave the track width alone so we don't
748 // change for no reason.
749 if( bds.UseNetClassTrack()
750 || ( width < bds.m_TrackMinWidth )
751 || ( width < constraint.m_Value.Min() )
752 || ( width > constraint.m_Value.Max() ) )
753 {
754 sizes.SetTrackWidth( std::max( bds.m_TrackMinWidth, constraint.m_Value.Opt() ) );
755 }
756
757 if( sizes.TrackWidth() == constraint.m_Value.Opt() )
758 sizes.SetWidthSource( constraint.GetName() );
759 else if( sizes.TrackWidth() == bds.m_TrackMinWidth )
760 sizes.SetWidthSource( _( "board minimum track width" ) );
761 else
762 sizes.SetWidthSource( _( "existing track" ) );
763 }
764 }
765
766 if( nets.size() >= 2 && ( bds.UseNetClassDiffPair() || !sizes.TrackWidthIsExplicit() ) )
767 {
768 PCB_TRACK dummyTrackB( board() );
769 dummyTrackB.SetFlags( ROUTER_TRANSIENT );
770 dummyTrackB.SetLayer( targetLayer );
771 dummyTrackB.SetNet( static_cast<NETINFO_ITEM*>( nets[1] ) );
772 dummyTrackB.SetStart( aPos );
773 dummyTrackB.SetEnd( dummyTrackB.GetStart() );
774
775 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, &dummyTrack, &dummyTrackB,
776 targetLayer );
777
778 if( !constraint.IsNull() )
779 {
780 sizes.SetDiffPairWidth( std::max( bds.m_TrackMinWidth, constraint.m_Value.Opt() ) );
781
782 if( sizes.DiffPairWidth() == constraint.m_Value.Opt() )
783 sizes.SetDiffPairWidthSource( constraint.GetName() );
784 else
785 sizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
786 }
787
788 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, &dummyTrack, &dummyTrackB,
789 targetLayer );
790
791 if( !constraint.IsNull() )
792 {
793 sizes.SetDiffPairGap( std::max( bds.m_MinClearance, constraint.m_Value.Opt() ) );
794
795 if( sizes.DiffPairGap() == constraint.m_Value.Opt() )
796 sizes.SetDiffPairGapSource( constraint.GetName() );
797 else
798 sizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
799 }
800 }
801
802 m_router->UpdateSizes( sizes );
803}
804
805
806static VIATYPE getViaTypeFromFlags( int aFlags )
807{
808 switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
809 {
811 return VIATYPE::THROUGH;
815 return VIATYPE::MICROVIA;
816 default:
817 wxASSERT_MSG( false, wxT( "Unhandled via type" ) );
818 return VIATYPE::THROUGH;
819 }
820}
821
822
824{
825 handleLayerSwitch( aEvent, false );
827
828 return 0;
829}
830
831
833{
834 if( !m_router->IsPlacingVia() )
835 {
836 return handleLayerSwitch( aEvent, true );
837 }
838 else
839 {
842 updateEndItem( aEvent );
844 }
845
847 return 0;
848}
849
850
851int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
852{
853 wxCHECK( m_router, 0 );
854
855 if( !IsToolActive() )
856 return 0;
857
858 // First see if this is one of the switch layer commands
859 BOARD* brd = board();
860 LSET enabledLayers = LSET::AllCuMask( brd->GetDesignSettings().GetCopperLayerCount() );
861 LSEQ layers = enabledLayers.Seq();
863 PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
864
865 if( aEvent.IsAction( &PCB_ACTIONS::layerNext ) )
866 {
868 m_lastTargetLayer = currentLayer;
869
870 size_t idx = 0;
871 size_t target_idx = 0;
872
873 for( size_t i = 0; i < layers.size(); i++ )
874 {
875 if( layers[i] == m_lastTargetLayer )
876 {
877 idx = i;
878 break;
879 }
880 }
881
882 target_idx = ( idx + 1 ) % layers.size();
883 // issue: #14480
884 // idx + 1 layer may be invisible, switches to next visible layer
885 for( size_t i = 0; i < layers.size() - 1; i++ )
886 {
887 if( brd->IsLayerVisible( static_cast<PCB_LAYER_ID>( layers[target_idx] ) ) )
888 {
889 targetLayer = layers[target_idx];
890 break;
891 }
892 target_idx += 1;
893
894 if( target_idx >= layers.size() )
895 {
896 target_idx = 0;
897 }
898 }
899
900 if( targetLayer == UNDEFINED_LAYER )
901 {
902 // if there is no visible layers
903 return 0;
904 }
905 }
906 else if( aEvent.IsAction( &PCB_ACTIONS::layerPrev ) )
907 {
909 m_lastTargetLayer = currentLayer;
910
911 size_t idx = 0;
912 size_t target_idx = 0;
913
914 for( size_t i = 0; i < layers.size(); i++ )
915 {
916 if( layers[i] == m_lastTargetLayer )
917 {
918 idx = i;
919 break;
920 }
921 }
922
923 target_idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers.size() - 1 );
924
925 for( size_t i = 0; i < layers.size() - 1; i++ )
926 {
927 if( brd->IsLayerVisible( static_cast<PCB_LAYER_ID>( layers[target_idx] ) ) )
928 {
929 targetLayer = layers[target_idx];
930 break;
931 }
932
933 if( target_idx > 0 )
934 target_idx -= 1;
935 else
936 target_idx = layers.size() - 1;
937 }
938
939 if( targetLayer == UNDEFINED_LAYER )
940 {
941 // if there is no visible layers
942 return 0;
943 }
944 }
945 else if( aEvent.IsAction( &PCB_ACTIONS::layerToggle ) )
946 {
947 PCB_SCREEN* screen = frame()->GetScreen();
948
949 if( currentLayer == screen->m_Route_Layer_TOP )
950 targetLayer = screen->m_Route_Layer_BOTTOM;
951 else
952 targetLayer = screen->m_Route_Layer_TOP;
953 }
955 {
956 targetLayer = aEvent.Parameter<PCB_LAYER_ID>();
957
958 if( !enabledLayers.test( targetLayer ) )
959 return 0;
960 }
961
962 if( targetLayer != UNDEFINED_LAYER )
963 {
964 m_lastTargetLayer = targetLayer;
965
966 if( targetLayer == currentLayer )
967 return 0;
968
969 if( !aForceVia && m_router && m_router->SwitchLayer( targetLayer ) )
970 {
971 updateEndItem( aEvent );
973 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
974 return 0;
975 }
976 }
977
979 const int layerCount = bds.GetCopperLayerCount();
980
983
985
986 VIATYPE viaType = VIATYPE::THROUGH;
987 bool selectLayer = false;
988
989 // Otherwise it is one of the router-specific via commands
990 if( targetLayer == UNDEFINED_LAYER )
991 {
992 const int actViaFlags = aEvent.Parameter<int>();
993 selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
994
995 viaType = getViaTypeFromFlags( actViaFlags );
996
997 // ask the user for a target layer
998 if( selectLayer )
999 {
1000 wxPoint endPoint = ToWxPoint( view()->ToScreen( m_endSnapPoint ) );
1001 endPoint = frame()->GetCanvas()->ClientToScreen( endPoint );
1002
1003 // Build the list of not allowed layer for the target layer
1004 LSET not_allowed_ly = LSET::AllNonCuMask();
1005
1006 if( viaType != VIATYPE::THROUGH )
1007 not_allowed_ly.set( currentLayer );
1008
1009 if( viaType == VIATYPE::MICROVIA )
1010 {
1011 // Allows only the previous or the next layer from the current layer
1012 int previous_layer = currentLayer == B_Cu ? layerCount - 2
1013 : currentLayer - 1;
1014
1015 int next_layer = currentLayer >= layerCount-2 ? B_Cu
1016 : currentLayer + 1;
1017
1018 not_allowed_ly = LSET::AllLayersMask();
1019
1020 if( previous_layer >= F_Cu && previous_layer != currentLayer )
1021 not_allowed_ly.reset( previous_layer );
1022
1023 if( next_layer != currentLayer )
1024 not_allowed_ly.reset( next_layer );
1025 }
1026
1027 targetLayer = frame()->SelectOneLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
1028 not_allowed_ly, endPoint );
1029
1030 // Reset the cursor to the end of the track
1032
1033 if( targetLayer == UNDEFINED_LAYER ) // cancelled by user
1034 return 0;
1035
1036 // One cannot place a blind/buried via on only one layer:
1037 if( viaType != VIATYPE::THROUGH )
1038 {
1039 if( currentLayer == targetLayer )
1040 return 0;
1041 }
1042 }
1043 }
1044
1045 // fixme: P&S supports more than one fixed layer pair. Update the dialog?
1046 sizes.ClearLayerPairs();
1047
1048 // Convert blind/buried via to a through hole one, if it goes through all layers
1049 if( viaType == VIATYPE::BLIND_BURIED
1050 && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
1051 || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
1052 {
1053 viaType = VIATYPE::THROUGH;
1054 }
1055
1056 if( targetLayer == UNDEFINED_LAYER )
1057 {
1058 // Implicic layer selection
1059
1060 switch( viaType )
1061 {
1062 case VIATYPE::THROUGH:
1063 // use the default layer pair
1064 currentLayer = pairTop;
1065 targetLayer = pairBottom;
1066 break;
1067
1068 case VIATYPE::MICROVIA:
1069 // Try to use the layer pair preset, if the layers are adjacent,
1070 // because a microvia is usually restricted to 2 adjacent copper layers
1071 if( pairTop > pairBottom ) std::swap( pairTop, pairBottom );
1072
1073 if( currentLayer == pairTop && pairBottom == pairTop+1 )
1074 {
1075 targetLayer = pairBottom;
1076 }
1077 else if( currentLayer == pairBottom && pairBottom == pairTop+1 )
1078 {
1079 targetLayer = pairTop;
1080 }
1081 else if( currentLayer == F_Cu || currentLayer == In1_Cu )
1082 {
1083 // front-side microvia
1084 currentLayer = F_Cu;
1085
1086 if( layerCount > 2 ) // Ensure the inner layer In1_Cu exists
1087 targetLayer = In1_Cu;
1088 else
1089 targetLayer = B_Cu;
1090 }
1091 else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
1092 {
1093 // back-side microvia
1094 currentLayer = B_Cu,
1095 targetLayer = (PCB_LAYER_ID) ( layerCount - 2 );
1096 }
1097 else
1098 {
1099 // This is not optimal: from an internal layer one can want to switch
1100 // to the previous or the next internal layer
1101 // but at this point we do not know what the user want.
1102 targetLayer = PCB_LAYER_ID( currentLayer + 1 );
1103 }
1104
1105 break;
1106
1107 case VIATYPE::BLIND_BURIED:
1108 if( currentLayer == pairTop || currentLayer == pairBottom )
1109 {
1110 // the current layer is on the defined layer pair,
1111 // swap to the other side
1112 currentLayer = pairTop;
1113 targetLayer = pairBottom;
1114 }
1115 else
1116 {
1117 // the current layer is not part of the current layer pair,
1118 // so fallback and swap to the top layer of the pair by default
1119 targetLayer = pairTop;
1120 }
1121
1122 // Do not create a broken via (i.e. a via on only one copper layer)
1123 if( currentLayer == targetLayer )
1124 {
1125 WX_INFOBAR* infobar = frame()->GetInfoBar();
1126 infobar->ShowMessageFor( _( "Blind/buried via need 2 different layers." ),
1127 2000, wxICON_ERROR,
1129 return 0;
1130 }
1131
1132 break;
1133
1134 default:
1135 wxFAIL_MSG( wxT( "unexpected via type" ) );
1136 return 0;
1137 break;
1138 }
1139 }
1140
1141 sizes.SetViaDiameter( bds.m_ViasMinSize );
1142 sizes.SetViaDrill( bds.m_MinThroughDrill );
1143
1144 if( bds.UseNetClassVia() || viaType == VIATYPE::MICROVIA )
1145 {
1146 PCB_VIA dummyVia( board() );
1147 dummyVia.SetViaType( viaType );
1148 dummyVia.SetLayerPair( currentLayer, targetLayer );
1149
1150 if( !m_router->GetCurrentNets().empty() )
1151 dummyVia.SetNet( static_cast<NETINFO_ITEM*>( m_router->GetCurrentNets()[0] ) );
1152
1153 DRC_CONSTRAINT constraint;
1154
1155 constraint = bds.m_DRCEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, &dummyVia, nullptr,
1156 currentLayer );
1157
1158 if( !constraint.IsNull() )
1159 sizes.SetViaDiameter( constraint.m_Value.Opt() );
1160
1161 constraint = bds.m_DRCEngine->EvalRules( HOLE_SIZE_CONSTRAINT, &dummyVia, nullptr,
1162 currentLayer );
1163
1164 if( !constraint.IsNull() )
1165 sizes.SetViaDrill( constraint.m_Value.Opt() );
1166 }
1167 else
1168 {
1169 sizes.SetViaDiameter( bds.GetCurrentViaSize() );
1170 sizes.SetViaDrill( bds.GetCurrentViaDrill() );
1171 }
1172
1173 sizes.SetViaType( viaType );
1174 sizes.AddLayerPair( currentLayer, targetLayer );
1175
1176 m_router->UpdateSizes( sizes );
1177
1178 if( !m_router->IsPlacingVia() )
1180
1181 m_lastTargetLayer = targetLayer;
1182
1184 {
1185 updateEndItem( aEvent );
1187 }
1188 else
1189 {
1190 updateStartItem( aEvent );
1191 }
1192
1193 return 0;
1194}
1195
1196
1198{
1199 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1200 int routingLayer = getStartLayer( m_startItem );
1201
1202 if( !IsCopperLayer( routingLayer ) )
1203 {
1204 editFrame->ShowInfoBarError( _( "Tracks on Copper layers only." ) );
1205 return false;
1206 }
1207
1209 editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
1210
1211 if( !getView()->IsLayerVisible( routingLayer ) )
1212 {
1213 editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1214 editFrame->GetCanvas()->Refresh();
1215 }
1216
1218
1219 m_iface->SetStartLayer( routingLayer );
1220
1222 m_iface->ImportSizes( sizes, m_startItem, nullptr );
1223 sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
1224 frame()->GetScreen()->m_Route_Layer_BOTTOM );
1225
1226 m_router->UpdateSizes( sizes );
1227
1228 if( m_startItem && m_startItem->Net() )
1229 {
1231 {
1233 highlightNets( true, { m_startItem->Net(), coupledNet } );
1234 }
1235 else
1236 {
1237 highlightNets( true, { m_startItem->Net() } );
1238 }
1239 }
1240
1241 controls()->SetAutoPan( true );
1242
1243 if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
1244 {
1245 // It would make more sense to leave the net highlighted as the higher-contrast mode
1246 // makes the router clearances more visible. However, since we just started routing
1247 // the conversion of the screen from low contrast to high contrast is a bit jarring and
1248 // makes the infobar coming up less noticeable.
1249 highlightNets( false );
1250
1252 [&]()
1253 {
1254 m_router->ClearViewDecorations();
1255 } );
1256
1257 controls()->SetAutoPan( false );
1258 return false;
1259 }
1260
1261 m_endItem = nullptr;
1263
1265 frame()->UndoRedoBlock( true );
1266
1267 return true;
1268}
1269
1270
1272{
1274
1275 m_startItem = nullptr;
1276 m_endItem = nullptr;
1277
1280 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1281 controls()->SetAutoPan( false );
1282 controls()->ForceCursorPosition( false );
1283 frame()->UndoRedoBlock( false );
1284 highlightNets( false );
1285
1286 return true;
1287}
1288
1289
1291{
1293
1294 if( !prepareInteractive() )
1295 return;
1296
1297 auto setCursor =
1298 [&]()
1299 {
1300 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1301 };
1302
1303 auto syncRouterAndFrameLayer =
1304 [&]()
1305 {
1306 PCB_LAYER_ID routingLayer = ToLAYER_ID( m_router->GetCurrentLayer() );
1307 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1308
1309 editFrame->SetActiveLayer( routingLayer );
1310
1311 if( !getView()->IsLayerVisible( routingLayer ) )
1312 {
1313 editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1314 editFrame->GetCanvas()->Refresh();
1315 }
1316 };
1317
1318 // Set initial cursor
1319 setCursor();
1320
1321 while( TOOL_EVENT* evt = Wait() )
1322 {
1323 setCursor();
1324
1325 // Don't crash if we missed an operation that canceled routing.
1326 if( !m_router->RoutingInProgress() )
1327 {
1328 if( evt->IsCancelInteractive() )
1329 m_cancelled = true;
1330
1331 break;
1332 }
1333
1334 handleCommonEvents( *evt );
1335
1336 if( evt->IsMotion() )
1337 {
1338 updateEndItem( *evt );
1340 }
1341 else if( evt->IsAction( &PCB_ACTIONS::routerUndoLastSegment )
1342 || evt->IsAction( &ACTIONS::doDelete )
1343 || evt->IsAction( &ACTIONS::undo ) )
1344 {
1345 if( std::optional<VECTOR2I> last = m_router->UndoLastSegment() )
1346 {
1347 getViewControls()->WarpMouseCursor( last.value(), true );
1348 evt->SetMousePosition( last.value() );
1349 }
1350
1351 updateEndItem( *evt );
1353 }
1354 else if( evt->IsAction( &PCB_ACTIONS::routerAttemptFinish ) )
1355 {
1356 bool* autoRouted = evt->Parameter<bool*>();
1357
1358 if( m_router->Finish() )
1359 {
1360 // When we're routing a group of signals automatically we want
1361 // to break up the undo stack every time we have to manually route
1362 // so the user gets nice checkpoints. Remove the APPEND_UNDO flag.
1363 if( autoRouted != nullptr )
1364 *autoRouted = true;
1365
1366 break;
1367 }
1368 else
1369 {
1370 // This acts as check if we were called by the autorouter; we don't want
1371 // to reset APPEND_UNDO if we're auto finishing after route-other-end
1372 if( autoRouted != nullptr )
1373 {
1374 *autoRouted = false;
1375 m_iface->SetCommitFlags( 0 );
1376 }
1377
1378 // Warp the mouse so the user is at the point we managed to route to
1379 controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
1380 }
1381 }
1382 else if( evt->IsAction( &PCB_ACTIONS::routerContinueFromEnd ) )
1383 {
1384 bool needsAppend = m_router->Placer()->HasPlacedAnything();
1385
1387 {
1388 syncRouterAndFrameLayer();
1390 updateEndItem( *evt );
1391
1392 // Warp the mouse to wherever we actually ended up routing to
1393 controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
1394
1395 // We want the next router commit to be one undo at the UI layer
1396 m_iface->SetCommitFlags( needsAppend ? APPEND_UNDO : 0 );
1397 }
1398 else
1399 {
1401 }
1402 }
1403 else if( evt->IsClick( BUT_LEFT )
1404 || evt->IsDrag( BUT_LEFT )
1405 || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
1406 {
1407 updateEndItem( *evt );
1408 bool needLayerSwitch = m_router->IsPlacingVia();
1409 bool forceFinish = evt->Modifier( MD_SHIFT );
1410 bool forceCommit = false;
1411
1412 if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ) )
1413 break;
1414
1415 if( needLayerSwitch )
1417
1418 // Synchronize the indicated layer
1419 syncRouterAndFrameLayer();
1420
1421 updateEndItem( *evt );
1423 m_startItem = nullptr;
1424 }
1425 else if( evt->IsAction( &ACT_SwitchCornerMode ) )
1426 {
1429 updateEndItem( *evt );
1430 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1431 }
1432 else if( evt->IsAction( &ACT_SwitchPosture ) )
1433 {
1435 updateEndItem( *evt );
1436 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1437 }
1438 else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1439 {
1440 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1441 controls()->SetAutoPan( false );
1442 {
1444 }
1445 controls()->SetAutoPan( true );
1446 setCursor();
1448 }
1449 else if( evt->IsAction( &ACTIONS::finishInteractive ) || evt->IsDblClick( BUT_LEFT ) )
1450 {
1451 // Stop current routing:
1452 bool forceFinish = true;
1453 bool forceCommit = false;
1454
1455 m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit );
1456 break;
1457 }
1458 else if( evt->IsCancelInteractive() || evt->IsActivate()
1459 || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
1460 {
1461 if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
1462 m_cancelled = true;
1463
1464 if( evt->IsActivate() && !evt->IsMoveTool() )
1465 m_cancelled = true;
1466
1467 break;
1468 }
1469 else if( evt->IsUndoRedo() )
1470 {
1471 // We're in an UndoRedoBlock. If we get here, something's broken.
1472 wxFAIL;
1473 break;
1474 }
1475 else if( evt->IsClick( BUT_RIGHT ) )
1476 {
1478 }
1479 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
1480 // but we don't at present have that, so we just knock out some of the egregious ones.
1481 else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
1482 {
1483 wxBell();
1484 }
1485 else
1486 {
1487 evt->SetPassEvent();
1488 }
1489 }
1490
1492 // Reset to normal for next route
1493 m_iface->SetCommitFlags( 0 );
1494
1496}
1497
1498
1500{
1502 DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
1503
1504 if( settingsDlg.ShowModal() == wxID_OK )
1505 {
1506 m_router->UpdateSizes( sizes );
1507 m_savedSizes = sizes;
1508
1511 bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
1513 }
1514
1515 return 0;
1516}
1517
1518
1520{
1521 DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
1522
1523 settingsDlg.ShowModal();
1524
1526
1527 return 0;
1528}
1529
1530
1532{
1533 PNS::PNS_MODE mode = aEvent.Parameter<PNS::PNS_MODE>();
1535
1536 settings.SetMode( mode );
1538
1539 return 0;
1540}
1541
1542
1544{
1546 PNS::PNS_MODE mode = settings.Mode();
1547
1548 switch( mode )
1549 {
1550 case PNS::RM_MarkObstacles: mode = PNS::RM_Shove; break;
1551 case PNS::RM_Shove: mode = PNS::RM_Walkaround; break;
1552 case PNS::RM_Walkaround: mode = PNS::RM_MarkObstacles; break;
1553 }
1554
1555 settings.SetMode( mode );
1557
1558 return 0;
1559}
1560
1561
1563{
1564 return m_router->Settings().Mode();
1565}
1566
1567
1569{
1570 return m_router->RoutingInProgress();
1571}
1572
1573
1575{
1576 if( !m_startItem )
1577 return;
1578
1581}
1582
1583
1585{
1587 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1589 PCB_LAYER_ID originalLayer = frame->GetActiveLayer();
1590 bool autoRoute = aEvent.Matches( PCB_ACTIONS::routerAutorouteSelected.MakeEvent() );
1591 bool otherEnd = aEvent.Matches( PCB_ACTIONS::routerRouteSelectedFromEnd.MakeEvent() );
1592
1594 return 0;
1595
1596 // Save selection then clear it for interactive routing
1598
1599 if( selection.Size() == 0 )
1600 return 0;
1601
1603
1604 frame->PushTool( aEvent );
1605
1606 auto setCursor =
1607 [&]()
1608 {
1609 frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1610 };
1611
1612 Activate();
1613 // Must be done after Activate() so that it gets set into the correct context
1614 controls->ShowCursor( true );
1615 controls->ForceCursorPosition( false );
1616 // Set initial cursor
1617 setCursor();
1618
1619 // Get all connected board items, adding pads for any footprints selected
1620 std::vector<BOARD_CONNECTED_ITEM*> itemList;
1621
1623 {
1624 if( item->Type() == PCB_FOOTPRINT_T )
1625 {
1626 const PADS& fpPads = ( static_cast<FOOTPRINT*>( item ) )->Pads();
1627
1628 for( PAD* pad : fpPads )
1629 itemList.push_back( pad );
1630 }
1631 else if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) != nullptr )
1632 {
1633 itemList.push_back( static_cast<BOARD_CONNECTED_ITEM*>( item ) );
1634 }
1635 }
1636
1637 std::shared_ptr<CONNECTIVITY_DATA> connectivity = frame->GetBoard()->GetConnectivity();
1638
1639 // For putting sequential tracks that successfully autoroute into one undo commit
1640 bool groupStart = true;
1641
1642 for( BOARD_CONNECTED_ITEM* item : itemList )
1643 {
1644 // This code is similar to GetRatsnestForPad() but it only adds the anchor for
1645 // the side of the connectivity on this pad. It also checks for ratsnest points
1646 // inside the pad (like a trace end) and counts them.
1647 RN_NET* net = connectivity->GetRatsnestForNet( item->GetNetCode() );
1648
1649 if( !net )
1650 continue;
1651
1652 std::vector<std::shared_ptr<const CN_ANCHOR>> anchors;
1653
1654 for( const CN_EDGE& edge : net->GetEdges() )
1655 {
1656 std::shared_ptr<const CN_ANCHOR> target = edge.GetTargetNode();
1657 std::shared_ptr<const CN_ANCHOR> source = edge.GetSourceNode();
1658
1659 if( !source || source->Dirty() || !target || target->Dirty() )
1660 continue;
1661
1662 if( source->Parent() == item )
1663 anchors.push_back( source );
1664 else if( target->Parent() == item )
1665 anchors.push_back( target );
1666 }
1667
1668 // Route them
1669 for( std::shared_ptr<const CN_ANCHOR> anchor : anchors )
1670 {
1671 // Try to return to the original layer as indicating the user's preferred
1672 // layer for autorouting tracks. The layer can be changed by the user to
1673 // finish tracks that can't complete automatically, but should be changed
1674 // back after.
1675 if( frame->GetActiveLayer() != originalLayer )
1676 frame->SetActiveLayer( originalLayer );
1677
1678 VECTOR2I ignore;
1680 m_startSnapPoint = anchor->Pos();
1681 m_router->SetMode( mode );
1682
1683 // Prime the interactive routing to attempt finish if we are autorouting
1684 bool autoRouted = false;
1685
1686 if( autoRoute )
1688 else if( otherEnd )
1690
1691 // We want autorouted tracks to all be in one undo group except for
1692 // any tracks that need to be manually finished.
1693 // The undo appending for manually finished tracks is handled in peformRouting()
1694 if( groupStart )
1695 groupStart = false;
1696 else
1698
1699 // Start interactive routing. Will automatically finish if possible.
1701
1702 // Route didn't complete automatically, need to a new undo commit
1703 // for the next line so those can group as far as they autoroute
1704 if( !autoRouted )
1705 groupStart = true;
1706 }
1707 }
1708
1709 m_iface->SetCommitFlags( 0 );
1710 frame->PopTool( aEvent );
1711 return 0;
1712}
1713
1714
1716{
1717 if( m_inRouterTool )
1718 return 0;
1719
1721
1723 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1725
1727 {
1728 if( m_router->Mode() == mode )
1729 return 0;
1730 else
1732 }
1733
1734 // Deselect all items
1736
1737 frame->PushTool( aEvent );
1738
1739 auto setCursor =
1740 [&]()
1741 {
1742 frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1743 };
1744
1745 Activate();
1746 // Must be done after Activate() so that it gets set into the correct context
1747 controls->ShowCursor( true );
1748 controls->ForceCursorPosition( false );
1749 // Set initial cursor
1750 setCursor();
1751
1752 m_router->SetMode( mode );
1753 m_cancelled = false;
1754
1755 if( aEvent.HasPosition() )
1756 m_toolMgr->PrimeTool( aEvent.Position() );
1757
1758 // Main loop: keep receiving events
1759 while( TOOL_EVENT* evt = Wait() )
1760 {
1761 if( !evt->IsDrag() )
1762 setCursor();
1763
1764 if( evt->IsCancelInteractive() )
1765 {
1766 frame->PopTool( aEvent );
1767 break;
1768 }
1769 else if( evt->IsActivate() )
1770 {
1771 if( evt->IsMoveTool() || evt->IsEditorTool() )
1772 {
1773 // leave ourselves on the stack so we come back after the move
1774 break;
1775 }
1776 else
1777 {
1778 frame->PopTool( aEvent );
1779 break;
1780 }
1781 }
1782 else if( evt->Action() == TA_UNDO_REDO_PRE )
1783 {
1785 }
1786 else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
1787 {
1789 }
1790 else if( evt->IsMotion() )
1791 {
1792 updateStartItem( *evt );
1793 }
1794 else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
1795 {
1796 updateStartItem( *evt, true );
1798 }
1799 else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
1800 {
1801 updateStartItem( *evt, true );
1803 }
1804 else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
1805 {
1806 updateStartItem( *evt, true );
1807 breakTrack( );
1808 evt->SetPassEvent( false );
1809 }
1810 else if( evt->IsClick( BUT_LEFT )
1811 || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
1812 || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
1813 {
1814 updateStartItem( *evt );
1815
1816 if( evt->HasPosition() )
1817 {
1818 if( evt->Modifier( MD_SHIFT ) )
1820 else
1822 }
1823 }
1824 else if( evt->IsAction( &ACT_PlaceThroughVia ) )
1825 {
1827 }
1828 else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1829 {
1831 updateStartItem( *evt );
1833 }
1834 else if( evt->IsKeyPressed() )
1835 {
1836 // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
1837 // event so we need to process the wxEVT_CHAR event that will follow as long as we
1838 // pass the event.
1839 evt->SetPassEvent();
1840 }
1841 else if( evt->IsClick( BUT_RIGHT ) )
1842 {
1844 }
1845 else
1846 {
1847 evt->SetPassEvent();
1848 }
1849
1850 if( m_cancelled )
1851 {
1852 frame->PopTool( aEvent );
1853 break;
1854 }
1855 }
1856
1857 // Store routing settings till the next invocation
1860
1861 return 0;
1862}
1863
1864
1866{
1868
1869 view()->ClearPreview();
1870 view()->InitPreview();
1871
1873
1874 if( m_startItem && m_startItem->IsLocked() )
1875 {
1876 KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1877 wxOK | wxCANCEL | wxICON_WARNING );
1878 dlg.SetOKLabel( _( "Drag Anyway" ) );
1879 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1880
1881 if( dlg.ShowModal() == wxID_CANCEL )
1882 return;
1883 }
1884
1885 // We don't support dragging arcs inside the PNS right now
1887 {
1890
1891 m_startItem = nullptr;
1892
1893 m_gridHelper->SetAuxAxes( false );
1894 ctls->ForceCursorPosition( false );
1895 highlightNets( false );
1896
1897 m_cancelled = true;
1898
1900
1901 return;
1902 }
1903
1904 bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1905
1906 if( !dragStarted )
1907 return;
1908
1909 if( m_startItem && m_startItem->Net() )
1910 highlightNets( true, { m_startItem->Net() } );
1911
1912 ctls->SetAutoPan( true );
1914 frame()->UndoRedoBlock( true );
1915
1916 while( TOOL_EVENT* evt = Wait() )
1917 {
1918 ctls->ForceCursorPosition( false );
1919
1920 if( evt->IsMotion() )
1921 {
1922 updateEndItem( *evt );
1924
1925 if( PNS::DRAG_ALGO* dragger = m_router->GetDragger() )
1926 {
1927 bool dragStatus;
1928
1929 if( dragger->GetForceMarkObstaclesMode( &dragStatus ) )
1930 {
1931 view()->ClearPreview();
1932
1933 if( !dragStatus )
1934 {
1935 wxString hint;
1936 hint.Printf( _( "(%s to commit anyway.)" ),
1938
1940 statusItem->SetMessage( _( "Track violates DRC." ) );
1941 statusItem->SetHint( hint );
1942 statusItem->SetPosition( frame()->GetToolManager()->GetMousePosition() );
1943 view()->AddToPreview( statusItem );
1944 }
1945 }
1946 }
1947 }
1948 else if( evt->IsClick( BUT_LEFT ) )
1949 {
1950 bool forceFinish = false;
1951 bool forceCommit = evt->Modifier( MD_CTRL );
1952
1953 if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ) )
1954 break;
1955 }
1956 else if( evt->IsClick( BUT_RIGHT ) )
1957 {
1959 }
1960 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1961 {
1962 if( evt->IsCancelInteractive() && !m_startItem )
1963 m_cancelled = true;
1964
1965 if( evt->IsActivate() && !evt->IsMoveTool() )
1966 m_cancelled = true;
1967
1968 break;
1969 }
1970 else if( evt->IsUndoRedo() )
1971 {
1972 // We're in an UndoRedoBlock. If we get here, something's broken.
1973 wxFAIL;
1974 break;
1975 }
1976 else if( evt->Category() == TC_COMMAND )
1977 {
1978 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
1979 // but we don't at present have that, so we just knock out some of the egregious ones.
1980 if( evt->IsAction( &ACTIONS::cut )
1981 || evt->IsAction( &ACTIONS::copy )
1982 || evt->IsAction( &ACTIONS::paste )
1983 || evt->IsAction( &ACTIONS::pasteSpecial )
1985 {
1986 wxBell();
1987 }
1988 // treat an undo as an escape
1989 else if( evt->IsAction( &ACTIONS::undo ) )
1990 {
1991 if( m_startItem )
1992 break;
1993 else
1994 wxBell();
1995 }
1996 else
1997 {
1998 evt->SetPassEvent();
1999 }
2000 }
2001 else
2002 {
2003 evt->SetPassEvent();
2004 }
2005
2006 handleCommonEvents( *evt );
2007 }
2008
2009 view()->ClearPreview();
2010 view()->ShowPreview( false );
2011
2014
2015 m_startItem = nullptr;
2016
2017 m_gridHelper->SetAuxAxes( false );
2018 frame()->UndoRedoBlock( false );
2019 ctls->SetAutoPan( false );
2020 ctls->ForceCursorPosition( false );
2021 highlightNets( false );
2022}
2023
2024
2026 PCB_SELECTION_TOOL* aSelTool )
2027{
2028 /*
2029 * If the collection contains a trivial line corner (two connected segments)
2030 * or a non-fanout-via (a via with no more than two connected segments), then
2031 * trim the collection down to a single item (which one won't matter since
2032 * they're all connected).
2033 */
2034
2035 // First make sure we've got something that *might* match.
2036 int vias = aCollector.CountType( PCB_VIA_T );
2037 int traces = aCollector.CountType( PCB_TRACE_T );
2038 int arcs = aCollector.CountType( PCB_ARC_T );
2039
2040 // We eliminate arcs because they are not supported in the inline drag code.
2041 if( arcs > 0 )
2042 return;
2043
2044 // We need to have at least 1 via or track
2045 if( vias + traces == 0 )
2046 return;
2047
2048 // We cannot drag more than one via at a time
2049 if( vias > 1 )
2050 return;
2051
2052 // We cannot drag more than two track segments at a time
2053 if( traces > 2 )
2054 return;
2055
2056 // Fetch first PCB_TRACK (via or trace) as our reference
2057 PCB_TRACK* reference = nullptr;
2058
2059 for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
2060 reference = dynamic_cast<PCB_TRACK*>( aCollector[i] );
2061
2062 // This should never happen, but just in case...
2063 if( !reference )
2064 return;
2065
2066 int refNet = reference->GetNetCode();
2067
2068 VECTOR2I refPoint( aPt.x, aPt.y );
2069 EDA_ITEM_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
2070
2071 if( flags & STARTPOINT )
2072 refPoint = reference->GetStart();
2073 else if( flags & ENDPOINT )
2074 refPoint = reference->GetEnd();
2075
2076 // Check all items to ensure that any TRACKs are co-terminus with the reference and on
2077 // the same net.
2078 for( int i = 0; i < aCollector.GetCount(); i++ )
2079 {
2080 PCB_TRACK* neighbor = dynamic_cast<PCB_TRACK*>( aCollector[i] );
2081
2082 if( neighbor && neighbor != reference )
2083 {
2084 if( neighbor->GetNetCode() != refNet )
2085 return;
2086
2087 if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
2088 return;
2089 }
2090 }
2091
2092 // Selection meets criteria; trim it to the reference item.
2093 aCollector.Empty();
2094 aCollector.Append( reference );
2095}
2096
2097
2098bool ROUTER_TOOL::CanInlineDrag( int aDragMode )
2099{
2102 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2103
2104 const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
2105
2106 // Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using
2107 // DragArcTrack(), so PCB_ARC_T should never occur here.
2109 {
2110 // Footprints cannot be dragged freely.
2111 if( item->IsType( { PCB_FOOTPRINT_T } ) )
2112 return !( aDragMode & PNS::DM_FREE_ANGLE );
2113 else
2114 return true;
2115 }
2116
2117 return false;
2118}
2119
2120
2122{
2123 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2124
2125 if( selection.Empty() )
2126 {
2129 }
2130
2131 if( selection.Empty() )
2132 return 0;
2133
2134 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
2135
2136 if( item->Type() != PCB_TRACE_T
2137 && item->Type() != PCB_VIA_T
2138 && item->Type() != PCB_FOOTPRINT_T )
2139 {
2140 return 0;
2141 }
2142
2143 std::set<FOOTPRINT*> footprints;
2144
2145 if( item->Type() == PCB_FOOTPRINT_T )
2146 footprints.insert( static_cast<FOOTPRINT*>( item ) );
2147
2148 // We can drag multiple footprints, but not a grab-bag of items
2149 if( selection.Size() > 1 )
2150 {
2151 if( item->Type() != PCB_FOOTPRINT_T )
2152 return 0;
2153
2154 for( int idx = 1; idx < selection.Size(); ++idx )
2155 {
2156 if( static_cast<BOARD_ITEM*>( selection.GetItem( idx ) )->Type() != PCB_FOOTPRINT_T )
2157 return 0;
2158
2159 footprints.insert( static_cast<FOOTPRINT*>( selection.GetItem( idx ) ) );
2160 }
2161 }
2162
2163 // If we overrode locks, we want to clear the flag from the source item before SyncWorld is
2164 // called so that virtual vias are not generated for the (now unlocked) track segment. Note in
2165 // this case the lock can't be reliably re-applied, because there is no guarantee that the end
2166 // state of the drag results in the same number of segments so it's not clear which segment to
2167 // apply the lock state to.
2168 bool wasLocked = false;
2169
2170 if( item->IsLocked() )
2171 {
2172 wasLocked = true;
2173 item->SetLocked( false );
2174 }
2175
2177
2178 frame()->PushTool( aEvent );
2179 Activate();
2180
2181 m_startItem = nullptr;
2182
2183 PNS::ITEM* startItem = nullptr;
2184 PNS::ITEM_SET itemsToDrag;
2185
2186 bool showCourtyardConflicts = frame()->GetPcbNewSettings()->m_ShowCourtyardCollisions;
2187
2188 std::shared_ptr<DRC_ENGINE> drcEngine = m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine();
2189 DRC_INTERACTIVE_COURTYARD_CLEARANCE courtyardClearanceDRC( drcEngine );
2190
2191 std::shared_ptr<CONNECTIVITY_DATA> connectivityData = board()->GetConnectivity();
2192 std::vector<BOARD_ITEM*> dynamicItems;
2193 std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr;
2194 VECTOR2I lastOffset;
2195
2196 if( !footprints.empty() )
2197 {
2198 if( showCourtyardConflicts )
2199 courtyardClearanceDRC.Init( board() );
2200
2201 for( FOOTPRINT* footprint : footprints )
2202 {
2203 for( PAD* pad : footprint->Pads() )
2204 {
2206
2207 if( solid )
2208 itemsToDrag.Add( solid );
2209
2210 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2211 {
2212 if( connectivityData->GetRatsnestForPad( pad ).size() > 0 )
2213 dynamicItems.push_back( pad );
2214 }
2215 }
2216
2217 for( ZONE* zone : footprint->Zones() )
2218 {
2219 std::vector<PNS::ITEM*> solids = m_router->GetWorld()->FindItemsByZone( zone );
2220
2221 for( PNS::ITEM* solid : solids )
2222 itemsToDrag.Add( solid );
2223 }
2224
2225 if( showCourtyardConflicts )
2226 courtyardClearanceDRC.m_FpInMove.push_back( footprint );
2227 }
2228
2229 dynamicData = std::make_unique<CONNECTIVITY_DATA>( board()->GetConnectivity(),
2230 dynamicItems, true );
2231 connectivityData->BlockRatsnestItems( dynamicItems );
2232 }
2233 else
2234 {
2235 startItem = m_router->GetWorld()->FindItemByParent( item );
2236
2237 if( startItem )
2238 itemsToDrag.Add( startItem );
2239 }
2240
2241 GAL* gal = m_toolMgr->GetView()->GetGAL();
2242 VECTOR2I p0 = controls()->GetCursorPosition( false );
2243 VECTOR2I p = p0;
2244
2246 m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
2247
2248 if( startItem )
2249 {
2250 p = snapToItem( startItem, p0 );
2251 m_startItem = startItem;
2252
2253 if( m_startItem->Net() )
2254 highlightNets( true, { m_startItem->Net() } );
2255 }
2256 else if( !footprints.empty() )
2257 {
2258 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
2259
2260 // The mouse is going to be moved on grid before dragging begins.
2261 VECTOR2I tweakedMousePos;
2262 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
2263
2264 // Check if user wants to warp the mouse to origin of moved object
2265
2266 if( editFrame->GetMoveWarpsCursor() )
2267 tweakedMousePos = footprint->GetPosition(); // Use footprint anchor to warp mouse
2268 else
2269 tweakedMousePos = controls()->GetCursorPosition(); // Just use current mouse pos
2270
2271 // We tweak the mouse position using the value from above, and then use that as the
2272 // start position to prevent the footprint from jumping when we start dragging.
2273 // First we move the visual cross hair cursor...
2274 controls()->ForceCursorPosition( true, tweakedMousePos );
2275 controls()->SetCursorPosition( tweakedMousePos ); // ...then the mouse pointer
2276
2277 // Now that the mouse is in the right position, get a copy of the position to use later
2278 p = controls()->GetCursorPosition();
2279 }
2280
2281 int dragMode = aEvent.Parameter<int> ();
2282
2283 bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
2284
2285 if( !dragStarted )
2286 {
2287 if( wasLocked )
2288 item->SetLocked( true );
2289
2290 if( !footprints.empty() )
2291 connectivityData->ClearLocalRatsnest();
2292
2293 // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
2294 courtyardClearanceDRC.ClearConflicts( getView() );
2295
2296 controls()->ForceCursorPosition( false );
2297 frame()->PopTool( aEvent );
2298 highlightNets( false );
2299 return 0;
2300 }
2301
2302 m_gridHelper->SetAuxAxes( true, p );
2303 controls()->ShowCursor( true );
2304 controls()->SetAutoPan( true );
2305 frame()->UndoRedoBlock( true );
2306
2307 view()->ClearPreview();
2308 view()->InitPreview();
2309
2310 auto setCursor =
2311 [&]()
2312 {
2313 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2314 };
2315
2316 // Set initial cursor
2317 setCursor();
2318
2319 // Set the initial visible area
2320 BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
2321 m_router->SetVisibleViewArea( BOX2I( viewAreaD.GetOrigin(), viewAreaD.GetSize() ) );
2322
2323 // Send an initial movement to prime the collision detection
2324 m_router->Move( p, nullptr );
2325
2326 bool hasMouseMoved = false;
2327
2328 while( TOOL_EVENT* evt = Wait() )
2329 {
2330 setCursor();
2331
2332 if( evt->IsCancelInteractive() )
2333 {
2334 if( wasLocked )
2335 item->SetLocked( true );
2336
2337 break;
2338 }
2339 else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
2340 {
2341 hasMouseMoved = true;
2342 updateEndItem( *evt );
2344
2345 view()->ClearPreview();
2346
2347 if( !footprints.empty() )
2348 {
2349 VECTOR2I offset = m_endSnapPoint - p;
2350 BOARD_ITEM* previewItem;
2351
2352 for( FOOTPRINT* footprint : footprints )
2353 {
2354 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2355 {
2356 previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() );
2357 previewItem->Move( offset );
2358
2359 view()->AddToPreview( previewItem );
2360 view()->Hide( drawing, true );
2361 }
2362
2363 for( PAD* pad : footprint->Pads() )
2364 {
2365 if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none()
2366 && pad->GetDrillSize().x == 0 )
2367 {
2368 previewItem = static_cast<BOARD_ITEM*>( pad->Clone() );
2369 previewItem->Move( offset );
2370
2371 view()->AddToPreview( previewItem );
2372 }
2373 else
2374 {
2375 // Pads with copper or holes are handled by the router
2376 }
2377
2378 view()->Hide( pad, true );
2379 }
2380
2381 previewItem = static_cast<BOARD_ITEM*>( footprint->Reference().Clone() );
2382 previewItem->Move( offset );
2383 view()->AddToPreview( previewItem );
2384 view()->Hide( &footprint->Reference() );
2385
2386 previewItem = static_cast<BOARD_ITEM*>( footprint->Value().Clone() );
2387 previewItem->Move( offset );
2388 view()->AddToPreview( previewItem );
2389 view()->Hide( &footprint->Value() );
2390
2391 if( showCourtyardConflicts )
2392 footprint->Move( offset );
2393 }
2394
2395 if( showCourtyardConflicts )
2396 {
2397 courtyardClearanceDRC.Run();
2398 courtyardClearanceDRC.UpdateConflicts( getView(), false );
2399
2400 for( FOOTPRINT* footprint : footprints )
2401 footprint->Move( -offset );
2402 }
2403
2404 // Update ratsnest
2405 dynamicData->Move( offset - lastOffset );
2406 lastOffset = offset;
2407 connectivityData->ComputeLocalRatsnest( dynamicItems, dynamicData.get(), offset );
2408 }
2409
2410 if( PNS::DRAG_ALGO* dragger = m_router->GetDragger() )
2411 {
2412 bool dragStatus;
2413
2414 if( dragger->GetForceMarkObstaclesMode( &dragStatus ) )
2415 {
2416 if( !dragStatus )
2417 {
2418 wxString hint;
2419 hint.Printf( _( "(%s to commit anyway.)" ),
2421
2423 statusItem->SetMessage( _( "Track violates DRC." ) );
2424 statusItem->SetHint( hint );
2425 statusItem->SetPosition( frame()->GetToolManager()->GetMousePosition() );
2426 view()->AddToPreview( statusItem );
2427 }
2428 }
2429 }
2430 }
2431 else if( hasMouseMoved && ( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
2432 {
2433 bool forceFinish = false;
2434 bool forceCommit = evt->Modifier( MD_CTRL );
2435
2436 updateEndItem( *evt );
2437 m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit );
2438 break;
2439 }
2440 else if( evt->IsUndoRedo() )
2441 {
2442 // We're in an UndoRedoBlock. If we get here, something's broken.
2443 wxFAIL;
2444 break;
2445 }
2446 else if( evt->Category() == TC_COMMAND )
2447 {
2448 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
2449 // but we don't at present have that, so we just knock out some of the egregious ones.
2450 if( evt->IsAction( &ACTIONS::cut )
2451 || evt->IsAction( &ACTIONS::copy )
2452 || evt->IsAction( &ACTIONS::paste )
2453 || evt->IsAction( &ACTIONS::pasteSpecial )
2455 {
2456 wxBell();
2457 }
2458 // treat an undo as an escape
2459 else if( evt->IsAction( &ACTIONS::undo ) )
2460 {
2461 if( wasLocked )
2462 item->SetLocked( true );
2463
2464 break;
2465 }
2466 else
2467 {
2468 evt->SetPassEvent();
2469 }
2470 }
2471 else
2472 {
2473 evt->SetPassEvent();
2474 }
2475
2476 handleCommonEvents( *evt );
2477 }
2478
2479 if( !footprints.empty() )
2480 {
2481 for( FOOTPRINT* footprint : footprints )
2482 {
2483 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2484 view()->Hide( drawing, false );
2485
2486 view()->Hide( &footprint->Reference(), false );
2487 view()->Hide( &footprint->Value(), false );
2488
2489 for( PAD* pad : footprint->Pads() )
2490 view()->Hide( pad, false );
2491 }
2492
2493 connectivityData->ClearLocalRatsnest();
2494 }
2495
2496 view()->ClearPreview();
2497 view()->ShowPreview( false );
2498
2499 // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
2500 courtyardClearanceDRC.ClearConflicts( getView() );
2501
2504
2505 m_gridHelper->SetAuxAxes( false );
2506 controls()->SetAutoPan( false );
2507 controls()->ForceCursorPosition( false );
2508 frame()->UndoRedoBlock( false );
2509 frame()->PopTool( aEvent );
2510 highlightNets( false );
2511
2512 return 0;
2513}
2514
2515
2517{
2518 const SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2519
2520 if( selection.Size() != 1 )
2521 return 0;
2522
2523 const BOARD_CONNECTED_ITEM* item =
2524 static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
2525
2526 if( item->Type() != PCB_TRACE_T && item->Type() != PCB_ARC_T )
2527 return 0;
2528
2530
2531 Activate();
2532
2534
2535 TOOL_MANAGER* toolManager = frame()->GetToolManager();
2536 GAL* gal = toolManager->GetView()->GetGAL();
2537
2539 m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
2540
2541 controls()->ForceCursorPosition( false );
2542
2543 if( toolManager->IsContextMenuActive() )
2544 {
2545 // If we're here from a context menu then we need to get the position of the
2546 // cursor when the context menu was invoked. This is used to figure out the
2547 // break point on the track.
2549 }
2550 else
2551 {
2552 // If we're here from a hotkey, then get the current mouse position so we know
2553 // where to break the track.
2554 m_startSnapPoint = snapToItem( m_startItem, controls()->GetCursorPosition() );
2555 }
2556
2557 if( m_startItem && m_startItem->IsLocked() )
2558 {
2559 KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
2560 wxOK | wxCANCEL | wxICON_WARNING );
2561 dlg.SetOKLabel( _( "Break Track" ) );
2562 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
2563
2564 if( dlg.ShowModal() == wxID_CANCEL )
2565 return 0;
2566 }
2567
2568 frame()->UndoRedoBlock( true );
2569 breakTrack();
2570
2573
2574 frame()->UndoRedoBlock( false );
2575
2576 return 0;
2577}
2578
2579
2581{
2583 DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
2584
2585 if( sizeDlg.ShowModal() == wxID_OK )
2586 {
2587 bds.m_TempOverrideTrackWidth = true;
2588 bds.UseCustomTrackViaSize( true );
2589
2592 }
2593
2594 return 0;
2595}
2596
2597
2599{
2601
2602 if( !m_router->GetCurrentNets().empty() )
2604
2605 m_router->UpdateSizes( sizes );
2606
2607 // Changing the track width can affect the placement, so call the
2608 // move routine without changing the destination
2609 // Update end item first to avoid moving to an invalid/missing item
2610 updateEndItem( aEvent );
2612
2614
2615 return 0;
2616}
2617
2618
2620{
2621 std::vector<MSG_PANEL_ITEM> items;
2622
2624 {
2627 PNS::CONSTRAINT constraint;
2628 std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
2629 wxString description;
2630 wxString secondary;
2631 wxString mode;
2632
2634 {
2635 wxASSERT( nets.size() >= 2 );
2636
2637 NETINFO_ITEM* netA = static_cast<NETINFO_ITEM*>( nets[0] );
2638 NETINFO_ITEM* netB = static_cast<NETINFO_ITEM*>( nets[1] );
2639 wxASSERT( netA );
2640 wxASSERT( netB );
2641
2642 description = wxString::Format( _( "Routing Diff Pair: %s" ),
2643 netA->GetNetname() + wxT( ", " ) + netB->GetNetname() );
2644
2645 wxString netclass;
2646 NETCLASS* netclassA = netA->GetNetClass();
2647 NETCLASS* netclassB = netB->GetNetClass();
2648
2649 if( netclassA == netclassB )
2650 netclass = netclassA->GetName();
2651 else
2652 netclass = netclassA->GetName() + wxT( ", " ) + netclassB->GetName();
2653
2654 secondary = wxString::Format( _( "Resolved Netclass: %s" ),
2655 UnescapeString( netclass ) );
2656 }
2657 else if( !nets.empty() && nets[0] )
2658 {
2659 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( nets[0] );
2660
2661 description = wxString::Format( _( "Routing Track: %s" ),
2662 net->GetNetname() );
2663
2664 secondary = wxString::Format( _( "Resolved Netclass: %s" ),
2665 UnescapeString( net->GetNetClass()->GetName() ) );
2666 }
2667 else
2668 {
2669 description = _( "Routing Track" );
2670 secondary = _( "(no net)" );
2671 }
2672
2673 items.emplace_back( description, secondary );
2674
2675 wxString cornerMode;
2676
2678 {
2679 cornerMode = _( "Free-angle" );
2680 }
2681 else
2682 {
2683 switch( m_router->Settings().GetCornerMode() )
2684 {
2685 case DIRECTION_45::CORNER_MODE::MITERED_45: cornerMode = _( "45-degree" ); break;
2686 case DIRECTION_45::CORNER_MODE::ROUNDED_45: cornerMode = _( "45-degree rounded" ); break;
2687 case DIRECTION_45::CORNER_MODE::MITERED_90: cornerMode = _( "90-degree" ); break;
2688 case DIRECTION_45::CORNER_MODE::ROUNDED_90: cornerMode = _( "90-degree rounded" ); break;
2689 default: break;
2690 }
2691 }
2692
2693 items.emplace_back( _( "Corner Style" ), cornerMode );
2694
2695 switch( m_router->Settings().Mode() )
2696 {
2697 case PNS::PNS_MODE::RM_MarkObstacles: mode = _( "Highlight collisions" ); break;
2698 case PNS::PNS_MODE::RM_Walkaround: mode = _( "Walk around" ); break;
2699 case PNS::PNS_MODE::RM_Shove: mode = _( "Shove" ); break;
2700 default: break;
2701 }
2702
2703 items.emplace_back( _( "Mode" ), mode );
2704
2705#define FORMAT_VALUE( x ) frame()->MessageTextFromValue( x )
2706
2708 {
2709 items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2710 FORMAT_VALUE( sizes.DiffPairWidth() ) ),
2711 wxString::Format( _( "(from %s)" ),
2712 sizes.GetDiffPairWidthSource() ) );
2713
2714 items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2715 FORMAT_VALUE( sizes.Clearance() ) ),
2716 wxString::Format( _( "(from %s)" ),
2717 sizes.GetClearanceSource() ) );
2718
2719 items.emplace_back( wxString::Format( _( "Diff Pair Gap: %s" ),
2720 FORMAT_VALUE( sizes.DiffPairGap() ) ),
2721 wxString::Format( _( "(from %s)" ),
2722 sizes.GetDiffPairGapSource() ) );
2723
2724 const PNS::ITEM_SET& traces = m_router->Placer()->Traces();
2725 wxASSERT( traces.Count() == 2 );
2726
2727 if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_MAX_UNCOUPLED, traces[0],
2728 traces[1], m_router->GetCurrentLayer(), &constraint ) )
2729 {
2730 items.emplace_back( wxString::Format( _( "DP Max Uncoupled-length: %s" ),
2731 FORMAT_VALUE( constraint.m_Value.Max() ) ),
2732 wxString::Format( _( "(from %s)" ),
2733 constraint.m_RuleName ) );
2734 }
2735 }
2736 else
2737 {
2738 items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2739 FORMAT_VALUE( sizes.TrackWidth() ) ),
2740 wxString::Format( _( "(from %s)" ),
2741 sizes.GetWidthSource() ) );
2742
2743 items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2744 FORMAT_VALUE( sizes.Clearance() ) ),
2745 wxString::Format( _( "(from %s)" ),
2746 sizes.GetClearanceSource() ) );
2747 }
2748
2749#undef FORMAT_VALUE
2750
2751 frame()->SetMsgPanel( items );
2752 }
2753 else
2754 {
2755 frame()->SetMsgPanel( board() );
2756 return;
2757 }
2758}
2759
2760
2762{
2764
2778
2785
2821
2824}
@ select_w_layer
@ change_entry_orient
@ switch_corner_rounding_shape
@ via_microvia
BOX2< VECTOR2I > BOX2I
Definition: box2.h:853
static TOOL_ACTION paste
Definition: actions.h:70
static TOOL_ACTION cancelInteractive
Definition: actions.h:63
static TOOL_ACTION copy
Definition: actions.h:69
static TOOL_ACTION pasteSpecial
Definition: actions.h:71
static TOOL_ACTION undo
Definition: actions.h:66
static TOOL_ACTION doDelete
Definition: actions.h:75
static TOOL_ACTION cut
Definition: actions.h:68
static TOOL_ACTION finishInteractive
Definition: actions.h:64
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void Clear()
Remove all the entries from the menu (as well as its title).
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:92
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:78
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void SetLayerVisible(int aLayer, bool isVisible)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
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.
void SetDiffPairIndex(unsigned aIndex)
std::shared_ptr< DRC_ENGINE > m_DRCEngine
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
void SetCustomDiffPairGap(int aGap)
Sets custom gap for differential pairs (i.e.
void SetTrackWidthIndex(unsigned aIndex)
Set the current track width list index to aIndex.
void SetViaSizeIndex(unsigned aIndex)
Set the current via size list index to aIndex.
unsigned GetTrackWidthIndex() const
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
unsigned GetViaSizeIndex() const
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 UseCustomDiffPairDimensions(bool aEnabled)
Enables/disables custom differential pair dimensions.
std::vector< int > m_TrackWidthList
unsigned GetDiffPairIndex() 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...
Definition: board_item.h:77
virtual void SetLocked(bool aLocked)
Definition: board_item.h:300
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition: board_item.h:314
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:260
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
virtual bool IsLocked() const
Definition: board_item.cpp:74
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:276
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:695
PROJECT * GetProject() const
Definition: board.h:457
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:806
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:441
const Vec & GetOrigin() const
Definition: box2.h:184
const Vec & GetSize() const
Definition: box2.h:180
CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
void Empty()
Clear the list.
Definition: collector.h:89
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
int CountType(KICAD_T aType)
Count the number of items matching aType.
Definition: collector.h:221
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition: collector.h:99
Implementing DIALOG_TRACK_VIA_SIZE_BASE.
PCB_EDIT_FRAME & m_frame
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
DIFF_PAIR_MENU(PCB_EDIT_FRAME &aFrame)
void update() override
Update menu state stub.
@ ROUNDED_90
H/V with filleted corners.
Definition: direction45.h:71
@ MITERED_90
H/V only (90-degree corners)
Definition: direction45.h:70
@ ROUNDED_45
H/V/45 with filleted corners.
Definition: direction45.h:69
@ MITERED_45
H/V/45 with mitered corners (default)
Definition: direction45.h:68
wxString GetName() const
Definition: drc_rule.h:149
MINOPTMAX< int > m_Value
Definition: drc_rule.h:172
bool IsNull() const
Definition: drc_rule.h:136
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void UpdateConflicts(KIGFX::VIEW *aView, bool aHighlightMoved)
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_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...
WX_INFOBAR * GetInfoBar()
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
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.
Definition: eda_item.h:85
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:172
ZONES & Zones()
Definition: footprint.h:194
PCB_FIELD & Value()
read/write accessors:
Definition: footprint.h:617
PADS & Pads()
Definition: footprint.h:188
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:1948
PCB_FIELD & Reference()
Definition: footprint.h:618
VECTOR2I GetPosition() const override
Definition: footprint.h:206
DRAWINGS & GraphicalItems()
Definition: footprint.h:191
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:206
static const std::vector< KICAD_T > DraggableItems
A scan list for items that can be dragged.
Definition: collectors.h:267
void SetSnap(bool aSnap)
Definition: grid_helper.h:106
void SetUseGrid(bool aSnapToGrid)
Definition: grid_helper.h:109
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0))
Definition: grid_helper.cpp:98
const std::string FormatAsString()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:47
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:56
int ShowModal() override
Definition: confirm.cpp:100
Abstract interface for drawing on a 2D-surface.
BOX2D GetVisibleWorldExtents() const
bool GetGridSnapping() const
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
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)
Definition: view.cpp:1694
virtual int GetTopLayer() const
Definition: view.cpp:818
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:197
void InitPreview()
Definition: view.cpp:1673
void ClearPreview()
Definition: view.cpp:1658
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1584
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1680
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:215
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:82
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:519
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:573
static LSET AllLayersMask()
Definition: lset.cpp:898
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:418
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:884
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:863
T Min() const
Definition: minoptmax.h:33
T Max() const
Definition: minoptmax.h:34
T Opt() const
Definition: minoptmax.h:35
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:44
const wxString GetName() const
Definition: netclass.h:62
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
NETCLASS * GetNetClass()
Definition: netinfo.h:101
int GetNetCode() const
Definition: netinfo.h:108
Definition: pad.h:59
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:140
bool m_ShowCourtyardCollisions
static TOOL_ACTION_GROUP layerDirectSwitchActions()
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:371
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:191
static TOOL_ACTION layerInner12
Definition: pcb_actions.h:347
static TOOL_ACTION routerUndoLastSegment
Definition: pcb_actions.h:252
static TOOL_ACTION layerInner8
Definition: pcb_actions.h:343
static TOOL_ACTION layerInner3
Definition: pcb_actions.h:338
static TOOL_ACTION layerPrev
Definition: pcb_actions.h:368
static TOOL_ACTION routerSettingsDialog
Activation of the Push and Shove settings dialogs.
Definition: pcb_actions.h:261
static TOOL_ACTION layerInner2
Definition: pcb_actions.h:337
static TOOL_ACTION routerAttemptFinish
Definition: pcb_actions.h:255
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:246
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:65
static TOOL_ACTION trackViaSizeChanged
Definition: pcb_actions.h:386
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:376
static TOOL_ACTION layerInner25
Definition: pcb_actions.h:360
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:189
static TOOL_ACTION routerRouteSelectedFromEnd
Definition: pcb_actions.h:257
static TOOL_ACTION routerHighlightMode
Actions to enable switching modes via hotkey assignments.
Definition: pcb_actions.h:265
static TOOL_ACTION routerWalkaroundMode
Definition: pcb_actions.h:267
static TOOL_ACTION routerShoveMode
Definition: pcb_actions.h:266
static TOOL_ACTION layerInner24
Definition: pcb_actions.h:359
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:174
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION layerInner29
Definition: pcb_actions.h:364
static TOOL_ACTION routerAutorouteSelected
Definition: pcb_actions.h:258
static TOOL_ACTION layerInner11
Definition: pcb_actions.h:346
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:262
static TOOL_ACTION routerContinueFromEnd
Definition: pcb_actions.h:254
static TOOL_ACTION layerInner16
Definition: pcb_actions.h:351
static TOOL_ACTION layerInner26
Definition: pcb_actions.h:361
static TOOL_ACTION layerInner18
Definition: pcb_actions.h:353
static TOOL_ACTION layerInner14
Definition: pcb_actions.h:349
static TOOL_ACTION selectLayerPair
Definition: pcb_actions.h:186
static TOOL_ACTION layerInner6
Definition: pcb_actions.h:341
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:192
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:545
static TOOL_ACTION layerInner22
Definition: pcb_actions.h:357
static TOOL_ACTION layerInner5
Definition: pcb_actions.h:340
static TOOL_ACTION layerInner20
Definition: pcb_actions.h:355
static TOOL_ACTION layerInner7
Definition: pcb_actions.h:342
static TOOL_ACTION layerInner27
Definition: pcb_actions.h:362
static TOOL_ACTION layerInner1
Definition: pcb_actions.h:336
static TOOL_ACTION layerInner10
Definition: pcb_actions.h:345
static TOOL_ACTION layerInner15
Definition: pcb_actions.h:350
static TOOL_ACTION layerInner17
Definition: pcb_actions.h:352
static TOOL_ACTION layerBottom
Definition: pcb_actions.h:366
static TOOL_ACTION layerInner19
Definition: pcb_actions.h:354
static TOOL_ACTION layerInner9
Definition: pcb_actions.h:344
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:271
static TOOL_ACTION layerInner30
Definition: pcb_actions.h:365
static TOOL_ACTION layerTop
Definition: pcb_actions.h:335
static TOOL_ACTION cycleRouterMode
Definition: pcb_actions.h:268
static TOOL_ACTION layerInner4
Definition: pcb_actions.h:339
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:243
static TOOL_ACTION layerInner13
Definition: pcb_actions.h:348
static TOOL_ACTION layerInner21
Definition: pcb_actions.h:356
static TOOL_ACTION layerNext
Definition: pcb_actions.h:367
static TOOL_ACTION routerRouteSelected
Definition: pcb_actions.h:256
static TOOL_ACTION layerInner23
Definition: pcb_actions.h:358
static TOOL_ACTION layerInner28
Definition: pcb_actions.h:363
Common, abstract interface for edit frames.
APPEARANCE_CONTROLS * GetAppearancePanel()
void UndoRedoBlock(bool aBlock=true)
Enable/disable undo and redo operations.
PCB_LAYER_ID SelectOneLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Show the dialog box for a layer selection.
Definition: sel_layer.cpp:285
PCBNEW_SETTINGS * GetPcbNewSettings() const
virtual PCB_LAYER_ID GetActiveLayer() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
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.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_field.cpp:155
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const STRING_UTF8_MAP *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
Definition: pcb_screen.h:43
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:44
The selection tool: currently supports:
KIGFX::PCB_VIEW * view() const
PCB_BASE_EDIT_FRAME * frame() const
KIGFX::VIEW_CONTROLS * controls() const
BOARD * board() const
PCBNEW_SETTINGS::DISPLAY_OPTIONS & displayOptions() const
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:109
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:112
const VECTOR2I & GetStart() const
Definition: pcb_track.h:113
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:110
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...
Definition: pcb_track.cpp:398
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/.
Definition: pcb_track.cpp:714
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:404
DRAG_ALGO.
Definition: pns_drag_algo.h:44
int Count(int aKindMask=-1) const
Definition: pns_itemset.h:66
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
Base class for PNS router board items.
Definition: pns_item.h:97
virtual NET_HANDLE Net() const
Definition: pns_item.h:193
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:166
@ SEGMENT_T
Definition: pns_item.h:105
const LAYER_RANGE & Layers() const
Definition: pns_item.h:195
bool OfKind(int aKindMask) const
Definition: pns_item.h:174
bool IsLocked() const
Definition: pns_item.h:246
static wxString FormatLogFileAsString(int aMode, const std::vector< ITEM * > &aAddedItems, const std::set< KIID > &aRemovedItems, const std::vector< ITEM * > &aHeads, const std::vector< EVENT_ENTRY > &aEvents)
Definition: pns_logger.cpp:67
std::vector< ITEM * > FindItemsByZone(const ZONE *aParent)
Definition: pns_node.cpp:1678
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
Definition: pns_node.cpp:1658
virtual const VECTOR2I & CurrentEnd() const =0
Function CurrentEnd()
virtual const ITEM_SET Traces()=0
Function Traces()
virtual bool HasPlacedAnything() const
virtual const VECTOR2I & CurrentStart() const =0
Function CurrentStart()
void SetMode(ROUTER_MODE aMode)
bool SwitchLayer(int layer)
Definition: pns_router.cpp:948
void StopRouting()
Definition: pns_router.cpp:905
void ClearViewDecorations()
Definition: pns_router.cpp:933
void ToggleCornerMode()
PLACEMENT_ALGO * Placer()
Definition: pns_router.h:216
void ClearWorld()
Definition: pns_router.cpp:104
void BreakSegmentOrArc(ITEM *aItem, const VECTOR2I &aP)
bool ContinueFromEnd(ITEM **aNewStartItem)
Definition: pns_router.cpp:573
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:722
LOGGER * Logger()
Definition: pns_router.cpp:992
ROUTER_MODE Mode() const
Definition: pns_router.h:136
void CommitRouting()
Definition: pns_router.cpp:896
bool Finish()
Definition: pns_router.cpp:525
void SyncWorld()
Definition: pns_router.cpp:94
const wxString & FailureReason() const
Definition: pns_router.h:214
bool IsPlacingVia() const
Definition: pns_router.cpp:998
void FlipPosture()
Definition: pns_router.cpp:939
RULE_RESOLVER * GetRuleResolver() const
Definition: pns_router.h:180
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:192
DRAG_ALGO * GetDragger()
Definition: pns_router.h:140
bool RoutingInProgress() const
Definition: pns_router.cpp:117
RouterState GetState() const
Definition: pns_router.h:138
std::optional< VECTOR2I > UndoLastSegment()
Definition: pns_router.cpp:884
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:156
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:390
void SetVisibleViewArea(const BOX2I &aExtents)
Definition: pns_router.h:220
int GetCurrentLayer() const
Definition: pns_router.cpp:981
void GetUpdatedItems(std::vector< PNS::ITEM * > &aRemoved, std::vector< PNS::ITEM * > &aAdded, std::vector< PNS::ITEM * > &aHeads)
Definition: pns_router.cpp:776
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:211
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish, bool aForceCommit)
Definition: pns_router.cpp:858
void ToggleViaPlacement()
Definition: pns_router.cpp:957
NODE * GetWorld() const
Definition: pns_router.h:164
const std::vector< NET_HANDLE > GetCurrentNets() const
Definition: pns_router.cpp:970
bool Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:450
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.
DIRECTION_45::CORNER_MODE GetCornerMode() const
virtual NET_HANDLE DpCoupledNet(NET_HANDLE aNet)=0
void SetViaType(VIATYPE aViaType)
void SetTrackWidth(int aWidth)
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)
std::optional< int > PairedLayer(int aLayerId)
bool TrackWidthIsExplicit() const
void SetViaDiameter(int aDiameter)
wxString GetWidthSource() const
void SetWidthSource(const wxString &aSource)
virtual void updateStartItem(const TOOL_EVENT &aEvent, bool aIgnorePads=false)
const VECTOR2I snapToItem(ITEM *aSnapToItem, const VECTOR2I &aP)
virtual void highlightNets(bool aEnabled, std::set< NET_HANDLE > aNetcodes={})
SIZES_SETTINGS m_savedSizes
Definition: pns_tool_base.h:70
PNS_KICAD_IFACE * m_iface
Definition: pns_tool_base.h:79
ITEM * m_startItem
Definition: pns_tool_base.h:71
virtual void updateEndItem(const TOOL_EVENT &aEvent)
ROUTER * m_router
Definition: pns_tool_base.h:80
VECTOR2I m_endSnapPoint
Definition: pns_tool_base.h:76
PCB_GRID_HELPER * m_gridHelper
Definition: pns_tool_base.h:78
VECTOR2I m_startSnapPoint
Definition: pns_tool_base.h:72
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, PNS::NET_HANDLE aNet) override
PNS::RULE_RESOLVER * GetRuleResolver() override
void SetStartLayer(int aLayer)
BOARD * GetBoard() const
void SetCommitFlags(int aCommitFlags)
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
Container for project specific data.
Definition: project.h:62
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:172
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:166
Describe ratsnest for a single net.
Definition: ratsnest_data.h:63
const std::vector< CN_EDGE > & GetEdges() const
Definition: ratsnest_data.h:96
void SetMessage(const wxString &aStatus)
void SetHint(const wxString &aHint)
void SetPosition(const VECTOR2I &aPos) override
int onViaCommand(const TOOL_EVENT &aEvent)
int InlineDrag(const TOOL_EVENT &aEvent)
std::shared_ptr< ACTION_MENU > m_trackViaMenu
Definition: router_tool.h:94
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int onTrackViaSizeChanged(const TOOL_EVENT &aEvent)
int CustomTrackWidthDialog(const TOOL_EVENT &aEvent)
static void NeighboringSegmentFilter(const VECTOR2I &aPt, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *aSelTool)
PNS::PNS_MODE GetRouterMode()
void saveRouterDebugLog()
void performDragging(int aMode=PNS::DM_ANY)
PCB_LAYER_ID m_originalActiveLayer
Definition: router_tool.h:97
int onLayerCommand(const TOOL_EVENT &aEvent)
int CycleRouterMode(const TOOL_EVENT &aEvent)
bool m_inRouterTool
Definition: router_tool.h:99
int handleLayerSwitch(const TOOL_EVENT &aEvent, bool aForceVia)
bool prepareInteractive()
int getStartLayer(const PNS::ITEM *aItem)
void switchLayerOnViaPlacement()
int RouteSelected(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
bool finishInteractive()
int ChangeRouterMode(const TOOL_EVENT &aEvent)
std::shared_ptr< ACTION_MENU > m_diffPairMenu
Definition: router_tool.h:93
void handleCommonEvents(TOOL_EVENT &evt)
bool Init() override
Init() is called once upon a registration of the tool.
int InlineBreakTrack(const TOOL_EVENT &aEvent)
void performRouting()
bool RoutingInProgress()
Returns whether routing is currently active.
void breakTrack()
void UpdateMessagePanel()
int MainLoop(const TOOL_EVENT &aEvent)
bool CanInlineDrag(int aDragMode)
int SettingsDialog(const TOOL_EVENT &aEvent)
int DpDimensionsDialog(const TOOL_EVENT &aEvent)
int m_lastTargetLayer
Definition: router_tool.h:96
void updateSizesAfterLayerSwitch(PCB_LAYER_ID targetLayer, const VECTOR2I &aPos)
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:337
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:75
const std::vector< EDA_ITEM * > GetItemsSortedBySelectionOrder() const
Definition: selection.cpp:222
EDA_ITEM * Front() const
Definition: selection.h:208
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:109
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
bool GetMoveWarpsCursor() const
Indicate that a move operation should warp the mouse pointer to the origin of the move object.
Definition: tools_holder.h:150
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
Build up the properties of a TOOL_ACTION in an incremental manner that is static-construction safe.
Definition: tool_action.h:102
Represent a single user action.
Definition: tool_action.h:269
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
Base abstract interface for all kinds of tools.
Definition: tool_base.h:66
virtual void Reset(RESET_REASON aReason)=0
Bring the tool to a known, initial state.
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
bool IsToolActive() const
Definition: tool_base.cpp:31
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ RUN
Tool is invoked after being inactive.
Definition: tool_base.h:79
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool HasPosition() const
Definition: tool_event.h:256
bool DisableGridSnapping() const
Definition: tool_event.h:363
int KeyCode() const
Definition: tool_event.h:368
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition: tool_event.h:384
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:285
bool IsKeyPressed() const
Definition: tool_event.h:373
TOOL_EVENT_CATEGORY Category() const
Returns more specific information about the type of an event.
Definition: tool_event.h:243
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:358
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:82
bool IsActionInGroup(const TOOL_ACTION_GROUP &aGroup) const
Definition: tool_event.cpp:88
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:460
void SetPassEvent(bool aPass=true)
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition: tool_event.h:252
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
Master controller class:
Definition: tool_manager.h:57
VECTOR2D GetMenuCursorPos() const
Definition: tool_manager.h:535
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
void PrimeTool(const VECTOR2D &aPosition)
"Prime" a tool by sending a cursor left-click event with the mouse position set to the passed in posi...
bool PostAction(const std::string &aActionName, T aParam)
Run the specified action after the current action (coroutine) ends.
Definition: tool_manager.h:230
bool IsContextMenuActive() const
True while processing a context menu.
Definition: tool_manager.h:506
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:378
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void RegisterSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:50
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
TRACK_WIDTH_MENU(PCB_EDIT_FRAME &aFrame)
void update() override
Update menu state stub.
PCB_EDIT_FRAME & m_frame
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:75
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.
Definition: wx_infobar.cpp:140
static bool IsZoneFillAction(const TOOL_EVENT *aEvent)
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
This file is part of the common library.
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:63
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:66
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:56
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:51
#define _(s)
#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
Definition: export_idf.cpp:53
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
#define PSEUDO_WXK_CLICK
Definition: hotkeys_basic.h:50
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:879
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:96
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ In1_Cu
Definition: layer_ids.h:66
@ F_Cu
Definition: layer_ids.h:65
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:247
PNS_MODE
< Routing modes
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
@ RM_Shove
Only shove.
void * NET_HANDLE
Definition: pns_item.h:54
ROUTER_MODE
Definition: pns_router.h:62
@ PNS_MODE_ROUTE_DIFF_PAIR
Definition: pns_router.h:64
@ DM_ANY
Definition: pns_router.h:77
@ DM_FREE_ANGLE
Definition: pns_router.h:75
void(* CLIENT_SELECTION_FILTER)(const VECTOR2I &, GENERAL_COLLECTOR &, PCB_SELECTION_TOOL *)
VIATYPE
Definition: pcb_track.h:64
@ BLIND_BURIED
@ ID_POPUP_PCB_SELECT_WIDTH1
Definition: pcbnew_id.h:29
@ ID_POPUP_PCB_SELECT_DIFFPAIR16
Definition: pcbnew_id.h:78
@ ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES
Definition: pcbnew_id.h:28
@ ID_POPUP_PCB_SELECT_WIDTH16
Definition: pcbnew_id.h:44
@ ID_POPUP_PCB_SELECT_AUTO_WIDTH
Definition: pcbnew_id.h:27
@ ID_POPUP_PCB_SELECT_CUSTOM_WIDTH
Definition: pcbnew_id.h:26
@ ID_POPUP_PCB_SELECT_DIFFPAIR1
Definition: pcbnew_id.h:63
@ ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR
Definition: pcbnew_id.h:62
@ ID_POPUP_PCB_SELECT_VIASIZE1
Definition: pcbnew_id.h:45
@ ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR
Definition: pcbnew_id.h:61
@ ID_POPUP_PCB_SELECT_VIASIZE16
Definition: pcbnew_id.h:60
Class that computes missing connections on a PCB.
#define FORMAT_VALUE(x)
static const TOOL_ACTION ACT_PlaceBlindVia(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.PlaceBlindVia") .Scope(AS_CONTEXT) .DefaultHotkey(MD_ALT+MD_SHIFT+ 'V') .LegacyHotkeyName("Add Blind/Buried Via") .FriendlyName(_("Place Blind/Buried Via")) .Tooltip(_("Adds a blind or buried via at the end of currently routed track.")) .Icon(BITMAPS::via_buried) .Flags(AF_NONE) .Parameter< int >(VIA_ACTION_FLAGS::BLIND_VIA))
static VIATYPE getViaTypeFromFlags(int aFlags)
static const TOOL_ACTION ACT_PlaceMicroVia(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.PlaceMicroVia") .Scope(AS_CONTEXT) .DefaultHotkey(MD_CTRL+ 'V') .LegacyHotkeyName("Add MicroVia") .FriendlyName(_("Place Microvia")) .Tooltip(_("Adds a microvia at the end of currently routed track.")) .Icon(BITMAPS::via_microvia) .Flags(AF_NONE) .Parameter< int >(VIA_ACTION_FLAGS::MICROVIA))
static const TOOL_ACTION ACT_SelLayerAndPlaceBlindVia(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia") .Scope(AS_CONTEXT) .DefaultHotkey(MD_ALT+'<') .LegacyHotkeyName("Select Layer and Add Blind/Buried Via") .FriendlyName(_("Select Layer and Place Blind/Buried Via...")) .Tooltip(_("Select a layer, then add a blind or buried via at the end of currently routed track.")) .Icon(BITMAPS::select_w_layer) .Flags(AF_NONE) .Parameter< int >(VIA_ACTION_FLAGS::BLIND_VIA|VIA_ACTION_FLAGS::SELECT_LAYER))
static const TOOL_ACTION ACT_SwitchPosture(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.SwitchPosture") .Scope(AS_CONTEXT) .DefaultHotkey('/') .LegacyHotkeyName("Switch Track Posture") .FriendlyName(_("Switch Track Posture")) .Tooltip(_("Switches posture of the currently routed track.")) .Icon(BITMAPS::change_entry_orient))
VIA_ACTION_FLAGS
Flags used by via tool actions.
Definition: router_tool.cpp:90
@ BLIND_VIA
blind/buried via
Definition: router_tool.cpp:94
@ SELECT_LAYER
Ask user to select layer before adding via.
Definition: router_tool.cpp:98
@ MICROVIA
Microvia.
Definition: router_tool.cpp:95
@ VIA_MASK
Definition: router_tool.cpp:92
@ VIA
Normal via.
Definition: router_tool.cpp:93
static const TOOL_ACTION ACT_SwitchCornerMode(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.SwitchRounding") .Scope(AS_CONTEXT) .DefaultHotkey(MD_CTRL+'/') .FriendlyName(_("Track Corner Mode")) .Tooltip(_("Switches between sharp/rounded and 45°/90° corners when routing tracks.")) .Icon(BITMAPS::switch_corner_rounding_shape))
static const TOOL_ACTION ACT_SelLayerAndPlaceThroughVia(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.SelLayerAndPlaceVia") .Scope(AS_CONTEXT) .DefaultHotkey('<') .LegacyHotkeyName("Select Layer and Add Through Via") .FriendlyName(_("Select Layer and Place Through Via...")) .Tooltip(_("Select a layer, then add a through-hole via at the end of currently routed track.")) .Icon(BITMAPS::select_w_layer) .Flags(AF_NONE) .Parameter< int >(VIA_ACTION_FLAGS::VIA|VIA_ACTION_FLAGS::SELECT_LAYER))
static const TOOL_ACTION ACT_SelLayerAndPlaceMicroVia(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia") .Scope(AS_CONTEXT) .FriendlyName(_("Select Layer and Place Micro Via...")) .Tooltip(_("Select a layer, then add a micro via at the end of currently routed track.")) .Icon(BITMAPS::select_w_layer) .Flags(AF_NONE) .Parameter< int >(VIA_ACTION_FLAGS::MICROVIA|VIA_ACTION_FLAGS::SELECT_LAYER))
static const TOOL_ACTION ACT_PlaceThroughVia(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.PlaceVia") .Scope(AS_CONTEXT) .DefaultHotkey( 'V') .LegacyHotkeyName("Add Through Via") .FriendlyName(_("Place Through Via")) .Tooltip(_("Adds a through-hole via at the end of currently routed track.")) .Icon(BITMAPS::via) .Flags(AF_NONE) .Parameter< int >(VIA_ACTION_FLAGS::VIA))
#define _(s)
static const TOOL_ACTION ACT_CustomTrackWidth(TOOL_ACTION_ARGS() .Name("pcbnew.InteractiveRouter.CustomTrackViaSize") .Scope(AS_CONTEXT) .DefaultHotkey( 'Q') .LegacyHotkeyName("Custom Track/Via Size") .FriendlyName(_("Custom Track/Via Size...")) .Tooltip(_("Shows a dialog for changing the track width and via size.")) .Icon(BITMAPS::width_track))
#define APPEND_UNDO
Definition: sch_commit.h:41
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...
Definition: pns_node.h:73
wxString m_RuleName
Definition: pns_node.h:77
MINOPTMAX< int > m_Value
Definition: pns_node.h:75
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
@ AS_CONTEXT
Action belongs to a particular tool (i.e. a part of a pop-up menu)
Definition: tool_action.h:46
@ AF_NONE
Definition: tool_action.h:54
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:629
@ TA_MODEL_CHANGE
Definition: tool_event.h:120
@ TA_UNDO_REDO_PRE
Definition: tool_event.h:105
@ TA_UNDO_REDO_POST
Definition: tool_event.h:108
@ TC_COMMAND
Definition: tool_event.h:56
@ TC_MOUSE
Definition: tool_event.h:54
@ TC_VIEW
Definition: tool_event.h:58
@ MD_ALT
Definition: tool_event.h:144
@ MD_CTRL
Definition: tool_event.h:143
@ MD_SHIFT
Definition: tool_event.h:142
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
wxPoint ToWxPoint(const VECTOR2I &aSize)
Definition: vector2wx.h:50
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.