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 <confirm.h>
48#include <kidialog.h>
49#include <widgets/wx_infobar.h>
54#include <bitmaps.h>
55#include <string_utils.h>
56#include <gal/painter.h>
57#include <tool/action_menu.h>
58#include <tool/tool_manager.h>
59#include <tool/tool_menu.h>
60#include <tools/pcb_actions.h>
63#include <tools/drc_tool.h>
66#include <view/view_controls.h>
67
68#include <project.h>
71
72#include "router_tool.h"
74#include "pns_router.h"
75#include "pns_itemset.h"
76#include "pns_logger.h"
77#include "pns_placement_algo.h"
78#include "pns_drag_algo.h"
79
80#include "pns_kicad_iface.h"
81
83
85
86using namespace KIGFX;
87
92{
93 // Via type
94 VIA_MASK = 0x03,
95 VIA = 0x00,
96 BLIND_VIA = 0x01,
97 MICROVIA = 0x02,
98
99 // Select layer
101};
102
103
104// Actions, being statically-defined, require specialized I18N handling. We continue to
105// use the _() macro so that string harvesting by the I18N framework doesn't have to be
106// specialized, but we don't translate on initialization and instead do it in the getters.
107
108#undef _
109#define _(s) s
110
111// Pass all the parameters as int to allow combining flags
113 .Name( "pcbnew.InteractiveRouter.PlaceVia" )
114 .Scope( AS_CONTEXT )
115 .DefaultHotkey( 'V' )
116 .LegacyHotkeyName( "Add Through Via" )
117 .FriendlyName( _( "Place Through Via" ) )
118 .Tooltip( _( "Adds a through-hole via at the end of currently routed track." ) )
119 .Icon( BITMAPS::via )
120 .Flags( AF_NONE )
121 .Parameter<int>( VIA_ACTION_FLAGS::VIA ) );
122
124 .Name( "pcbnew.InteractiveRouter.PlaceBlindVia" )
125 .Scope( AS_CONTEXT )
126 .DefaultHotkey( MD_ALT + MD_SHIFT + 'V' )
127 .LegacyHotkeyName( "Add Blind/Buried Via" )
128 .FriendlyName( _( "Place Blind/Buried Via" ) )
129 .Tooltip( _( "Adds a blind or buried via at the end of currently routed track.") )
130 .Icon( BITMAPS::via_buried )
131 .Flags( AF_NONE )
132 .Parameter<int>( VIA_ACTION_FLAGS::BLIND_VIA ) );
133
135 .Name( "pcbnew.InteractiveRouter.PlaceMicroVia" )
136 .Scope( AS_CONTEXT )
137 .DefaultHotkey( MD_CTRL + 'V' )
138 .LegacyHotkeyName( "Add MicroVia" )
139 .FriendlyName( _( "Place Microvia" ) )
140 .Tooltip( _( "Adds a microvia at the end of currently routed track." ) )
141 .Icon( BITMAPS::via_microvia )
142 .Flags( AF_NONE )
143 .Parameter<int>( VIA_ACTION_FLAGS::MICROVIA ) );
144
146 .Name( "pcbnew.InteractiveRouter.SelLayerAndPlaceVia" )
147 .Scope( AS_CONTEXT )
148 .DefaultHotkey( '<' )
149 .LegacyHotkeyName( "Select Layer and Add Through Via" )
150 .FriendlyName( _( "Select Layer and Place Through Via..." ) )
151 .Tooltip( _( "Select a layer, then add a through-hole via at the end of currently routed track." ) )
153 .Flags( AF_NONE )
155
157 .Name( "pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia" )
158 .Scope( AS_CONTEXT )
159 .DefaultHotkey( MD_ALT + '<' )
160 .LegacyHotkeyName( "Select Layer and Add Blind/Buried Via" )
161 .FriendlyName( _( "Select Layer and Place Blind/Buried Via..." ) )
162 .Tooltip( _( "Select a layer, then add a blind or buried via at the end of currently routed track." ) )
164 .Flags( AF_NONE )
166
168 .Name( "pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia" )
169 .Scope( AS_CONTEXT )
170 .FriendlyName( _( "Select Layer and Place Micro Via..." ) )
171 .Tooltip( _( "Select a layer, then add a micro via at the end of currently routed track." ) )
173 .Flags( AF_NONE )
175
177 .Name( "pcbnew.InteractiveRouter.CustomTrackViaSize" )
178 .Scope( AS_CONTEXT )
179 .DefaultHotkey( 'Q' )
180 .LegacyHotkeyName( "Custom Track/Via Size" )
181 .FriendlyName( _( "Custom Track/Via Size..." ) )
182 .Tooltip( _( "Shows a dialog for changing the track width and via size." ) )
183 .Icon( BITMAPS::width_track ) );
184
186 .Name( "pcbnew.InteractiveRouter.SwitchPosture" )
187 .Scope( AS_CONTEXT )
188 .DefaultHotkey( '/' )
189 .LegacyHotkeyName( "Switch Track Posture" )
190 .FriendlyName( _( "Switch Track Posture" ) )
191 .Tooltip( _( "Switches posture of the currently routed track." ) )
193
195 .Name( "pcbnew.InteractiveRouter.SwitchRounding" )
196 .Scope( AS_CONTEXT )
197 .DefaultHotkey( MD_CTRL + '/' )
198 .FriendlyName( _( "Track Corner Mode" ) )
199 .Tooltip( _( "Switches between sharp/rounded and 45°/90° corners when routing tracks." ) )
201
202#undef _
203#define _(s) wxGetTranslation((s))
204
205
207 TOOL_BASE( "pcbnew.InteractiveRouter" ),
208 m_lastTargetLayer( UNDEFINED_LAYER ),
209 m_originalActiveLayer( UNDEFINED_LAYER ),
210 m_inRouterTool( false )
211{
212}
213
214
216{
217public:
219 ACTION_MENU( true ),
220 m_frame( aFrame )
221 {
222 SetIcon( BITMAPS::width_track_via );
223 SetTitle( _( "Select Track/Via Width" ) );
224 }
225
226protected:
227 ACTION_MENU* create() const override
228 {
229 return new TRACK_WIDTH_MENU( m_frame );
230 }
231
232 void update() override
233 {
235 bool useIndex = !bds.m_UseConnectedTrackWidth &&
237 wxString msg;
238
239 Clear();
240
241 Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
242 _( "Route using the width of the starting track." ), wxITEM_CHECK );
245
246 Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
247 _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
249 useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
250
251 Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
252 _( "Specify custom track and via sizes" ), wxITEM_CHECK );
254
255 AppendSeparator();
256
257 // Append the list of tracks & via sizes
258 for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
259 {
260 int width = bds.m_TrackWidthList[i];
261
262 if( i == 0 )
263 msg = _( "Track netclass width" );
264 else
265 msg.Printf( _( "Track %s" ), m_frame.MessageTextFromValue( width ) );
266
267 int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
268 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
269 Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
270 }
271
272 AppendSeparator();
273
274 for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
275 {
277
278 if( i == 0 )
279 msg = _( "Via netclass values" );
280 else
281 {
282 if( via.m_Drill > 0 )
283 {
284 msg.Printf( _("Via %s, hole %s" ),
285 m_frame.MessageTextFromValue( via.m_Diameter ),
286 m_frame.MessageTextFromValue( via.m_Drill ) );
287 }
288 else
289 {
290 msg.Printf( _( "Via %s" ),
291 m_frame.MessageTextFromValue( via.m_Diameter ) );
292 }
293 }
294
295 int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
296 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
297 Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
298 }
299 }
300
301 OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
302 {
304 int id = aEvent.GetId();
305
306 // On Windows, this handler can be called with an event ID not existing in any
307 // menuitem, so only set flags when we have an ID match.
308
310 {
311 bds.UseCustomTrackViaSize( true );
312 bds.m_TempOverrideTrackWidth = true;
314 }
315 else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
316 {
317 bds.UseCustomTrackViaSize( false );
318 bds.m_UseConnectedTrackWidth = true;
319 bds.m_TempOverrideTrackWidth = false;
320 }
322 {
323 bds.UseCustomTrackViaSize( false );
324 bds.m_UseConnectedTrackWidth = false;
325 bds.SetViaSizeIndex( 0 );
326 bds.SetTrackWidthIndex( 0 );
327 }
329 {
330 bds.UseCustomTrackViaSize( false );
332 }
334 {
335 bds.UseCustomTrackViaSize( false );
336 bds.m_TempOverrideTrackWidth = true;
338 }
339
341 }
342
343private:
345};
346
347
349{
350public:
352 ACTION_MENU( true ),
353 m_frame( aFrame )
354 {
355 SetIcon( BITMAPS::width_track_via );
356 SetTitle( _( "Select Differential Pair Dimensions" ) );
357 }
358
359protected:
360 ACTION_MENU* create() const override
361 {
362 return new DIFF_PAIR_MENU( m_frame );
363 }
364
365 void update() override
366 {
368
369 Clear();
370
371 Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
372 _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
374 !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
375
376 Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
377 _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
379
380 AppendSeparator();
381
382 // Append the list of differential pair dimensions
383
384 // Drop index 0 which is the current netclass dimensions (which are handled above)
385 for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
386 {
388 wxString msg;
389
390 if( diffPair.m_Gap <= 0 )
391 {
392 if( diffPair.m_ViaGap <= 0 )
393 {
394 msg.Printf( _( "Width %s" ),
396 }
397 else
398 {
399 msg.Printf( _( "Width %s, via gap %s" ),
402 }
403 }
404 else
405 {
406 if( diffPair.m_ViaGap <= 0 )
407 {
408 msg.Printf( _( "Width %s, gap %s" ),
410 m_frame.MessageTextFromValue( diffPair.m_Gap ) );
411 }
412 else
413 {
414 msg.Printf( _( "Width %s, gap %s, via gap %s" ),
418 }
419 }
420
421 int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
422 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
423 Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
424 }
425 }
426
427 OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
428 {
430 int id = aEvent.GetId();
431
432 // On Windows, this handler can be called with an event ID not existing in any
433 // menuitem, so only set flags when we have an ID match.
434
436 {
437 bds.UseCustomDiffPairDimensions( true );
438 TOOL_MANAGER* toolManager = m_frame.GetToolManager();
440 }
442 {
443 bds.UseCustomDiffPairDimensions( false );
444 bds.SetDiffPairIndex( 0 );
445 }
447 {
448 bds.UseCustomDiffPairDimensions( false );
449 // remember that the menu doesn't contain index 0 (which is the netclass values)
451 }
452
454 }
455
456private:
458};
459
460
462{
463}
464
465
467{
470
471 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
472
473 wxASSERT( frame );
474
475 auto& menu = m_menu.GetMenu();
476 menu.SetTitle( _( "Interactive Router" ) );
477
478 m_trackViaMenu = std::make_shared<TRACK_WIDTH_MENU>( *frame );
479 m_trackViaMenu->SetTool( this );
481
482 m_diffPairMenu = std::make_shared<DIFF_PAIR_MENU>( *frame );
483 m_diffPairMenu->SetTool( this );
485
486 auto haveHighlight =
487 [&]( const SELECTION& sel )
488 {
490
491 return !cfg->GetHighlightNetCodes().empty();
492 };
493
494 auto notRoutingCond =
495 [this]( const SELECTION& )
496 {
497 return !m_router->RoutingInProgress();
498 };
499
500 auto hasOtherEnd =
501 [&]( const SELECTION& )
502 {
503 std::vector<PNS::NET_HANDLE> currentNets = m_router->GetCurrentNets();
504
505 if( currentNets.empty() || currentNets[0] == nullptr )
506 return false;
507
508 // Need to have something unconnected to finish to
509 NETINFO_ITEM* netInfo = static_cast<NETINFO_ITEM*>( currentNets[0] );
510 int currentNet = netInfo->GetNetCode();
511 BOARD* board = getEditFrame<PCB_EDIT_FRAME>()->GetBoard();
512 RN_NET* ratsnest = board->GetConnectivity()->GetRatsnestForNet( currentNet );
513
514 return ratsnest && !ratsnest->GetEdges().empty();
515 };
516
518 menu.AddSeparator( 1 );
519
520 menu.AddItem( PCB_ACTIONS::clearHighlight, haveHighlight, 2 );
521 menu.AddSeparator( haveHighlight, 2 );
522
523 menu.AddItem( PCB_ACTIONS::routeSingleTrack, notRoutingCond );
524 menu.AddItem( PCB_ACTIONS::routeDiffPair, notRoutingCond );
527 menu.AddItem( PCB_ACTIONS::routerContinueFromEnd, hasOtherEnd );
528 menu.AddItem( PCB_ACTIONS::routerAttemptFinish, hasOtherEnd );
529 menu.AddItem( PCB_ACTIONS::breakTrack, notRoutingCond );
530
531 menu.AddItem( PCB_ACTIONS::drag45Degree, notRoutingCond );
532 menu.AddItem( PCB_ACTIONS::dragFreeAngle, notRoutingCond );
533
542
543 menu.AddSeparator();
544
545 auto diffPairCond =
546 [this]( const SELECTION& )
547 {
549 };
550
552 menu.AddMenu( m_diffPairMenu.get(), diffPairCond );
553
555
556 menu.AddSeparator();
557
559
560 return true;
561}
562
563
565{
567
568 if( aReason == RUN )
569 TOOL_BASE::Reset( aReason );
570}
571
572// Saves the complete event log and the dump of the PCB, allowing us to
573// recreate hard-to-find P&S quirks and bugs.
574
576{
577 static wxString mruPath = PATHS::GetDefaultUserProjectsPath();
578 static size_t lastLoggerSize = 0;
579
580 auto logger = m_router->Logger();
581
582 if( !logger || logger->GetEvents().size() == 0
583 || logger->GetEvents().size() == lastLoggerSize )
584 {
585 return;
586 }
587
588 wxFileDialog dlg( frame(), _( "Save router log" ), mruPath, "pns.log",
589 "PNS log files" + AddFileExtListToFilter( { "log" } ),
590 wxFD_OVERWRITE_PROMPT | wxFD_SAVE );
591
592 if( dlg.ShowModal() != wxID_OK )
593 {
594 lastLoggerSize = logger->GetEvents().size(); // prevent re-entry
595 return;
596 }
597
598 wxFileName fname_log( dlg.GetPath() );
599 mruPath = fname_log.GetPath();
600
601 wxFileName fname_dump( fname_log );
602 fname_dump.SetExt( "dump" );
603
604 wxFileName fname_settings( fname_log );
605 fname_settings.SetExt( "settings" );
606
607
608 FILE* settings_f = wxFopen( fname_settings.GetAbsolutePath(), "wb" );
609 std::string settingsStr = m_router->Settings().FormatAsString();
610 fprintf( settings_f, "%s\n", settingsStr.c_str() );
611 fclose( settings_f );
612
613 // Export as *.kicad_pcb format, using a strategy which is specifically chosen
614 // as an example on how it could also be used to send it to the system clipboard.
615
616 PCB_IO_KICAD_SEXPR pcb_io;
617
618 pcb_io.SaveBoard( fname_dump.GetAbsolutePath(), m_iface->GetBoard(), nullptr );
619
620 PROJECT* prj = m_iface->GetBoard()->GetProject();
621 prj->GetProjectFile().SaveAs( fname_dump.GetPath(), fname_dump.GetName() );
622 prj->GetLocalSettings().SaveAs( fname_dump.GetPath(), fname_dump.GetName() );
623
624 // Build log file:
625 std::vector<PNS::ITEM*> added, removed, heads;
626 m_router->GetUpdatedItems( removed, added, heads );
627
628 std::set<KIID> removedKIIDs;
629
630 for( auto item : removed )
631 {
632 wxASSERT_MSG( item->Parent() != nullptr, "removed an item with no parent uuid?" );
633
634 if( item->Parent() )
635 removedKIIDs.insert( item->Parent()->m_Uuid );
636 }
637
638 FILE* log_f = wxFopen( fname_log.GetAbsolutePath(), "wb" );
639 wxString logString = PNS::LOGGER::FormatLogFileAsString( m_router->Mode(),
640 added, removedKIIDs, heads,
641 logger->GetEvents() );
642
643 if( !log_f )
644 {
645 DisplayError( frame(), wxString::Format( _( "Unable to write '%s'." ),
646 fname_log.GetAbsolutePath() ) );
647 return;
648 }
649
650 fprintf( log_f, "%s\n", logString.c_str().AsChar() );
651 fclose( log_f );
652
653 logger->Clear(); // prevent re-entry
654 lastLoggerSize = 0;
655}
656
657
659{
660 if( aEvent.Category() == TC_VIEW || aEvent.Category() == TC_MOUSE )
661 {
662 BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
663 m_router->SetVisibleViewArea( BOX2ISafe( viewAreaD ) );
664 }
665
666 if( !ADVANCED_CFG::GetCfg().m_EnableRouterDump )
667 return;
668
669 if( !aEvent.IsKeyPressed() )
670 return;
671
672 switch( aEvent.KeyCode() )
673 {
674 case '0':
676 aEvent.SetPassEvent( false );
677 break;
678
679 default:
680 break;
681 }
682}
683
684
686{
687 int tl = getView()->GetTopLayer();
688
689 if( m_startItem )
690 {
691 const LAYER_RANGE& ls = m_startItem->Layers();
692
693 if( ls.Overlaps( tl ) )
694 return tl;
695 else
696 return ls.Start();
697 }
698
699 return tl;
700}
701
702
704{
705 int activeLayer = frame()->GetActiveLayer();
706 int currentLayer = m_router->GetCurrentLayer();
707
708 if( currentLayer != activeLayer )
709 m_router->SwitchLayer( activeLayer );
710
711 std::optional<int> newLayer = m_router->Sizes().PairedLayer( currentLayer );
712
713 if( !newLayer )
714 newLayer = m_router->Sizes().GetLayerTop();
715
716 m_router->SwitchLayer( *newLayer );
717 m_lastTargetLayer = *newLayer;
718
720}
721
722
724{
725 std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
726
729 std::shared_ptr<DRC_ENGINE>& drcEngine = bds.m_DRCEngine;
730 DRC_CONSTRAINT constraint;
731
732 PCB_TRACK dummyTrack( board() );
733 dummyTrack.SetFlags( ROUTER_TRANSIENT );
734 dummyTrack.SetLayer( targetLayer );
735 dummyTrack.SetNet( nets.empty() ? nullptr: static_cast<NETINFO_ITEM*>( nets[0] ) );
736 dummyTrack.SetStart( aPos );
737 dummyTrack.SetEnd( dummyTrack.GetStart() );
738
739 if( bds.UseNetClassTrack() || !sizes.TrackWidthIsExplicit() )
740 {
741 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, &dummyTrack, nullptr,
742 targetLayer );
743
744 if( !constraint.IsNull() )
745 {
746 int width = sizes.TrackWidth();
747
748 // Only change the size if we're explicitly using the net class, or we're out of range
749 // for our new constraints. Otherwise, just leave the track width alone so we don't
750 // change for no reason.
751 if( bds.UseNetClassTrack()
752 || ( width < bds.m_TrackMinWidth )
753 || ( width < constraint.m_Value.Min() )
754 || ( width > constraint.m_Value.Max() ) )
755 {
756 sizes.SetTrackWidth( std::max( bds.m_TrackMinWidth, constraint.m_Value.Opt() ) );
757 }
758
759 if( sizes.TrackWidth() == constraint.m_Value.Opt() )
760 sizes.SetWidthSource( constraint.GetName() );
761 else if( sizes.TrackWidth() == bds.m_TrackMinWidth )
762 sizes.SetWidthSource( _( "board minimum track width" ) );
763 else
764 sizes.SetWidthSource( _( "existing track" ) );
765 }
766 }
767
768 if( nets.size() >= 2 && ( bds.UseNetClassDiffPair() || !sizes.TrackWidthIsExplicit() ) )
769 {
770 PCB_TRACK dummyTrackB( board() );
771 dummyTrackB.SetFlags( ROUTER_TRANSIENT );
772 dummyTrackB.SetLayer( targetLayer );
773 dummyTrackB.SetNet( static_cast<NETINFO_ITEM*>( nets[1] ) );
774 dummyTrackB.SetStart( aPos );
775 dummyTrackB.SetEnd( dummyTrackB.GetStart() );
776
777 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, &dummyTrack, &dummyTrackB,
778 targetLayer );
779
780 if( !constraint.IsNull() )
781 {
782 sizes.SetDiffPairWidth( std::max( bds.m_TrackMinWidth, constraint.m_Value.Opt() ) );
783
784 if( sizes.DiffPairWidth() == constraint.m_Value.Opt() )
785 sizes.SetDiffPairWidthSource( constraint.GetName() );
786 else
787 sizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
788 }
789
790 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, &dummyTrack, &dummyTrackB,
791 targetLayer );
792
793 if( !constraint.IsNull() )
794 {
795 sizes.SetDiffPairGap( std::max( bds.m_MinClearance, constraint.m_Value.Opt() ) );
796
797 if( sizes.DiffPairGap() == constraint.m_Value.Opt() )
798 sizes.SetDiffPairGapSource( constraint.GetName() );
799 else
800 sizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
801 }
802 }
803
804 m_router->UpdateSizes( sizes );
805}
806
807
808static VIATYPE getViaTypeFromFlags( int aFlags )
809{
810 switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
811 {
813 return VIATYPE::THROUGH;
817 return VIATYPE::MICROVIA;
818 default:
819 wxASSERT_MSG( false, wxT( "Unhandled via type" ) );
820 return VIATYPE::THROUGH;
821 }
822}
823
824
826{
827 handleLayerSwitch( aEvent, false );
829
830 return 0;
831}
832
833
835{
836 if( !m_router->IsPlacingVia() )
837 {
838 return handleLayerSwitch( aEvent, true );
839 }
840 else
841 {
844 updateEndItem( aEvent );
846 }
847
849 return 0;
850}
851
852
853int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
854{
855 wxCHECK( m_router, 0 );
856
857 if( !IsToolActive() )
858 return 0;
859
860 // First see if this is one of the switch layer commands
861 BOARD* brd = board();
862 LSET enabledLayers = LSET::AllCuMask( brd->GetDesignSettings().GetCopperLayerCount() );
863 LSEQ layers = enabledLayers.Seq();
865 PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
866
867 if( aEvent.IsAction( &PCB_ACTIONS::layerNext ) )
868 {
870 m_lastTargetLayer = currentLayer;
871
872 size_t idx = 0;
873 size_t target_idx = 0;
874
875 for( size_t i = 0; i < layers.size(); i++ )
876 {
877 if( layers[i] == m_lastTargetLayer )
878 {
879 idx = i;
880 break;
881 }
882 }
883
884 target_idx = ( idx + 1 ) % layers.size();
885 // issue: #14480
886 // idx + 1 layer may be invisible, switches to next visible layer
887 for( size_t i = 0; i < layers.size() - 1; i++ )
888 {
889 if( brd->IsLayerVisible( static_cast<PCB_LAYER_ID>( layers[target_idx] ) ) )
890 {
891 targetLayer = layers[target_idx];
892 break;
893 }
894 target_idx += 1;
895
896 if( target_idx >= layers.size() )
897 {
898 target_idx = 0;
899 }
900 }
901
902 if( targetLayer == UNDEFINED_LAYER )
903 {
904 // if there is no visible layers
905 return 0;
906 }
907 }
908 else if( aEvent.IsAction( &PCB_ACTIONS::layerPrev ) )
909 {
911 m_lastTargetLayer = currentLayer;
912
913 size_t idx = 0;
914 size_t target_idx = 0;
915
916 for( size_t i = 0; i < layers.size(); i++ )
917 {
918 if( layers[i] == m_lastTargetLayer )
919 {
920 idx = i;
921 break;
922 }
923 }
924
925 target_idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers.size() - 1 );
926
927 for( size_t i = 0; i < layers.size() - 1; i++ )
928 {
929 if( brd->IsLayerVisible( static_cast<PCB_LAYER_ID>( layers[target_idx] ) ) )
930 {
931 targetLayer = layers[target_idx];
932 break;
933 }
934
935 if( target_idx > 0 )
936 target_idx -= 1;
937 else
938 target_idx = layers.size() - 1;
939 }
940
941 if( targetLayer == UNDEFINED_LAYER )
942 {
943 // if there is no visible layers
944 return 0;
945 }
946 }
947 else if( aEvent.IsAction( &PCB_ACTIONS::layerToggle ) )
948 {
949 PCB_SCREEN* screen = frame()->GetScreen();
950
951 if( currentLayer == screen->m_Route_Layer_TOP )
952 targetLayer = screen->m_Route_Layer_BOTTOM;
953 else
954 targetLayer = screen->m_Route_Layer_TOP;
955 }
957 {
958 targetLayer = aEvent.Parameter<PCB_LAYER_ID>();
959
960 if( !enabledLayers.test( targetLayer ) )
961 return 0;
962 }
963
964 if( targetLayer != UNDEFINED_LAYER )
965 {
966 m_lastTargetLayer = targetLayer;
967
968 if( targetLayer == currentLayer )
969 return 0;
970
971 if( !aForceVia && m_router && m_router->SwitchLayer( targetLayer ) )
972 {
973 updateEndItem( aEvent );
975 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
976 return 0;
977 }
978 }
979
981 const int layerCount = bds.GetCopperLayerCount();
982
985
987
988 VIATYPE viaType = VIATYPE::THROUGH;
989 bool selectLayer = false;
990
991 // Otherwise it is one of the router-specific via commands
992 if( targetLayer == UNDEFINED_LAYER )
993 {
994 const int actViaFlags = aEvent.Parameter<int>();
995 selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
996
997 viaType = getViaTypeFromFlags( actViaFlags );
998
999 // ask the user for a target layer
1000 if( selectLayer )
1001 {
1002 wxPoint endPoint = ToWxPoint( view()->ToScreen( m_endSnapPoint ) );
1003 endPoint = frame()->GetCanvas()->ClientToScreen( endPoint );
1004
1005 // Build the list of not allowed layer for the target layer
1006 LSET not_allowed_ly = LSET::AllNonCuMask();
1007
1008 if( viaType != VIATYPE::THROUGH )
1009 not_allowed_ly.set( currentLayer );
1010
1011 if( viaType == VIATYPE::MICROVIA )
1012 {
1013 // Allows only the previous or the next layer from the current layer
1014 int previous_layer = currentLayer == B_Cu ? layerCount - 2
1015 : currentLayer - 1;
1016
1017 int next_layer = currentLayer >= layerCount-2 ? B_Cu
1018 : currentLayer + 1;
1019
1020 not_allowed_ly = LSET::AllLayersMask();
1021
1022 if( previous_layer >= F_Cu && previous_layer != currentLayer )
1023 not_allowed_ly.reset( previous_layer );
1024
1025 if( next_layer != currentLayer )
1026 not_allowed_ly.reset( next_layer );
1027 }
1028
1029 targetLayer = frame()->SelectOneLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
1030 not_allowed_ly, endPoint );
1031
1032 // Reset the cursor to the end of the track
1034
1035 if( targetLayer == UNDEFINED_LAYER ) // cancelled by user
1036 return 0;
1037
1038 // One cannot place a blind/buried via on only one layer:
1039 if( viaType != VIATYPE::THROUGH )
1040 {
1041 if( currentLayer == targetLayer )
1042 return 0;
1043 }
1044 }
1045 }
1046
1047 // fixme: P&S supports more than one fixed layer pair. Update the dialog?
1048 sizes.ClearLayerPairs();
1049
1050 // Convert blind/buried via to a through hole one, if it goes through all layers
1051 if( viaType == VIATYPE::BLIND_BURIED
1052 && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
1053 || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
1054 {
1055 viaType = VIATYPE::THROUGH;
1056 }
1057
1058 if( targetLayer == UNDEFINED_LAYER )
1059 {
1060 // Implicic layer selection
1061
1062 switch( viaType )
1063 {
1064 case VIATYPE::THROUGH:
1065 // use the default layer pair
1066 currentLayer = pairTop;
1067 targetLayer = pairBottom;
1068 break;
1069
1070 case VIATYPE::MICROVIA:
1071 // Try to use the layer pair preset, if the layers are adjacent,
1072 // because a microvia is usually restricted to 2 adjacent copper layers
1073 if( pairTop > pairBottom ) std::swap( pairTop, pairBottom );
1074
1075 if( currentLayer == pairTop && pairBottom == pairTop+1 )
1076 {
1077 targetLayer = pairBottom;
1078 }
1079 else if( currentLayer == pairBottom && pairBottom == pairTop+1 )
1080 {
1081 targetLayer = pairTop;
1082 }
1083 else if( currentLayer == F_Cu || currentLayer == In1_Cu )
1084 {
1085 // front-side microvia
1086 currentLayer = F_Cu;
1087
1088 if( layerCount > 2 ) // Ensure the inner layer In1_Cu exists
1089 targetLayer = In1_Cu;
1090 else
1091 targetLayer = B_Cu;
1092 }
1093 else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
1094 {
1095 // back-side microvia
1096 currentLayer = B_Cu,
1097 targetLayer = (PCB_LAYER_ID) ( layerCount - 2 );
1098 }
1099 else
1100 {
1101 // This is not optimal: from an internal layer one can want to switch
1102 // to the previous or the next internal layer
1103 // but at this point we do not know what the user want.
1104 targetLayer = PCB_LAYER_ID( currentLayer + 1 );
1105 }
1106
1107 break;
1108
1109 case VIATYPE::BLIND_BURIED:
1110 if( currentLayer == pairTop || currentLayer == pairBottom )
1111 {
1112 // the current layer is on the defined layer pair,
1113 // swap to the other side
1114 currentLayer = pairTop;
1115 targetLayer = pairBottom;
1116 }
1117 else
1118 {
1119 // the current layer is not part of the current layer pair,
1120 // so fallback and swap to the top layer of the pair by default
1121 targetLayer = pairTop;
1122 }
1123
1124 // Do not create a broken via (i.e. a via on only one copper layer)
1125 if( currentLayer == targetLayer )
1126 {
1127 WX_INFOBAR* infobar = frame()->GetInfoBar();
1128 infobar->ShowMessageFor( _( "Blind/buried via need 2 different layers." ),
1129 2000, wxICON_ERROR,
1131 return 0;
1132 }
1133
1134 break;
1135
1136 default:
1137 wxFAIL_MSG( wxT( "unexpected via type" ) );
1138 return 0;
1139 break;
1140 }
1141 }
1142
1143 sizes.SetViaDiameter( bds.m_ViasMinSize );
1144 sizes.SetViaDrill( bds.m_MinThroughDrill );
1145
1146 if( bds.UseNetClassVia() || viaType == VIATYPE::MICROVIA )
1147 {
1148 PCB_VIA dummyVia( board() );
1149 dummyVia.SetViaType( viaType );
1150 dummyVia.SetLayerPair( currentLayer, targetLayer );
1151
1152 if( !m_router->GetCurrentNets().empty() )
1153 dummyVia.SetNet( static_cast<NETINFO_ITEM*>( m_router->GetCurrentNets()[0] ) );
1154
1155 DRC_CONSTRAINT constraint;
1156
1157 constraint = bds.m_DRCEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, &dummyVia, nullptr,
1158 currentLayer );
1159
1160 if( !constraint.IsNull() )
1161 sizes.SetViaDiameter( constraint.m_Value.Opt() );
1162
1163 constraint = bds.m_DRCEngine->EvalRules( HOLE_SIZE_CONSTRAINT, &dummyVia, nullptr,
1164 currentLayer );
1165
1166 if( !constraint.IsNull() )
1167 sizes.SetViaDrill( constraint.m_Value.Opt() );
1168 }
1169 else
1170 {
1171 sizes.SetViaDiameter( bds.GetCurrentViaSize() );
1172 sizes.SetViaDrill( bds.GetCurrentViaDrill() );
1173 }
1174
1175 sizes.SetViaType( viaType );
1176 sizes.AddLayerPair( currentLayer, targetLayer );
1177
1178 m_router->UpdateSizes( sizes );
1179
1180 if( !m_router->IsPlacingVia() )
1182
1183 m_lastTargetLayer = targetLayer;
1184
1186 {
1187 updateEndItem( aEvent );
1189 }
1190 else
1191 {
1192 updateStartItem( aEvent );
1193 }
1194
1195 return 0;
1196}
1197
1198
1200{
1201 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1202 int routingLayer = getStartLayer( m_startItem );
1203
1204 if( !IsCopperLayer( routingLayer ) )
1205 {
1206 editFrame->ShowInfoBarError( _( "Tracks on Copper layers only." ) );
1207 return false;
1208 }
1209
1211 editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
1212
1213 if( !getView()->IsLayerVisible( routingLayer ) )
1214 {
1215 editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1216 editFrame->GetCanvas()->Refresh();
1217 }
1218
1220
1221 m_iface->SetStartLayer( routingLayer );
1222
1224 m_iface->ImportSizes( sizes, m_startItem, nullptr );
1225 sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
1226 frame()->GetScreen()->m_Route_Layer_BOTTOM );
1227
1228 m_router->UpdateSizes( sizes );
1229
1230 if( m_startItem && m_startItem->Net() )
1231 {
1233 {
1235 highlightNets( true, { m_startItem->Net(), coupledNet } );
1236 }
1237 else
1238 {
1239 highlightNets( true, { m_startItem->Net() } );
1240 }
1241 }
1242
1243 controls()->SetAutoPan( true );
1244
1245 if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
1246 {
1247 // It would make more sense to leave the net highlighted as the higher-contrast mode
1248 // makes the router clearances more visible. However, since we just started routing
1249 // the conversion of the screen from low contrast to high contrast is a bit jarring and
1250 // makes the infobar coming up less noticeable.
1251 highlightNets( false );
1252
1254 [&]()
1255 {
1256 m_router->ClearViewDecorations();
1257 } );
1258
1259 controls()->SetAutoPan( false );
1260 return false;
1261 }
1262
1263 m_endItem = nullptr;
1265
1267 frame()->UndoRedoBlock( true );
1268
1269 return true;
1270}
1271
1272
1274{
1276
1277 m_startItem = nullptr;
1278 m_endItem = nullptr;
1279
1282 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1283 controls()->SetAutoPan( false );
1284 controls()->ForceCursorPosition( false );
1285 frame()->UndoRedoBlock( false );
1286 highlightNets( false );
1287
1288 return true;
1289}
1290
1291
1293{
1295
1296 if( !prepareInteractive() )
1297 return;
1298
1299 auto setCursor =
1300 [&]()
1301 {
1302 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1303 };
1304
1305 auto syncRouterAndFrameLayer =
1306 [&]()
1307 {
1308 PCB_LAYER_ID routingLayer = ToLAYER_ID( m_router->GetCurrentLayer() );
1309 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1310
1311 editFrame->SetActiveLayer( routingLayer );
1312
1313 if( !getView()->IsLayerVisible( routingLayer ) )
1314 {
1315 editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1316 editFrame->GetCanvas()->Refresh();
1317 }
1318 };
1319
1320 // Set initial cursor
1321 setCursor();
1322
1323 while( TOOL_EVENT* evt = Wait() )
1324 {
1325 setCursor();
1326
1327 // Don't crash if we missed an operation that canceled routing.
1328 if( !m_router->RoutingInProgress() )
1329 {
1330 if( evt->IsCancelInteractive() )
1331 m_cancelled = true;
1332
1333 break;
1334 }
1335
1336 handleCommonEvents( *evt );
1337
1338 if( evt->IsMotion() )
1339 {
1340 updateEndItem( *evt );
1342 }
1343 else if( evt->IsAction( &PCB_ACTIONS::routerUndoLastSegment )
1344 || evt->IsAction( &ACTIONS::doDelete )
1345 || evt->IsAction( &ACTIONS::undo ) )
1346 {
1347 if( std::optional<VECTOR2I> last = m_router->UndoLastSegment() )
1348 {
1349 getViewControls()->WarpMouseCursor( last.value(), true );
1350 evt->SetMousePosition( last.value() );
1351 }
1352
1353 updateEndItem( *evt );
1355 }
1356 else if( evt->IsAction( &PCB_ACTIONS::routerAttemptFinish ) )
1357 {
1358 bool* autoRouted = evt->Parameter<bool*>();
1359
1360 if( m_router->Finish() )
1361 {
1362 // When we're routing a group of signals automatically we want
1363 // to break up the undo stack every time we have to manually route
1364 // so the user gets nice checkpoints. Remove the APPEND_UNDO flag.
1365 if( autoRouted != nullptr )
1366 *autoRouted = true;
1367
1368 break;
1369 }
1370 else
1371 {
1372 // This acts as check if we were called by the autorouter; we don't want
1373 // to reset APPEND_UNDO if we're auto finishing after route-other-end
1374 if( autoRouted != nullptr )
1375 {
1376 *autoRouted = false;
1377 m_iface->SetCommitFlags( 0 );
1378 }
1379
1380 // Warp the mouse so the user is at the point we managed to route to
1381 controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
1382 }
1383 }
1384 else if( evt->IsAction( &PCB_ACTIONS::routerContinueFromEnd ) )
1385 {
1386 bool needsAppend = m_router->Placer()->HasPlacedAnything();
1387
1389 {
1390 syncRouterAndFrameLayer();
1392 updateEndItem( *evt );
1393
1394 // Warp the mouse to wherever we actually ended up routing to
1395 controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
1396
1397 // We want the next router commit to be one undo at the UI layer
1398 m_iface->SetCommitFlags( needsAppend ? APPEND_UNDO : 0 );
1399 }
1400 else
1401 {
1403 }
1404 }
1405 else if( evt->IsClick( BUT_LEFT )
1406 || evt->IsDrag( BUT_LEFT )
1407 || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
1408 {
1409 updateEndItem( *evt );
1410 bool needLayerSwitch = m_router->IsPlacingVia();
1411 bool forceCommit = false;
1412
1413 if( m_router->FixRoute( m_endSnapPoint, m_endItem, false, forceCommit ) )
1414 break;
1415
1416 if( needLayerSwitch )
1418
1419 // Synchronize the indicated layer
1420 syncRouterAndFrameLayer();
1421
1422 updateEndItem( *evt );
1424 m_startItem = nullptr;
1425 }
1426 else if( evt->IsAction( &ACT_SwitchCornerMode ) )
1427 {
1430 updateEndItem( *evt );
1431 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1432 }
1433 else if( evt->IsAction( &ACT_SwitchPosture ) )
1434 {
1436 updateEndItem( *evt );
1437 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1438 }
1439 else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1440 {
1441 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1442 controls()->SetAutoPan( false );
1443 {
1445 }
1446 controls()->SetAutoPan( true );
1447 setCursor();
1449 }
1450 else if( evt->IsAction( &ACTIONS::finishInteractive ) || evt->IsDblClick( BUT_LEFT ) )
1451 {
1452 // Stop current routing:
1453 bool forceFinish = true;
1454 bool forceCommit = false;
1455
1456 m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit );
1457 break;
1458 }
1459 else if( evt->IsCancelInteractive() || evt->IsActivate()
1460 || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
1461 {
1462 if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
1463 m_cancelled = true;
1464
1465 if( evt->IsActivate() && !evt->IsMoveTool() )
1466 m_cancelled = true;
1467
1468 break;
1469 }
1470 else if( evt->IsUndoRedo() )
1471 {
1472 // We're in an UndoRedoBlock. If we get here, something's broken.
1473 wxFAIL;
1474 break;
1475 }
1476 else if( evt->IsClick( BUT_RIGHT ) )
1477 {
1479 }
1480 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
1481 // but we don't at present have that, so we just knock out some of the egregious ones.
1482 else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
1483 {
1484 wxBell();
1485 }
1486 else
1487 {
1488 evt->SetPassEvent();
1489 }
1490 }
1491
1493 // Reset to normal for next route
1494 m_iface->SetCommitFlags( 0 );
1495
1497}
1498
1499
1501{
1503 DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
1504
1505 if( settingsDlg.ShowModal() == wxID_OK )
1506 {
1507 m_router->UpdateSizes( sizes );
1508 m_savedSizes = sizes;
1509
1512 bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
1514 }
1515
1516 return 0;
1517}
1518
1519
1521{
1522 DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
1523
1524 settingsDlg.ShowModal();
1525
1527
1528 return 0;
1529}
1530
1531
1533{
1534 PNS::PNS_MODE mode = aEvent.Parameter<PNS::PNS_MODE>();
1536
1537 settings.SetMode( mode );
1539
1540 return 0;
1541}
1542
1543
1545{
1547 PNS::PNS_MODE mode = settings.Mode();
1548
1549 switch( mode )
1550 {
1551 case PNS::RM_MarkObstacles: mode = PNS::RM_Shove; break;
1552 case PNS::RM_Shove: mode = PNS::RM_Walkaround; break;
1553 case PNS::RM_Walkaround: mode = PNS::RM_MarkObstacles; break;
1554 }
1555
1556 settings.SetMode( mode );
1558
1559 return 0;
1560}
1561
1562
1564{
1565 return m_router->Settings().Mode();
1566}
1567
1568
1570{
1571 return m_router->RoutingInProgress();
1572}
1573
1574
1576{
1577 if( !m_startItem )
1578 return;
1579
1582}
1583
1584
1586{
1588 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1590 PCB_LAYER_ID originalLayer = frame->GetActiveLayer();
1591 bool autoRoute = aEvent.Matches( PCB_ACTIONS::routerAutorouteSelected.MakeEvent() );
1592 bool otherEnd = aEvent.Matches( PCB_ACTIONS::routerRouteSelectedFromEnd.MakeEvent() );
1593
1595 return 0;
1596
1597 // Save selection then clear it for interactive routing
1599
1600 if( selection.Size() == 0 )
1601 return 0;
1602
1604
1605 frame->PushTool( aEvent );
1606
1607 auto setCursor =
1608 [&]()
1609 {
1610 frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1611 };
1612
1613 Activate();
1614 // Must be done after Activate() so that it gets set into the correct context
1615 controls->ShowCursor( true );
1616 controls->ForceCursorPosition( false );
1617 // Set initial cursor
1618 setCursor();
1619
1620 // Get all connected board items, adding pads for any footprints selected
1621 std::vector<BOARD_CONNECTED_ITEM*> itemList;
1622
1624 {
1625 if( item->Type() == PCB_FOOTPRINT_T )
1626 {
1627 const PADS& fpPads = ( static_cast<FOOTPRINT*>( item ) )->Pads();
1628
1629 for( PAD* pad : fpPads )
1630 itemList.push_back( pad );
1631 }
1632 else if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) != nullptr )
1633 {
1634 itemList.push_back( static_cast<BOARD_CONNECTED_ITEM*>( item ) );
1635 }
1636 }
1637
1638 std::shared_ptr<CONNECTIVITY_DATA> connectivity = frame->GetBoard()->GetConnectivity();
1639
1640 // For putting sequential tracks that successfully autoroute into one undo commit
1641 bool groupStart = true;
1642
1643 for( BOARD_CONNECTED_ITEM* item : itemList )
1644 {
1645 // This code is similar to GetRatsnestForPad() but it only adds the anchor for
1646 // the side of the connectivity on this pad. It also checks for ratsnest points
1647 // inside the pad (like a trace end) and counts them.
1648 RN_NET* net = connectivity->GetRatsnestForNet( item->GetNetCode() );
1649
1650 if( !net )
1651 continue;
1652
1653 std::vector<std::shared_ptr<const CN_ANCHOR>> anchors;
1654
1655 for( const CN_EDGE& edge : net->GetEdges() )
1656 {
1657 std::shared_ptr<const CN_ANCHOR> target = edge.GetTargetNode();
1658 std::shared_ptr<const CN_ANCHOR> source = edge.GetSourceNode();
1659
1660 if( !source || source->Dirty() || !target || target->Dirty() )
1661 continue;
1662
1663 if( source->Parent() == item )
1664 anchors.push_back( source );
1665 else if( target->Parent() == item )
1666 anchors.push_back( target );
1667 }
1668
1669 // Route them
1670 for( std::shared_ptr<const CN_ANCHOR> anchor : anchors )
1671 {
1672 // Try to return to the original layer as indicating the user's preferred
1673 // layer for autorouting tracks. The layer can be changed by the user to
1674 // finish tracks that can't complete automatically, but should be changed
1675 // back after.
1676 if( frame->GetActiveLayer() != originalLayer )
1677 frame->SetActiveLayer( originalLayer );
1678
1679 VECTOR2I ignore;
1681 m_startSnapPoint = anchor->Pos();
1682 m_router->SetMode( mode );
1683
1684 // Prime the interactive routing to attempt finish if we are autorouting
1685 bool autoRouted = false;
1686
1687 if( autoRoute )
1689 else if( otherEnd )
1691
1692 // We want autorouted tracks to all be in one undo group except for
1693 // any tracks that need to be manually finished.
1694 // The undo appending for manually finished tracks is handled in peformRouting()
1695 if( groupStart )
1696 groupStart = false;
1697 else
1699
1700 // Start interactive routing. Will automatically finish if possible.
1702
1703 // Route didn't complete automatically, need to a new undo commit
1704 // for the next line so those can group as far as they autoroute
1705 if( !autoRouted )
1706 groupStart = true;
1707 }
1708 }
1709
1710 m_iface->SetCommitFlags( 0 );
1711 frame->PopTool( aEvent );
1712 return 0;
1713}
1714
1715
1717{
1718 if( m_inRouterTool )
1719 return 0;
1720
1722
1724 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1726
1728 {
1729 if( m_router->Mode() == mode )
1730 return 0;
1731 else
1733 }
1734
1735 // Deselect all items
1737
1738 frame->PushTool( aEvent );
1739
1740 auto setCursor =
1741 [&]()
1742 {
1743 frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1744 };
1745
1746 Activate();
1747 // Must be done after Activate() so that it gets set into the correct context
1748 controls->ShowCursor( true );
1749 controls->ForceCursorPosition( false );
1750 // Set initial cursor
1751 setCursor();
1752
1753 m_router->SetMode( mode );
1754 m_cancelled = false;
1755
1756 if( aEvent.HasPosition() )
1757 m_toolMgr->PrimeTool( aEvent.Position() );
1758
1759 // Main loop: keep receiving events
1760 while( TOOL_EVENT* evt = Wait() )
1761 {
1762 if( !evt->IsDrag() )
1763 setCursor();
1764
1765 if( evt->IsCancelInteractive() )
1766 {
1767 frame->PopTool( aEvent );
1768 break;
1769 }
1770 else if( evt->IsActivate() )
1771 {
1772 if( evt->IsMoveTool() || evt->IsEditorTool() )
1773 {
1774 // leave ourselves on the stack so we come back after the move
1775 break;
1776 }
1777 else
1778 {
1779 frame->PopTool( aEvent );
1780 break;
1781 }
1782 }
1783 else if( evt->Action() == TA_UNDO_REDO_PRE )
1784 {
1786 }
1787 else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
1788 {
1790 }
1791 else if( evt->IsMotion() )
1792 {
1793 updateStartItem( *evt );
1794 }
1795 else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
1796 {
1797 updateStartItem( *evt, true );
1799 }
1800 else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
1801 {
1802 updateStartItem( *evt, true );
1804 }
1805 else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
1806 {
1807 updateStartItem( *evt, true );
1808 breakTrack( );
1809 evt->SetPassEvent( false );
1810 }
1811 else if( evt->IsClick( BUT_LEFT )
1812 || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
1813 || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
1814 {
1815 updateStartItem( *evt );
1816
1817 if( evt->HasPosition() )
1818 {
1819 if( evt->Modifier( MD_SHIFT ) )
1821 else
1823 }
1824 }
1825 else if( evt->IsAction( &ACT_PlaceThroughVia ) )
1826 {
1828 }
1829 else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1830 {
1832 updateStartItem( *evt );
1834 }
1835 else if( evt->IsKeyPressed() )
1836 {
1837 // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
1838 // event so we need to process the wxEVT_CHAR event that will follow as long as we
1839 // pass the event.
1840 evt->SetPassEvent();
1841 }
1842 else if( evt->IsClick( BUT_RIGHT ) )
1843 {
1845 }
1846 else
1847 {
1848 evt->SetPassEvent();
1849 }
1850
1851 if( m_cancelled )
1852 {
1853 frame->PopTool( aEvent );
1854 break;
1855 }
1856 }
1857
1858 // Store routing settings till the next invocation
1861
1862 return 0;
1863}
1864
1865
1867{
1869
1870 view()->ClearPreview();
1871 view()->InitPreview();
1872
1874
1875 if( m_startItem && m_startItem->IsLocked() )
1876 {
1877 KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1878 wxOK | wxCANCEL | wxICON_WARNING );
1879 dlg.SetOKLabel( _( "Drag Anyway" ) );
1880 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1881
1882 if( dlg.ShowModal() == wxID_CANCEL )
1883 return;
1884 }
1885
1886 // We don't support dragging arcs inside the PNS right now
1888 {
1891
1892 m_startItem = nullptr;
1893
1894 m_gridHelper->SetAuxAxes( false );
1895 ctls->ForceCursorPosition( false );
1896 highlightNets( false );
1897
1898 m_cancelled = true;
1899
1901
1902 return;
1903 }
1904
1905 bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1906
1907 if( !dragStarted )
1908 return;
1909
1910 if( m_startItem && m_startItem->Net() )
1911 highlightNets( true, { m_startItem->Net() } );
1912
1913 ctls->SetAutoPan( true );
1915 frame()->UndoRedoBlock( true );
1916
1917 while( TOOL_EVENT* evt = Wait() )
1918 {
1919 ctls->ForceCursorPosition( false );
1920
1921 if( evt->IsMotion() )
1922 {
1923 updateEndItem( *evt );
1925
1926 if( PNS::DRAG_ALGO* dragger = m_router->GetDragger() )
1927 {
1928 bool dragStatus;
1929
1930 if( dragger->GetForceMarkObstaclesMode( &dragStatus ) )
1931 {
1932 view()->ClearPreview();
1933
1934 if( !dragStatus )
1935 {
1936 wxString hint;
1937 hint.Printf( _( "(%s to commit anyway.)" ),
1939
1941 statusItem->SetMessage( _( "Track violates DRC." ) );
1942 statusItem->SetHint( hint );
1943 statusItem->SetPosition( frame()->GetToolManager()->GetMousePosition() );
1944 view()->AddToPreview( statusItem );
1945 }
1946 }
1947 }
1948 }
1949 else if( evt->IsClick( BUT_LEFT ) )
1950 {
1951 bool forceFinish = false;
1952 bool forceCommit = evt->Modifier( MD_CTRL );
1953
1954 if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit ) )
1955 break;
1956 }
1957 else if( evt->IsClick( BUT_RIGHT ) )
1958 {
1960 }
1961 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1962 {
1963 if( evt->IsCancelInteractive() && !m_startItem )
1964 m_cancelled = true;
1965
1966 if( evt->IsActivate() && !evt->IsMoveTool() )
1967 m_cancelled = true;
1968
1969 break;
1970 }
1971 else if( evt->IsUndoRedo() )
1972 {
1973 // We're in an UndoRedoBlock. If we get here, something's broken.
1974 wxFAIL;
1975 break;
1976 }
1977 else if( evt->Category() == TC_COMMAND )
1978 {
1979 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
1980 // but we don't at present have that, so we just knock out some of the egregious ones.
1981 if( evt->IsAction( &ACTIONS::cut )
1982 || evt->IsAction( &ACTIONS::copy )
1983 || evt->IsAction( &ACTIONS::paste )
1984 || evt->IsAction( &ACTIONS::pasteSpecial )
1986 {
1987 wxBell();
1988 }
1989 // treat an undo as an escape
1990 else if( evt->IsAction( &ACTIONS::undo ) )
1991 {
1992 if( m_startItem )
1993 break;
1994 else
1995 wxBell();
1996 }
1997 else
1998 {
1999 evt->SetPassEvent();
2000 }
2001 }
2002 else
2003 {
2004 evt->SetPassEvent();
2005 }
2006
2007 handleCommonEvents( *evt );
2008 }
2009
2010 view()->ClearPreview();
2011 view()->ShowPreview( false );
2012
2015
2016 m_startItem = nullptr;
2017
2018 m_gridHelper->SetAuxAxes( false );
2019 frame()->UndoRedoBlock( false );
2020 ctls->SetAutoPan( false );
2021 ctls->ForceCursorPosition( false );
2022 highlightNets( false );
2023}
2024
2025
2027 PCB_SELECTION_TOOL* aSelTool )
2028{
2029 /*
2030 * If the collection contains a trivial line corner (two connected segments)
2031 * or a non-fanout-via (a via with no more than two connected segments), then
2032 * trim the collection down to a single item (which one won't matter since
2033 * they're all connected).
2034 */
2035
2036 // First make sure we've got something that *might* match.
2037 int vias = aCollector.CountType( PCB_VIA_T );
2038 int traces = aCollector.CountType( PCB_TRACE_T );
2039 int arcs = aCollector.CountType( PCB_ARC_T );
2040
2041 // We eliminate arcs because they are not supported in the inline drag code.
2042 if( arcs > 0 )
2043 return;
2044
2045 // We need to have at least 1 via or track
2046 if( vias + traces == 0 )
2047 return;
2048
2049 // We cannot drag more than one via at a time
2050 if( vias > 1 )
2051 return;
2052
2053 // We cannot drag more than two track segments at a time
2054 if( traces > 2 )
2055 return;
2056
2057 // Fetch first PCB_TRACK (via or trace) as our reference
2058 PCB_TRACK* reference = nullptr;
2059
2060 for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
2061 reference = dynamic_cast<PCB_TRACK*>( aCollector[i] );
2062
2063 // This should never happen, but just in case...
2064 if( !reference )
2065 return;
2066
2067 int refNet = reference->GetNetCode();
2068
2069 VECTOR2I refPoint( aPt.x, aPt.y );
2070 EDA_ITEM_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
2071
2072 if( flags & STARTPOINT )
2073 refPoint = reference->GetStart();
2074 else if( flags & ENDPOINT )
2075 refPoint = reference->GetEnd();
2076
2077 // Check all items to ensure that any TRACKs are co-terminus with the reference and on
2078 // the same net.
2079 for( int i = 0; i < aCollector.GetCount(); i++ )
2080 {
2081 PCB_TRACK* neighbor = dynamic_cast<PCB_TRACK*>( aCollector[i] );
2082
2083 if( neighbor && neighbor != reference )
2084 {
2085 if( neighbor->GetNetCode() != refNet )
2086 return;
2087
2088 if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
2089 return;
2090 }
2091 }
2092
2093 // Selection meets criteria; trim it to the reference item.
2094 aCollector.Empty();
2095 aCollector.Append( reference );
2096}
2097
2098
2099bool ROUTER_TOOL::CanInlineDrag( int aDragMode )
2100{
2103 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2104
2105 const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
2106
2107 // Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using
2108 // DragArcTrack(), so PCB_ARC_T should never occur here.
2110 {
2111 // Footprints cannot be dragged freely.
2112 if( item->IsType( { PCB_FOOTPRINT_T } ) )
2113 return !( aDragMode & PNS::DM_FREE_ANGLE );
2114 else
2115 return true;
2116 }
2117
2118 return false;
2119}
2120
2121
2123{
2124 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2125
2126 if( selection.Empty() )
2127 {
2130 }
2131
2132 if( selection.Empty() )
2133 return 0;
2134
2135 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
2136
2137 if( item->Type() != PCB_TRACE_T
2138 && item->Type() != PCB_VIA_T
2139 && item->Type() != PCB_FOOTPRINT_T )
2140 {
2141 return 0;
2142 }
2143
2144 std::set<FOOTPRINT*> footprints;
2145
2146 if( item->Type() == PCB_FOOTPRINT_T )
2147 footprints.insert( static_cast<FOOTPRINT*>( item ) );
2148
2149 // We can drag multiple footprints, but not a grab-bag of items
2150 if( selection.Size() > 1 )
2151 {
2152 if( item->Type() != PCB_FOOTPRINT_T )
2153 return 0;
2154
2155 for( int idx = 1; idx < selection.Size(); ++idx )
2156 {
2157 if( static_cast<BOARD_ITEM*>( selection.GetItem( idx ) )->Type() != PCB_FOOTPRINT_T )
2158 return 0;
2159
2160 footprints.insert( static_cast<FOOTPRINT*>( selection.GetItem( idx ) ) );
2161 }
2162 }
2163
2164 // If we overrode locks, we want to clear the flag from the source item before SyncWorld is
2165 // called so that virtual vias are not generated for the (now unlocked) track segment. Note in
2166 // this case the lock can't be reliably re-applied, because there is no guarantee that the end
2167 // state of the drag results in the same number of segments so it's not clear which segment to
2168 // apply the lock state to.
2169 bool wasLocked = false;
2170
2171 if( item->IsLocked() )
2172 {
2173 wasLocked = true;
2174 item->SetLocked( false );
2175 }
2176
2178
2179 frame()->PushTool( aEvent );
2180 Activate();
2181
2182 m_startItem = nullptr;
2183
2184 PNS::ITEM* startItem = nullptr;
2185 PNS::ITEM_SET itemsToDrag;
2186
2187 bool showCourtyardConflicts = frame()->GetPcbNewSettings()->m_ShowCourtyardCollisions;
2188
2189 std::shared_ptr<DRC_ENGINE> drcEngine = m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine();
2190 DRC_INTERACTIVE_COURTYARD_CLEARANCE courtyardClearanceDRC( drcEngine );
2191
2192 std::shared_ptr<CONNECTIVITY_DATA> connectivityData = board()->GetConnectivity();
2193 std::vector<BOARD_ITEM*> dynamicItems;
2194 std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr;
2195 VECTOR2I lastOffset;
2196
2197 if( !footprints.empty() )
2198 {
2199 if( showCourtyardConflicts )
2200 courtyardClearanceDRC.Init( board() );
2201
2202 for( FOOTPRINT* footprint : footprints )
2203 {
2204 for( PAD* pad : footprint->Pads() )
2205 {
2207
2208 if( solid )
2209 itemsToDrag.Add( solid );
2210
2211 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2212 {
2213 if( connectivityData->GetRatsnestForPad( pad ).size() > 0 )
2214 dynamicItems.push_back( pad );
2215 }
2216 }
2217
2218 for( ZONE* zone : footprint->Zones() )
2219 {
2220 std::vector<PNS::ITEM*> solids = m_router->GetWorld()->FindItemsByZone( zone );
2221
2222 for( PNS::ITEM* solid : solids )
2223 itemsToDrag.Add( solid );
2224 }
2225
2226 if( showCourtyardConflicts )
2227 courtyardClearanceDRC.m_FpInMove.push_back( footprint );
2228 }
2229
2230 dynamicData = std::make_unique<CONNECTIVITY_DATA>( board()->GetConnectivity(),
2231 dynamicItems, true );
2232 connectivityData->BlockRatsnestItems( dynamicItems );
2233 }
2234 else
2235 {
2236 startItem = m_router->GetWorld()->FindItemByParent( item );
2237
2238 if( startItem )
2239 itemsToDrag.Add( startItem );
2240 }
2241
2242 GAL* gal = m_toolMgr->GetView()->GetGAL();
2243 VECTOR2I p0 = GetClampedCoords( controls()->GetCursorPosition( false ), COORDS_PADDING );
2244 VECTOR2I p = p0;
2245
2247 m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
2248
2249 if( startItem )
2250 {
2251 p = snapToItem( startItem, p0 );
2252 m_startItem = startItem;
2253
2254 if( m_startItem->Net() )
2255 highlightNets( true, { m_startItem->Net() } );
2256 }
2257 else if( !footprints.empty() )
2258 {
2259 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
2260
2261 // The mouse is going to be moved on grid before dragging begins.
2262 VECTOR2I tweakedMousePos;
2263 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
2264
2265 // Check if user wants to warp the mouse to origin of moved object
2266
2267 if( editFrame->GetMoveWarpsCursor() )
2268 tweakedMousePos = footprint->GetPosition(); // Use footprint anchor to warp mouse
2269 else
2270 tweakedMousePos = GetClampedCoords( controls()->GetCursorPosition(),
2271 COORDS_PADDING ); // Just use current mouse pos
2272
2273 // We tweak the mouse position using the value from above, and then use that as the
2274 // start position to prevent the footprint from jumping when we start dragging.
2275 // First we move the visual cross hair cursor...
2276 controls()->ForceCursorPosition( true, tweakedMousePos );
2277 controls()->SetCursorPosition( tweakedMousePos ); // ...then the mouse pointer
2278
2279 // Now that the mouse is in the right position, get a copy of the position to use later
2280 p = controls()->GetCursorPosition();
2281 }
2282
2283 int dragMode = aEvent.Parameter<int> ();
2284
2285 bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
2286
2287 if( !dragStarted )
2288 {
2289 if( wasLocked )
2290 item->SetLocked( true );
2291
2292 if( !footprints.empty() )
2293 connectivityData->ClearLocalRatsnest();
2294
2295 // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
2296 courtyardClearanceDRC.ClearConflicts( getView() );
2297
2298 controls()->ForceCursorPosition( false );
2299 frame()->PopTool( aEvent );
2300 highlightNets( false );
2301 return 0;
2302 }
2303
2304 m_gridHelper->SetAuxAxes( true, p );
2305 controls()->ShowCursor( true );
2306 controls()->SetAutoPan( true );
2307 frame()->UndoRedoBlock( true );
2308
2309 view()->ClearPreview();
2310 view()->InitPreview();
2311
2312 auto setCursor =
2313 [&]()
2314 {
2315 frame()->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2316 };
2317
2318 // Set initial cursor
2319 setCursor();
2320
2321 // Set the initial visible area
2322 BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
2323 m_router->SetVisibleViewArea( BOX2ISafe( viewAreaD ) );
2324
2325 // Send an initial movement to prime the collision detection
2326 m_router->Move( p, nullptr );
2327
2328 bool hasMouseMoved = false;
2329
2330 while( TOOL_EVENT* evt = Wait() )
2331 {
2332 setCursor();
2333
2334 if( evt->IsCancelInteractive() )
2335 {
2336 if( wasLocked )
2337 item->SetLocked( true );
2338
2339 break;
2340 }
2341 else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
2342 {
2343 hasMouseMoved = true;
2344 updateEndItem( *evt );
2346
2347 view()->ClearPreview();
2348
2349 if( !footprints.empty() )
2350 {
2351 VECTOR2I offset = m_endSnapPoint - p;
2352 BOARD_ITEM* previewItem;
2353
2354 for( FOOTPRINT* footprint : footprints )
2355 {
2356 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2357 {
2358 previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() );
2359 previewItem->Move( offset );
2360
2361 view()->AddToPreview( previewItem );
2362 view()->Hide( drawing, true );
2363 }
2364
2365 for( PAD* pad : footprint->Pads() )
2366 {
2367 if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none()
2368 && pad->GetDrillSize().x == 0 )
2369 {
2370 previewItem = static_cast<BOARD_ITEM*>( pad->Clone() );
2371 previewItem->Move( offset );
2372
2373 view()->AddToPreview( previewItem );
2374 }
2375 else
2376 {
2377 // Pads with copper or holes are handled by the router
2378 }
2379
2380 view()->Hide( pad, true );
2381 }
2382
2383 previewItem = static_cast<BOARD_ITEM*>( footprint->Reference().Clone() );
2384 previewItem->Move( offset );
2385 view()->AddToPreview( previewItem );
2386 view()->Hide( &footprint->Reference() );
2387
2388 previewItem = static_cast<BOARD_ITEM*>( footprint->Value().Clone() );
2389 previewItem->Move( offset );
2390 view()->AddToPreview( previewItem );
2391 view()->Hide( &footprint->Value() );
2392
2393 if( showCourtyardConflicts )
2394 footprint->Move( offset );
2395 }
2396
2397 if( showCourtyardConflicts )
2398 {
2399 courtyardClearanceDRC.Run();
2400 courtyardClearanceDRC.UpdateConflicts( getView(), false );
2401
2402 for( FOOTPRINT* footprint : footprints )
2403 footprint->Move( -offset );
2404 }
2405
2406 // Update ratsnest
2407 dynamicData->Move( offset - lastOffset );
2408 lastOffset = offset;
2409 connectivityData->ComputeLocalRatsnest( dynamicItems, dynamicData.get(), offset );
2410 }
2411
2412 if( PNS::DRAG_ALGO* dragger = m_router->GetDragger() )
2413 {
2414 bool dragStatus;
2415
2416 if( dragger->GetForceMarkObstaclesMode( &dragStatus ) )
2417 {
2418 if( !dragStatus )
2419 {
2420 wxString hint;
2421 hint.Printf( _( "(%s to commit anyway.)" ),
2423
2425 statusItem->SetMessage( _( "Track violates DRC." ) );
2426 statusItem->SetHint( hint );
2427 statusItem->SetPosition( frame()->GetToolManager()->GetMousePosition() );
2428 view()->AddToPreview( statusItem );
2429 }
2430 }
2431 }
2432 }
2433 else if( hasMouseMoved && ( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
2434 {
2435 bool forceFinish = false;
2436 bool forceCommit = evt->Modifier( MD_CTRL );
2437
2438 updateEndItem( *evt );
2439 m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish, forceCommit );
2440 break;
2441 }
2442 else if( evt->IsUndoRedo() )
2443 {
2444 // We're in an UndoRedoBlock. If we get here, something's broken.
2445 wxFAIL;
2446 break;
2447 }
2448 else if( evt->Category() == TC_COMMAND )
2449 {
2450 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
2451 // but we don't at present have that, so we just knock out some of the egregious ones.
2452 if( evt->IsAction( &ACTIONS::cut )
2453 || evt->IsAction( &ACTIONS::copy )
2454 || evt->IsAction( &ACTIONS::paste )
2455 || evt->IsAction( &ACTIONS::pasteSpecial )
2457 {
2458 wxBell();
2459 }
2460 // treat an undo as an escape
2461 else if( evt->IsAction( &ACTIONS::undo ) )
2462 {
2463 if( wasLocked )
2464 item->SetLocked( true );
2465
2466 break;
2467 }
2468 else
2469 {
2470 evt->SetPassEvent();
2471 }
2472 }
2473 else
2474 {
2475 evt->SetPassEvent();
2476 }
2477
2478 handleCommonEvents( *evt );
2479 }
2480
2481 if( !footprints.empty() )
2482 {
2483 for( FOOTPRINT* footprint : footprints )
2484 {
2485 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2486 view()->Hide( drawing, false );
2487
2488 view()->Hide( &footprint->Reference(), false );
2489 view()->Hide( &footprint->Value(), false );
2490
2491 for( PAD* pad : footprint->Pads() )
2492 view()->Hide( pad, false );
2493 }
2494
2495 connectivityData->ClearLocalRatsnest();
2496 }
2497
2498 view()->ClearPreview();
2499 view()->ShowPreview( false );
2500
2501 // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
2502 courtyardClearanceDRC.ClearConflicts( getView() );
2503
2506
2507 m_gridHelper->SetAuxAxes( false );
2508 controls()->SetAutoPan( false );
2509 controls()->ForceCursorPosition( false );
2510 frame()->UndoRedoBlock( false );
2511 frame()->PopTool( aEvent );
2512 highlightNets( false );
2513
2514 return 0;
2515}
2516
2517
2519{
2520 const SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2521
2522 if( selection.Size() != 1 )
2523 return 0;
2524
2525 const BOARD_CONNECTED_ITEM* item =
2526 static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
2527
2528 if( item->Type() != PCB_TRACE_T && item->Type() != PCB_ARC_T )
2529 return 0;
2530
2532
2533 Activate();
2534
2536
2537 TOOL_MANAGER* toolManager = frame()->GetToolManager();
2538 GAL* gal = toolManager->GetView()->GetGAL();
2539
2541 m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
2542
2543 controls()->ForceCursorPosition( false );
2544
2545 if( toolManager->IsContextMenuActive() )
2546 {
2547 // If we're here from a context menu then we need to get the position of the
2548 // cursor when the context menu was invoked. This is used to figure out the
2549 // break point on the track.
2551 }
2552 else
2553 {
2554 // If we're here from a hotkey, then get the current mouse position so we know
2555 // where to break the track.
2557 m_startItem, GetClampedCoords( controls()->GetCursorPosition(), COORDS_PADDING ) );
2558 }
2559
2560 if( m_startItem && m_startItem->IsLocked() )
2561 {
2562 KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
2563 wxOK | wxCANCEL | wxICON_WARNING );
2564 dlg.SetOKLabel( _( "Break Track" ) );
2565 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
2566
2567 if( dlg.ShowModal() == wxID_CANCEL )
2568 return 0;
2569 }
2570
2571 frame()->UndoRedoBlock( true );
2572 breakTrack();
2573
2576
2577 frame()->UndoRedoBlock( false );
2578
2579 return 0;
2580}
2581
2582
2584{
2586 DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
2587
2588 if( sizeDlg.ShowModal() == wxID_OK )
2589 {
2590 bds.m_TempOverrideTrackWidth = true;
2591 bds.UseCustomTrackViaSize( true );
2592
2595 }
2596
2597 return 0;
2598}
2599
2600
2602{
2604
2605 if( !m_router->GetCurrentNets().empty() )
2607
2608 m_router->UpdateSizes( sizes );
2609
2610 // Changing the track width can affect the placement, so call the
2611 // move routine without changing the destination
2612 // Update end item first to avoid moving to an invalid/missing item
2613 updateEndItem( aEvent );
2615
2617
2618 return 0;
2619}
2620
2621
2623{
2624 std::vector<MSG_PANEL_ITEM> items;
2625
2627 {
2630 PNS::CONSTRAINT constraint;
2631 std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
2632 wxString description;
2633 wxString secondary;
2634 wxString mode;
2635
2637 {
2638 wxASSERT( nets.size() >= 2 );
2639
2640 NETINFO_ITEM* netA = static_cast<NETINFO_ITEM*>( nets[0] );
2641 NETINFO_ITEM* netB = static_cast<NETINFO_ITEM*>( nets[1] );
2642 wxASSERT( netA );
2643 wxASSERT( netB );
2644
2645 description = wxString::Format( _( "Routing Diff Pair: %s" ),
2646 netA->GetNetname() + wxT( ", " ) + netB->GetNetname() );
2647
2648 wxString netclass;
2649 NETCLASS* netclassA = netA->GetNetClass();
2650 NETCLASS* netclassB = netB->GetNetClass();
2651
2652 if( netclassA == netclassB )
2653 netclass = netclassA->GetName();
2654 else
2655 netclass = netclassA->GetName() + wxT( ", " ) + netclassB->GetName();
2656
2657 secondary = wxString::Format( _( "Resolved Netclass: %s" ),
2658 UnescapeString( netclass ) );
2659 }
2660 else if( !nets.empty() && nets[0] )
2661 {
2662 NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( nets[0] );
2663
2664 description = wxString::Format( _( "Routing Track: %s" ),
2665 net->GetNetname() );
2666
2667 secondary = wxString::Format( _( "Resolved Netclass: %s" ),
2668 UnescapeString( net->GetNetClass()->GetName() ) );
2669 }
2670 else
2671 {
2672 description = _( "Routing Track" );
2673 secondary = _( "(no net)" );
2674 }
2675
2676 items.emplace_back( description, secondary );
2677
2678 wxString cornerMode;
2679
2681 {
2682 cornerMode = _( "Free-angle" );
2683 }
2684 else
2685 {
2686 switch( m_router->Settings().GetCornerMode() )
2687 {
2688 case DIRECTION_45::CORNER_MODE::MITERED_45: cornerMode = _( "45-degree" ); break;
2689 case DIRECTION_45::CORNER_MODE::ROUNDED_45: cornerMode = _( "45-degree rounded" ); break;
2690 case DIRECTION_45::CORNER_MODE::MITERED_90: cornerMode = _( "90-degree" ); break;
2691 case DIRECTION_45::CORNER_MODE::ROUNDED_90: cornerMode = _( "90-degree rounded" ); break;
2692 default: break;
2693 }
2694 }
2695
2696 items.emplace_back( _( "Corner Style" ), cornerMode );
2697
2698 switch( m_router->Settings().Mode() )
2699 {
2700 case PNS::PNS_MODE::RM_MarkObstacles: mode = _( "Highlight collisions" ); break;
2701 case PNS::PNS_MODE::RM_Walkaround: mode = _( "Walk around" ); break;
2702 case PNS::PNS_MODE::RM_Shove: mode = _( "Shove" ); break;
2703 default: break;
2704 }
2705
2706 items.emplace_back( _( "Mode" ), mode );
2707
2708#define FORMAT_VALUE( x ) frame()->MessageTextFromValue( x )
2709
2711 {
2712 items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2713 FORMAT_VALUE( sizes.DiffPairWidth() ) ),
2714 wxString::Format( _( "(from %s)" ),
2715 sizes.GetDiffPairWidthSource() ) );
2716
2717 items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2718 FORMAT_VALUE( sizes.Clearance() ) ),
2719 wxString::Format( _( "(from %s)" ),
2720 sizes.GetClearanceSource() ) );
2721
2722 items.emplace_back( wxString::Format( _( "Diff Pair Gap: %s" ),
2723 FORMAT_VALUE( sizes.DiffPairGap() ) ),
2724 wxString::Format( _( "(from %s)" ),
2725 sizes.GetDiffPairGapSource() ) );
2726
2727 const PNS::ITEM_SET& traces = m_router->Placer()->Traces();
2728 wxASSERT( traces.Count() == 2 );
2729
2730 if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_MAX_UNCOUPLED, traces[0],
2731 traces[1], m_router->GetCurrentLayer(), &constraint ) )
2732 {
2733 items.emplace_back( wxString::Format( _( "DP Max Uncoupled-length: %s" ),
2734 FORMAT_VALUE( constraint.m_Value.Max() ) ),
2735 wxString::Format( _( "(from %s)" ),
2736 constraint.m_RuleName ) );
2737 }
2738 }
2739 else
2740 {
2741 items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2742 FORMAT_VALUE( sizes.TrackWidth() ) ),
2743 wxString::Format( _( "(from %s)" ),
2744 sizes.GetWidthSource() ) );
2745
2746 items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2747 FORMAT_VALUE( sizes.Clearance() ) ),
2748 wxString::Format( _( "(from %s)" ),
2749 sizes.GetClearanceSource() ) );
2750 }
2751
2752#undef FORMAT_VALUE
2753
2754 frame()->SetMsgPanel( items );
2755 }
2756 else
2757 {
2758 frame()->SetMsgPanel( board() );
2759 return;
2760 }
2761}
2762
2763
2765{
2767
2781
2788
2824
2827}
@ select_w_layer
@ change_entry_orient
@ switch_corner_rounding_shape
@ via_microvia
BOX2I BOX2ISafe(const BOX2D &aInput)
Definition: box2.h:883
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:282
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:683
PROJECT * GetProject() const
Definition: board.h:476
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:794
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:460
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:88
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:126
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:175
ZONES & Zones()
Definition: footprint.h:197
PCB_FIELD & Value()
read/write accessors:
Definition: footprint.h:624
PADS & Pads()
Definition: footprint.h:191
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:2209
PCB_FIELD & Reference()
Definition: footprint.h:625
VECTOR2I GetPosition() const override
Definition: footprint.h:209
DRAWINGS & GraphicalItems()
Definition: footprint.h:194
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: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
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:1689
virtual int GetTopLayer() const
Definition: view.cpp:821
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:197
void InitPreview()
Definition: view.cpp:1668
void ClearPreview()
Definition: view.cpp:1653
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1579
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1675
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:521
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:575
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:53
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:129
bool m_ShowCourtyardCollisions
static TOOL_ACTION_GROUP layerDirectSwitchActions()
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:376
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:193
static TOOL_ACTION layerInner12
Definition: pcb_actions.h:352
static TOOL_ACTION routerUndoLastSegment
Definition: pcb_actions.h:255
static TOOL_ACTION layerInner8
Definition: pcb_actions.h:348
static TOOL_ACTION layerInner3
Definition: pcb_actions.h:343
static TOOL_ACTION layerPrev
Definition: pcb_actions.h:373
static TOOL_ACTION routerSettingsDialog
Activation of the Push and Shove settings dialogs.
Definition: pcb_actions.h:264
static TOOL_ACTION layerInner2
Definition: pcb_actions.h:342
static TOOL_ACTION routerAttemptFinish
Definition: pcb_actions.h:258
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:249
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:391
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:381
static TOOL_ACTION layerInner25
Definition: pcb_actions.h:365
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:191
static TOOL_ACTION routerRouteSelectedFromEnd
Definition: pcb_actions.h:260
static TOOL_ACTION routerHighlightMode
Actions to enable switching modes via hotkey assignments.
Definition: pcb_actions.h:268
static TOOL_ACTION routerWalkaroundMode
Definition: pcb_actions.h:270
static TOOL_ACTION routerShoveMode
Definition: pcb_actions.h:269
static TOOL_ACTION layerInner24
Definition: pcb_actions.h:364
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:176
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION layerInner29
Definition: pcb_actions.h:369
static TOOL_ACTION routerAutorouteSelected
Definition: pcb_actions.h:261
static TOOL_ACTION layerInner11
Definition: pcb_actions.h:351
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:265
static TOOL_ACTION routerContinueFromEnd
Definition: pcb_actions.h:257
static TOOL_ACTION layerInner16
Definition: pcb_actions.h:356
static TOOL_ACTION layerInner26
Definition: pcb_actions.h:366
static TOOL_ACTION layerInner18
Definition: pcb_actions.h:358
static TOOL_ACTION layerInner14
Definition: pcb_actions.h:354
static TOOL_ACTION selectLayerPair
Definition: pcb_actions.h:188
static TOOL_ACTION layerInner6
Definition: pcb_actions.h:346
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:194
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:550
static TOOL_ACTION layerInner22
Definition: pcb_actions.h:362
static TOOL_ACTION layerInner5
Definition: pcb_actions.h:345
static TOOL_ACTION layerInner20
Definition: pcb_actions.h:360
static TOOL_ACTION layerInner7
Definition: pcb_actions.h:347
static TOOL_ACTION layerInner27
Definition: pcb_actions.h:367
static TOOL_ACTION layerInner1
Definition: pcb_actions.h:341
static TOOL_ACTION layerInner10
Definition: pcb_actions.h:350
static TOOL_ACTION layerInner15
Definition: pcb_actions.h:355
static TOOL_ACTION layerInner17
Definition: pcb_actions.h:357
static TOOL_ACTION layerBottom
Definition: pcb_actions.h:371
static TOOL_ACTION layerInner19
Definition: pcb_actions.h:359
static TOOL_ACTION layerInner9
Definition: pcb_actions.h:349
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:274
static TOOL_ACTION layerInner30
Definition: pcb_actions.h:370
static TOOL_ACTION layerTop
Definition: pcb_actions.h:340
static TOOL_ACTION cycleRouterMode
Definition: pcb_actions.h:271
static TOOL_ACTION layerInner4
Definition: pcb_actions.h:344
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:246
static TOOL_ACTION layerInner13
Definition: pcb_actions.h:353
static TOOL_ACTION layerInner21
Definition: pcb_actions.h:361
static TOOL_ACTION layerNext
Definition: pcb_actions.h:372
static TOOL_ACTION routerRouteSelected
Definition: pcb_actions.h:259
static TOOL_ACTION layerInner23
Definition: pcb_actions.h:363
static TOOL_ACTION layerInner28
Definition: pcb_actions.h:368
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:200
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:110
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:113
const VECTOR2I & GetStart() const
Definition: pcb_track.h:114
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:111
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:575
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:902
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:412
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:1684
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
Definition: pns_node.cpp:1664
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)
static const unsigned int COORDS_PADDING
Definition: pns_tool_base.h:84
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
EDA_ITEM * Front() const
Definition: selection.h:172
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
std::vector< EDA_ITEM * > GetItemsSortedBySelectionOrder() const
Definition: selection.cpp:264
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
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:217
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:62
VECTOR2D GetMenuCursorPos() const
Definition: tool_manager.h:548
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:150
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:235
bool IsContextMenuActive() const
True while processing a context menu.
Definition: tool_manager.h:519
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:391
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:161
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
VECTOR2< ret_type > GetClampedCoords(const VECTOR2< in_type > &aCoords, pad_type aPadding=1u)
Clamps a vector to values that can be negated, respecting numeric limits of coordinates data type wit...
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
#define PSEUDO_WXK_CLICK
Definition: hotkeys_basic.h:50
This file is part of the common library.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:881
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:95
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ In1_Cu
Definition: layer_ids.h:65
@ F_Cu
Definition: layer_ids.h:64
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:65
@ 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:92
@ BLIND_VIA
blind/buried via
Definition: router_tool.cpp:96
@ SELECT_LAYER
Ask user to select layer before adding via.
@ MICROVIA
Microvia.
Definition: router_tool.cpp:97
@ VIA_MASK
Definition: router_tool.cpp:94
@ VIA
Normal via.
Definition: router_tool.cpp:95
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:42
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.