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