KiCad PCB EDA Suite
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-2022 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 <wx/hyperlink.h>
24#include <advanced_config.h>
25
26#include <functional>
27#include <iomanip>
28#include <utility>
29#include <sstream>
30
31using namespace std::placeholders;
32#include <board.h>
34#include <board_item.h>
35#include <footprint.h>
36#include <fp_shape.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>
50#include <bitmaps.h>
51#include <string_utils.h>
52#include <painter.h>
53#include <tool/action_menu.h>
54#include <tool/tool_manager.h>
55#include <tool/tool_menu.h>
56#include <tools/pcb_actions.h>
59#include <tools/drc_tool.h>
62
63#include <project.h>
65
66#include "router_tool.h"
67#include "pns_segment.h"
68#include "pns_router.h"
69#include "pns_itemset.h"
70#include "pns_logger.h"
71#include "pns_placement_algo.h"
72#include "pns_line_placer.h"
73#include "pns_topology.h"
74
75#include "pns_kicad_iface.h"
76
78
80
81using namespace KIGFX;
82
87{
88 // Via type
89 VIA_MASK = 0x03,
90 VIA = 0x00,
91 BLIND_VIA = 0x01,
92 MICROVIA = 0x02,
93
94 // Select layer
96};
97
98
99// Actions, being statically-defined, require specialized I18N handling. We continue to
100// use the _() macro so that string harvesting by the I18N framework doesn't have to be
101// specialized, but we don't translate on initialization and instead do it in the getters.
102
103#undef _
104#define _(s) s
105
106static const TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack",
108 WXK_END, "",
109 _( "Finish Track" ), _( "Stops laying the current track." ),
111
112static const TOOL_ACTION ACT_PlaceThroughVia( "pcbnew.InteractiveRouter.PlaceVia",
114 'V', LEGACY_HK_NAME( "Add Through Via" ),
115 _( "Place Through Via" ),
116 _( "Adds a through-hole via at the end of currently routed track." ),
118
119static const TOOL_ACTION ACT_PlaceBlindVia( "pcbnew.InteractiveRouter.PlaceBlindVia",
121 MD_ALT + MD_SHIFT + 'V', LEGACY_HK_NAME( "Add Blind/Buried Via" ),
122 _( "Place Blind/Buried Via" ),
123 _( "Adds a blind or buried via at the end of currently routed track."),
125
126static const TOOL_ACTION ACT_PlaceMicroVia( "pcbnew.InteractiveRouter.PlaceMicroVia",
128 MD_CTRL + 'V', LEGACY_HK_NAME( "Add MicroVia" ),
129 _( "Place Microvia" ), _( "Adds a microvia at the end of currently routed track." ),
131
133 "pcbnew.InteractiveRouter.SelLayerAndPlaceVia",
135 '<', LEGACY_HK_NAME( "Select Layer and Add Through Via" ),
136 _( "Select Layer and Place Through Via..." ),
137 _( "Select a layer, then add a through-hole via at the end of currently routed track." ),
140
142 "pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia",
144 MD_ALT + '<', LEGACY_HK_NAME( "Select Layer and Add Blind/Buried Via" ),
145 _( "Select Layer and Place Blind/Buried Via..." ),
146 _( "Select a layer, then add a blind or buried via at the end of currently routed track." ),
149
151 "pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia",
153 0, "",
154 _( "Select Layer and Place Micro Via..." ),
155 _( "Select a layer, then add a micro via at the end of currently routed track." ),
158
159static const TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackViaSize",
161 'Q', LEGACY_HK_NAME( "Custom Track/Via Size" ),
162 _( "Custom Track/Via Size..." ),
163 _( "Shows a dialog for changing the track width and via size." ),
165
166static const TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture",
168 '/', LEGACY_HK_NAME( "Switch Track Posture" ),
169 _( "Switch Track Posture" ),
170 _( "Switches posture of the currently routed track." ),
172
173static const TOOL_ACTION ACT_SwitchCornerMode( "pcbnew.InteractiveRouter.SwitchRounding",
175 MD_CTRL + '/', "",
176 _( "Track Corner Mode" ),
177 _( "Switches between sharp/rounded and 45°/90° corners when routing tracks." ),
179
180#undef _
181#define _(s) wxGetTranslation((s))
182
183
185 TOOL_BASE( "pcbnew.InteractiveRouter" ),
186 m_lastTargetLayer( UNDEFINED_LAYER ),
187 m_originalActiveLayer( UNDEFINED_LAYER ),
188 m_inRouterTool( false )
189{
190}
191
192
194{
195public:
197 ACTION_MENU( true ),
198 m_frame( aFrame )
199 {
201 SetTitle( _( "Select Track/Via Width" ) );
202 }
203
204protected:
205 ACTION_MENU* create() const override
206 {
207 return new TRACK_WIDTH_MENU( m_frame );
208 }
209
210 void update() override
211 {
213 bool useIndex = !bds.m_UseConnectedTrackWidth &&
215 wxString msg;
216
217 Clear();
218
219 Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
220 _( "Route using the width of the starting track." ), wxITEM_CHECK );
223
224 Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
225 _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
227 useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
228
229 Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
230 _( "Specify custom track and via sizes" ), wxITEM_CHECK );
232
233 AppendSeparator();
234
235 // Append the list of tracks & via sizes
236 for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
237 {
238 int width = bds.m_TrackWidthList[i];
239
240 if( i == 0 )
241 msg = _( "Track netclass width" );
242 else
243 msg.Printf( _( "Track %s" ), m_frame.MessageTextFromValue( width ) );
244
245 int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
246 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
247 Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
248 }
249
250 AppendSeparator();
251
252 for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
253 {
255
256 if( i == 0 )
257 msg = _( "Via netclass values" );
258 else
259 {
260 if( via.m_Drill > 0 )
261 {
262 msg.Printf( _("Via %s, hole %s" ),
263 m_frame.MessageTextFromValue( via.m_Diameter ),
264 m_frame.MessageTextFromValue( via.m_Drill ) );
265 }
266 else
267 {
268 msg.Printf( _( "Via %s" ),
269 m_frame.MessageTextFromValue( via.m_Diameter ) );
270 }
271 }
272
273 int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
274 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
275 Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
276 }
277 }
278
279 OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
280 {
282 int id = aEvent.GetId();
283
284 // On Windows, this handler can be called with an event ID not existing in any
285 // menuitem, so only set flags when we have an ID match.
286
288 {
289 bds.UseCustomTrackViaSize( true );
290 bds.m_TempOverrideTrackWidth = true;
292 }
293 else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
294 {
295 bds.UseCustomTrackViaSize( false );
296 bds.m_UseConnectedTrackWidth = true;
297 bds.m_TempOverrideTrackWidth = false;
298 }
300 {
301 bds.UseCustomTrackViaSize( false );
302 bds.m_UseConnectedTrackWidth = false;
303 bds.SetViaSizeIndex( 0 );
304 bds.SetTrackWidthIndex( 0 );
305 }
307 {
308 bds.UseCustomTrackViaSize( false );
310 }
312 {
313 bds.UseCustomTrackViaSize( false );
314 bds.m_TempOverrideTrackWidth = true;
316 }
317
319 }
320
321private:
323};
324
325
327{
328public:
330 ACTION_MENU( true ),
331 m_frame( aFrame )
332 {
334 SetTitle( _( "Select Differential Pair Dimensions" ) );
335 }
336
337protected:
338 ACTION_MENU* create() const override
339 {
340 return new DIFF_PAIR_MENU( m_frame );
341 }
342
343 void update() override
344 {
346
347 Clear();
348
349 Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
350 _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
352 !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
353
354 Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
355 _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
357
358 AppendSeparator();
359
360 // Append the list of differential pair dimensions
361
362 // Drop index 0 which is the current netclass dimensions (which are handled above)
363 for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
364 {
366 wxString msg;
367
368 if( diffPair.m_Gap <= 0 )
369 {
370 if( diffPair.m_ViaGap <= 0 )
371 {
372 msg.Printf( _( "Width %s" ),
374 }
375 else
376 {
377 msg.Printf( _( "Width %s, via gap %s" ),
380 }
381 }
382 else
383 {
384 if( diffPair.m_ViaGap <= 0 )
385 {
386 msg.Printf( _( "Width %s, gap %s" ),
388 m_frame.MessageTextFromValue( diffPair.m_Gap ) );
389 }
390 else
391 {
392 msg.Printf( _( "Width %s, gap %s, via gap %s" ),
396 }
397 }
398
399 int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
400 Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
401 Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
402 }
403 }
404
405 OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
406 {
408 int id = aEvent.GetId();
409
410 // On Windows, this handler can be called with an event ID not existing in any
411 // menuitem, so only set flags when we have an ID match.
412
414 {
415 bds.UseCustomDiffPairDimensions( true );
416 TOOL_MANAGER* toolManager = m_frame.GetToolManager();
417 toolManager->RunAction( PCB_ACTIONS::routerDiffPairDialog, true );
418 }
420 {
421 bds.UseCustomDiffPairDimensions( false );
422 bds.SetDiffPairIndex( 0 );
423 }
425 {
426 bds.UseCustomDiffPairDimensions( false );
427 // remember that the menu doesn't contain index 0 (which is the netclass values)
429 }
430
432 }
433
434private:
436};
437
438
440{
441}
442
443
445{
448
449 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
450
451 wxASSERT( frame );
452
453 auto& menu = m_menu.GetMenu();
454 menu.SetTitle( _( "Interactive Router" ) );
455
456 m_trackViaMenu = std::make_shared<TRACK_WIDTH_MENU>( *frame );
457 m_trackViaMenu->SetTool( this );
459
460 m_diffPairMenu = std::make_shared<DIFF_PAIR_MENU>( *frame );
461 m_diffPairMenu->SetTool( this );
463
464 auto haveHighlight =
465 [&]( const SELECTION& sel )
466 {
468
469 return !cfg->GetHighlightNetCodes().empty();
470 };
471
472 auto notRoutingCond =
473 [this]( const SELECTION& )
474 {
475 return !m_router->RoutingInProgress();
476 };
477
478 auto hasOtherEnd =
479 [&]( const SELECTION& )
480 {
481 std::vector<int> currentNets = m_router->GetCurrentNets();
482
483 // Need to have something unconnected to finish to
484 int currentNet = currentNets.empty() ? -1 : currentNets[0];
485 BOARD* board = getEditFrame<PCB_EDIT_FRAME>()->GetBoard();
486 RN_NET* ratsnest = board->GetConnectivity()->GetRatsnestForNet( currentNet );
487
488 return ratsnest && !ratsnest->GetEdges().empty();
489 };
490
492 menu.AddSeparator( 1 );
493
494 menu.AddItem( PCB_ACTIONS::clearHighlight, haveHighlight, 2 );
495 menu.AddSeparator( haveHighlight, 2 );
496
497 menu.AddItem( PCB_ACTIONS::routeSingleTrack, notRoutingCond );
498 menu.AddItem( PCB_ACTIONS::routeDiffPair, notRoutingCond );
501 menu.AddItem( PCB_ACTIONS::routerContinueFromEnd, hasOtherEnd );
502 menu.AddItem( PCB_ACTIONS::routerAttemptFinish, hasOtherEnd );
503 menu.AddItem( PCB_ACTIONS::breakTrack, notRoutingCond );
504
505 menu.AddItem( PCB_ACTIONS::drag45Degree, notRoutingCond );
506 menu.AddItem( PCB_ACTIONS::dragFreeAngle, notRoutingCond );
507
516
517 menu.AddSeparator();
518
519 auto diffPairCond =
520 [this]( const SELECTION& )
521 {
523 };
524
526 menu.AddMenu( m_diffPairMenu.get(), diffPairCond );
527
529
530 menu.AddSeparator();
531
533
534 return true;
535}
536
537
539{
541
542 if( aReason == RUN )
543 TOOL_BASE::Reset( aReason );
544}
545
546// Saves the complete event log and the dump of the PCB, allowing us to
547// recreate hard-to-find P&S quirks and bugs.
548
550{
551 auto logger = m_router->Logger();
552
553 if( ! logger )
554 return;
555
556 wxString cwd = wxGetCwd();
557
558 wxFileName fname_log;
559 fname_log.SetPath( cwd );
560 fname_log.SetName( "pns.log" );
561
562 wxFileName fname_dump( cwd );
563 fname_dump.SetPath( cwd );
564 fname_dump.SetName( "pns.dump" );
565
566 wxFileName fname_settings( cwd );
567 fname_settings.SetPath( cwd );
568 fname_settings.SetName( "pns.settings" );
569
570 wxString msg = wxString::Format( _( "Event file: %s\nBoard dump: %s" ), fname_log.GetFullPath(), fname_log.GetFullPath() );
571
572 int rv = OKOrCancelDialog( nullptr, _("Save router log"), _("Would you like to save the router\nevent log for debugging purposes?"), msg, _("OK"), _("Cancel") );
573
574 if( !rv )
575 return;
576
577 FILE *f = fopen( fname_settings.GetFullPath().c_str(), "wb" );
578 std::string settingsStr = m_router->Settings().FormatAsString();
579 fprintf(f,"%s\n", settingsStr.c_str( ) );
580 fclose(f);
581
582 f = fopen( fname_log.GetFullPath().c_str(), "wb" );
583
584 fprintf(f, "mode %d\n", m_router->Mode() );
585
586 const auto& events = logger->GetEvents();
587
588 for( const auto& evt : events)
589 {
590 fprintf( f, "event %d %d %d %s %d %d %d %d %d %d %d\n", evt.p.x, evt.p.y, evt.type,
591 static_cast<const char*>( evt.uuid.AsString().c_str() ),
592 evt.sizes.TrackWidth(),
593 evt.sizes.ViaDiameter(),
594 evt.sizes.ViaDrill(),
595 evt.sizes.TrackWidthIsExplicit() ? 1: 0,
596 evt.sizes.GetLayerBottom(),
597 evt.sizes.GetLayerTop(),
598 static_cast<int>( evt.sizes.ViaType() ) );
599 }
600
601 // Export as *.kicad_pcb format, using a strategy which is specifically chosen
602 // as an example on how it could also be used to send it to the system clipboard.
603
604 PCB_PLUGIN pcb_io;
605
606 pcb_io.Save( fname_dump.GetFullPath(), m_iface->GetBoard(), nullptr );
607
608 PROJECT* prj = m_iface->GetBoard()->GetProject();
609 prj->GetProjectFile().SaveAs( cwd, "pns" );
610
611 std::vector<PNS::ITEM*> added, removed, heads;
612 m_router->GetUpdatedItems( removed, added, heads );
613
614 for( auto item : removed )
615 {
616 fprintf(f, "removed %s\n", item->Parent()->m_Uuid.AsString().c_str().AsChar() );
617 }
618
619 for( auto item : added )
620 {
621 fprintf(f, "added %s\n", item->Format().c_str() );
622 }
623
624 for( auto item : heads )
625 {
626 fprintf(f, "head %s\n", item->Format().c_str() );
627 }
628
629 fclose( f );
630}
631
632
634{
635 if( aEvent.Category() == TC_VIEW || aEvent.Category() == TC_MOUSE )
636 {
637 BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
638 m_router->SetVisibleViewArea( BOX2I( viewAreaD.GetOrigin(), viewAreaD.GetSize() ) );
639 }
640
641 if( !aEvent.IsKeyPressed() )
642 return;
643
644 switch( aEvent.KeyCode() )
645 {
646 case '0':
647 if( !ADVANCED_CFG::GetCfg().m_ShowRouterDebugGraphics )
648 return;
649
651 aEvent.SetPassEvent( false );
652 break;
653
654 default:
655 break;
656 }
657}
658
659
661{
662 int tl = getView()->GetTopLayer();
663
664 if( m_startItem )
665 {
666 const LAYER_RANGE& ls = m_startItem->Layers();
667
668 if( ls.Overlaps( tl ) )
669 return tl;
670 else
671 return ls.Start();
672 }
673
674 return tl;
675}
676
677
679{
680 int activeLayer = frame()->GetActiveLayer();
681 int currentLayer = m_router->GetCurrentLayer();
682
683 if( currentLayer != activeLayer )
684 m_router->SwitchLayer( activeLayer );
685
686 std::optional<int> newLayer = m_router->Sizes().PairedLayer( currentLayer );
687
688 if( !newLayer )
689 newLayer = m_router->Sizes().GetLayerTop();
690
691 m_router->SwitchLayer( *newLayer );
692 m_lastTargetLayer = *newLayer;
693
695}
696
697
699{
700 std::vector<int> nets = m_router->GetCurrentNets();
701
704 std::shared_ptr<DRC_ENGINE>& drcEngine = bds.m_DRCEngine;
705 DRC_CONSTRAINT constraint;
706
707 PCB_TRACK dummyTrack( board() );
708 dummyTrack.SetLayer( targetLayer );
709 dummyTrack.SetNetCode( nets.empty() ? 0 : nets[0] );
710
711 if( bds.UseNetClassTrack() || !sizes.TrackWidthIsExplicit() )
712 {
713 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, &dummyTrack, nullptr,
714 targetLayer );
715
716 if( !constraint.IsNull() )
717 {
718 int width = sizes.TrackWidth();
719
720 // Only change the size if we're explicitly using the net class, or we're out of range
721 // for our new constraints. Otherwise, just leave the track width alone so we don't
722 // change for no reason.
723 if( bds.UseNetClassTrack()
724 || ( width < bds.m_TrackMinWidth )
725 || ( width < constraint.m_Value.Min() )
726 || ( width > constraint.m_Value.Max() ) )
727 {
728 sizes.SetTrackWidth( std::max( bds.m_TrackMinWidth, constraint.m_Value.Opt() ) );
729 }
730
731 if( sizes.TrackWidth() == constraint.m_Value.Opt() )
732 sizes.SetWidthSource( constraint.GetName() );
733 else if( sizes.TrackWidth() == bds.m_TrackMinWidth )
734 sizes.SetWidthSource( _( "board minimum track width" ) );
735 else
736 sizes.SetWidthSource( _( "existing track" ) );
737 }
738 }
739
740 if( nets.size() >= 2 && ( bds.UseNetClassDiffPair() || !sizes.TrackWidthIsExplicit() ) )
741 {
742 PCB_TRACK dummyTrackB( board() );
743 dummyTrackB.SetLayer( targetLayer );
744 dummyTrackB.SetNetCode( nets[1] );
745
746 constraint = drcEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, &dummyTrack, &dummyTrackB,
747 targetLayer );
748
749 if( !constraint.IsNull() )
750 {
751 sizes.SetDiffPairWidth( std::max( bds.m_TrackMinWidth, constraint.m_Value.Opt() ) );
752
753 if( sizes.DiffPairWidth() == constraint.m_Value.Opt() )
754 sizes.SetDiffPairWidthSource( constraint.GetName() );
755 else
756 sizes.SetDiffPairWidthSource( _( "board minimum track width" ) );
757 }
758
759 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, &dummyTrack, &dummyTrackB,
760 targetLayer );
761
762 if( !constraint.IsNull() )
763 {
764 sizes.SetDiffPairGap( std::max( bds.m_MinClearance, constraint.m_Value.Opt() ) );
765
766 if( sizes.DiffPairGap() == constraint.m_Value.Opt() )
767 sizes.SetDiffPairGapSource( constraint.GetName() );
768 else
769 sizes.SetDiffPairGapSource( _( "board minimum clearance" ) );
770 }
771 }
772
773 m_router->UpdateSizes( sizes );
774}
775
776
777static VIATYPE getViaTypeFromFlags( int aFlags )
778{
779 switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
780 {
782 return VIATYPE::THROUGH;
786 return VIATYPE::MICROVIA;
787 default:
788 wxASSERT_MSG( false, wxT( "Unhandled via type" ) );
789 return VIATYPE::THROUGH;
790 }
791}
792
793
795{
796 if( aEvent.IsAction( &PCB_ACTIONS::layerTop ) )
797 return F_Cu;
798 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner1 ) )
799 return In1_Cu;
800 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner2 ) )
801 return In2_Cu;
802 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner3 ) )
803 return In3_Cu;
804 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner4 ) )
805 return In4_Cu;
806 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner5 ) )
807 return In5_Cu;
808 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner6 ) )
809 return In6_Cu;
810 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner7 ) )
811 return In7_Cu;
812 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner8 ) )
813 return In8_Cu;
814 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner9 ) )
815 return In9_Cu;
816 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner10 ) )
817 return In10_Cu;
818 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner11 ) )
819 return In11_Cu;
820 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner12 ) )
821 return In12_Cu;
822 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner13 ) )
823 return In13_Cu;
824 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner14 ) )
825 return In14_Cu;
826 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner15 ) )
827 return In15_Cu;
828 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner16 ) )
829 return In16_Cu;
830 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner17 ) )
831 return In17_Cu;
832 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner18 ) )
833 return In18_Cu;
834 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner19 ) )
835 return In19_Cu;
836 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner20 ) )
837 return In20_Cu;
838 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner21 ) )
839 return In21_Cu;
840 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner22 ) )
841 return In22_Cu;
842 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner23 ) )
843 return In23_Cu;
844 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner24 ) )
845 return In24_Cu;
846 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner25 ) )
847 return In25_Cu;
848 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner26 ) )
849 return In26_Cu;
850 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner27 ) )
851 return In27_Cu;
852 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner28 ) )
853 return In28_Cu;
854 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner29 ) )
855 return In29_Cu;
856 else if( aEvent.IsAction( &PCB_ACTIONS::layerInner30 ) )
857 return In30_Cu;
858 else if( aEvent.IsAction( &PCB_ACTIONS::layerBottom ) )
859 return B_Cu;
860 else
861 return UNDEFINED_LAYER;
862}
863
864
866{
867 return handleLayerSwitch( aEvent, false );
868}
869
870
872{
873 if( !m_router->IsPlacingVia() )
874 {
875 return handleLayerSwitch( aEvent, true );
876 }
877 else
878 {
881 updateEndItem( aEvent );
883 }
884
885 return 0;
886}
887
888
889int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
890{
891 wxCHECK( m_router, 0 );
892
893 if( !IsToolActive() )
894 return 0;
895
896 // First see if this is one of the switch layer commands
897 LSEQ layers = LSET( board()->GetEnabledLayers() & LSET::AllCuMask() ).Seq();
899 PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
900
901 if( aEvent.IsAction( &PCB_ACTIONS::layerNext ) )
902 {
904 m_lastTargetLayer = currentLayer;
905
906 size_t idx = 0;
907
908 for( size_t i = 0; i < layers.size(); i++ )
909 {
910 if( layers[i] == m_lastTargetLayer )
911 {
912 idx = i;
913 break;
914 }
915 }
916
917 idx = ( idx + 1 ) % layers.size();
918 targetLayer = layers[idx];
919 }
920 else if( aEvent.IsAction( &PCB_ACTIONS::layerPrev ) )
921 {
923 m_lastTargetLayer = currentLayer;
924
925 size_t idx = 0;
926
927 for( size_t i = 0; i < layers.size(); i++ )
928 {
929 if( layers[i] == m_lastTargetLayer )
930 {
931 idx = i;
932 break;
933 }
934 }
935
936 idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers.size() - 1 );
937 targetLayer = layers[idx];
938 }
939 else
940 {
941 targetLayer = getTargetLayerFromEvent( aEvent );
942 }
943
944 if( targetLayer != UNDEFINED_LAYER )
945 {
946 m_lastTargetLayer = targetLayer;
947
948 if( targetLayer == currentLayer )
949 return 0;
950
951 if( !aForceVia && m_router && m_router->SwitchLayer( targetLayer ) )
952 {
953 updateSizesAfterLayerSwitch( targetLayer );
954 updateEndItem( aEvent );
955 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
956 return 0;
957 }
958 }
959
961 const int layerCount = bds.GetCopperLayerCount();
962
965
967
968 VIATYPE viaType = VIATYPE::THROUGH;
969 bool selectLayer = false;
970
971 // Otherwise it is one of the router-specific via commands
972 if( targetLayer == UNDEFINED_LAYER )
973 {
974 const int actViaFlags = aEvent.Parameter<intptr_t>();
975 selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
976
977 viaType = getViaTypeFromFlags( actViaFlags );
978
979 // ask the user for a target layer
980 if( selectLayer )
981 {
982 wxPoint endPoint = ToWxPoint( view()->ToScreen( m_endSnapPoint ) );
983 endPoint = frame()->GetCanvas()->ClientToScreen( endPoint );
984
985 // Build the list of not allowed layer for the target layer
986 LSET not_allowed_ly = LSET::AllNonCuMask();
987
988 if( viaType != VIATYPE::THROUGH )
989 not_allowed_ly.set( currentLayer );
990
991 if( viaType == VIATYPE::MICROVIA )
992 {
993 // Allows only the previous or the next layer from the current layer
994 int previous_layer = currentLayer == B_Cu ? layerCount - 2
995 : currentLayer - 1;
996
997 int next_layer = currentLayer >= layerCount-2 ? B_Cu
998 : currentLayer + 1;
999
1000 not_allowed_ly = LSET::AllLayersMask();
1001
1002 if( previous_layer >= F_Cu && previous_layer != currentLayer )
1003 not_allowed_ly.reset( previous_layer );
1004
1005 if( next_layer != currentLayer )
1006 not_allowed_ly.reset( next_layer );
1007 }
1008
1009 targetLayer = frame()->SelectOneLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
1010 not_allowed_ly, endPoint );
1011
1012 // Reset the cursor to the end of the track
1014
1015 if( targetLayer == UNDEFINED_LAYER ) // cancelled by user
1016 return 0;
1017
1018 // One cannot place a blind/buried via on only one layer:
1019 if( viaType != VIATYPE::THROUGH )
1020 {
1021 if( currentLayer == targetLayer )
1022 return 0;
1023 }
1024 }
1025 }
1026
1027 // fixme: P&S supports more than one fixed layer pair. Update the dialog?
1028 sizes.ClearLayerPairs();
1029
1030 // Convert blind/buried via to a through hole one, if it goes through all layers
1031 if( viaType == VIATYPE::BLIND_BURIED
1032 && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
1033 || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
1034 {
1035 viaType = VIATYPE::THROUGH;
1036 }
1037
1038 if( targetLayer == UNDEFINED_LAYER )
1039 {
1040 // Implicic layer selection
1041
1042 switch( viaType )
1043 {
1044 case VIATYPE::THROUGH:
1045 // use the default layer pair
1046 currentLayer = pairTop;
1047 targetLayer = pairBottom;
1048 break;
1049
1050 case VIATYPE::MICROVIA:
1051 // Try to use the layer pair preset, if the layers are adjacent,
1052 // because a microvia is usually restricted to 2 adjacent copper layers
1053 if( pairTop > pairBottom ) std::swap( pairTop, pairBottom );
1054
1055 if( currentLayer == pairTop && pairBottom == pairTop+1 )
1056 {
1057 targetLayer = pairBottom;
1058 }
1059 else if( currentLayer == pairBottom && pairBottom == pairTop+1 )
1060 {
1061 targetLayer = pairTop;
1062 }
1063 else if( currentLayer == F_Cu || currentLayer == In1_Cu )
1064 {
1065 // front-side microvia
1066 currentLayer = F_Cu;
1067
1068 if( layerCount > 2 ) // Ensure the inner layer In1_Cu exists
1069 targetLayer = In1_Cu;
1070 else
1071 targetLayer = B_Cu;
1072 }
1073 else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
1074 {
1075 // back-side microvia
1076 currentLayer = B_Cu,
1077 targetLayer = (PCB_LAYER_ID) ( layerCount - 2 );
1078 }
1079 else
1080 {
1081 // This is not optimal: from an internal layer one can want to switch
1082 // to the previous or the next internal layer
1083 // but at this point we do not know what the user want.
1084 targetLayer = PCB_LAYER_ID( currentLayer + 1 );
1085 }
1086
1087 break;
1088
1090 if( currentLayer == pairTop || currentLayer == pairBottom )
1091 {
1092 // the current layer is on the defined layer pair,
1093 // swap to the other side
1094 currentLayer = pairTop;
1095 targetLayer = pairBottom;
1096 }
1097 else
1098 {
1099 // the current layer is not part of the current layer pair,
1100 // so fallback and swap to the top layer of the pair by default
1101 targetLayer = pairTop;
1102 }
1103
1104 // Do not create a broken via (i.e. a via on only one copper layer)
1105 if( currentLayer == targetLayer )
1106 {
1107 WX_INFOBAR* infobar = frame()->GetInfoBar();
1108 infobar->ShowMessageFor( _( "Blind/buried via need 2 different layers." ),
1109 2000, wxICON_ERROR,
1111 return 0;
1112 }
1113
1114 break;
1115
1116 default:
1117 wxFAIL_MSG( wxT( "unexpected via type" ) );
1118 return 0;
1119 break;
1120 }
1121 }
1122
1123 sizes.SetViaDiameter( bds.m_ViasMinSize );
1124 sizes.SetViaDrill( bds.m_MinThroughDrill );
1125
1126 if( bds.UseNetClassVia() || viaType == VIATYPE::MICROVIA )
1127 {
1128 PCB_VIA dummyVia( board() );
1129 dummyVia.SetViaType( viaType );
1130 dummyVia.SetLayerPair( currentLayer, targetLayer );
1131
1132 if( !m_router->GetCurrentNets().empty() )
1133 dummyVia.SetNetCode( m_router->GetCurrentNets()[0] );
1134
1135 DRC_CONSTRAINT constraint;
1136
1137 constraint = bds.m_DRCEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, &dummyVia, nullptr,
1138 currentLayer );
1139
1140 if( !constraint.IsNull() )
1141 sizes.SetViaDiameter( constraint.m_Value.Opt() );
1142
1143 constraint = bds.m_DRCEngine->EvalRules( HOLE_SIZE_CONSTRAINT, &dummyVia, nullptr,
1144 currentLayer );
1145
1146 if( !constraint.IsNull() )
1147 sizes.SetViaDrill( constraint.m_Value.Opt() );
1148 }
1149 else
1150 {
1151 sizes.SetViaDiameter( bds.GetCurrentViaSize() );
1152 sizes.SetViaDrill( bds.GetCurrentViaDrill() );
1153 }
1154
1155 sizes.SetViaType( viaType );
1156 sizes.AddLayerPair( currentLayer, targetLayer );
1157
1158 m_router->UpdateSizes( sizes );
1159
1160 if( !m_router->IsPlacingVia() )
1162
1163 m_lastTargetLayer = targetLayer;
1164
1166 {
1167 updateEndItem( aEvent );
1169 }
1170 else
1171 {
1172 updateStartItem( aEvent );
1173 }
1174
1175 return 0;
1176}
1177
1178
1180{
1181 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1182 int routingLayer = getStartLayer( m_startItem );
1183
1184 if( !IsCopperLayer( routingLayer ) )
1185 {
1186 editFrame->ShowInfoBarError( _( "Tracks on Copper layers only." ) );
1187 return false;
1188 }
1189
1191 editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
1192
1193 if( !getView()->IsLayerVisible( routingLayer ) )
1194 {
1195 editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1196 editFrame->GetCanvas()->Refresh();
1197 }
1198
1200
1201 m_iface->SetStartLayer( routingLayer );
1202
1204 m_iface->ImportSizes( sizes, m_startItem, -1 );
1205 sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
1206 frame()->GetScreen()->m_Route_Layer_BOTTOM );
1207
1208 m_router->UpdateSizes( sizes );
1209
1210 if( m_startItem && m_startItem->Net() > 0 )
1211 {
1213 {
1214 if( int coupledNet = m_router->GetRuleResolver()->DpCoupledNet( m_startItem->Net() ) )
1215 highlightNets( true, { m_startItem->Net(), coupledNet } );
1216 }
1217 else
1218 {
1219 highlightNets( true, { m_startItem->Net() } );
1220 }
1221 }
1222
1223 controls()->SetAutoPan( true );
1224
1225 if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
1226 {
1227 // It would make more sense to leave the net highlighted as the higher-contrast mode
1228 // makes the router clearances more visible. However, since we just started routing
1229 // the conversion of the screen from low contrast to high contrast is a bit jarring and
1230 // makes the infobar coming up less noticeable.
1231 highlightNets( false );
1232
1234 [&]()
1235 {
1236 m_router->ClearViewDecorations();
1237 } );
1238
1239 controls()->SetAutoPan( false );
1240 return false;
1241 }
1242
1243 m_endItem = nullptr;
1245
1247 frame()->UndoRedoBlock( true );
1248
1249 return true;
1250}
1251
1252
1254{
1256
1257 m_startItem = nullptr;
1258 m_endItem = nullptr;
1259
1263 controls()->SetAutoPan( false );
1264 controls()->ForceCursorPosition( false );
1265 frame()->UndoRedoBlock( false );
1266 highlightNets( false );
1267
1268 return true;
1269}
1270
1271
1273{
1275
1276 if( !prepareInteractive() )
1277 return;
1278
1279 auto setCursor =
1280 [&]()
1281 {
1283 };
1284
1285 auto syncRouterAndFrameLayer =
1286 [&]()
1287 {
1288 PCB_LAYER_ID routingLayer = ToLAYER_ID( m_router->GetCurrentLayer() );
1289 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1290
1291 editFrame->SetActiveLayer( routingLayer );
1292
1293 if( !getView()->IsLayerVisible( routingLayer ) )
1294 {
1295 editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1296 editFrame->GetCanvas()->Refresh();
1297 }
1298 };
1299
1300 // Set initial cursor
1301 setCursor();
1302
1303 while( TOOL_EVENT* evt = Wait() )
1304 {
1305 setCursor();
1306
1307 // Don't crash if we missed an operation that canceled routing.
1308 if( !m_router->RoutingInProgress() )
1309 {
1310 if( evt->IsCancelInteractive() )
1311 m_cancelled = true;
1312
1313 break;
1314 }
1315
1316 handleCommonEvents( *evt );
1317
1318 if( evt->IsMotion() )
1319 {
1320 updateEndItem( *evt );
1322 }
1323 else if( evt->IsAction( &PCB_ACTIONS::routerUndoLastSegment ) )
1324 {
1326 updateEndItem( *evt );
1328 }
1329 else if( evt->IsAction( &PCB_ACTIONS::routerAttemptFinish ) )
1330 {
1331 bool* autoRouted = evt->Parameter<bool*>();
1332
1333 if( m_router->Finish() )
1334 {
1335 // When we're routing a group of signals automatically we want
1336 // to break up the undo stack every time we have to manually route
1337 // so the user gets nice checkpoints. Remove the APPEND_UNDO flag.
1338 if( autoRouted != nullptr )
1339 *autoRouted = true;
1340
1341 break;
1342 }
1343 else
1344 {
1345 // This acts as check if we were called by the autorouter; we don't want
1346 // to reset APPEND_UNDO if we're auto finishing after route-other-end
1347 if( autoRouted != nullptr )
1348 {
1349 *autoRouted = false;
1350 m_iface->SetCommitFlags( 0 );
1351 }
1352
1353 // Warp the mouse so the user is at the point we managed to route to
1354 controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
1355 }
1356 }
1357 else if( evt->IsAction( &PCB_ACTIONS::routerContinueFromEnd ) )
1358 {
1359 bool needsAppend = m_router->Placer()->HasPlacedAnything();
1360
1361 if( m_router->ContinueFromEnd() )
1362 {
1363 syncRouterAndFrameLayer();
1365
1366 // Warp the mouse to wherever we actually ended up routing to
1367 controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
1368
1369 // We want the next router commit to be one undo at the UI layer
1370 m_iface->SetCommitFlags( needsAppend ? APPEND_UNDO : 0 );
1371 }
1372 }
1373 else if( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
1374 {
1375 updateEndItem( *evt );
1376 bool needLayerSwitch = m_router->IsPlacingVia();
1377 bool forceFinish = evt->Modifier( MD_SHIFT );
1378
1379 if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) )
1380 break;
1381
1382 if( needLayerSwitch )
1384
1385 // Synchronize the indicated layer
1386 syncRouterAndFrameLayer();
1387
1388 updateEndItem( *evt );
1390 m_startItem = nullptr;
1391 }
1392 else if( evt->IsAction( &ACT_SwitchCornerMode ) )
1393 {
1396 updateEndItem( *evt );
1397 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1398 }
1399 else if( evt->IsAction( &ACT_SwitchPosture ) )
1400 {
1402 updateEndItem( *evt );
1403 m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1404 }
1405 else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1406 {
1408 controls()->SetAutoPan( false );
1409 {
1411 }
1412 controls()->SetAutoPan( true );
1413 setCursor();
1415 }
1416 else if( evt->IsAction( &ACT_EndTrack ) || evt->IsDblClick( BUT_LEFT ) )
1417 {
1418 // Stop current routing:
1420 break;
1421 }
1422 else if( evt->IsCancelInteractive() || evt->IsActivate()
1423 || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
1424 {
1425 if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
1426 m_cancelled = true;
1427
1428 if( evt->IsActivate() && !evt->IsMoveTool() )
1429 m_cancelled = true;
1430
1431 break;
1432 }
1433 else if( evt->IsUndoRedo() )
1434 {
1435 // We're in an UndoRedoBlock. If we get here, something's broken.
1436 wxFAIL;
1437 break;
1438 }
1439 else if( evt->IsClick( BUT_RIGHT ) )
1440 {
1442 }
1443 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
1444 // but we don't at present have that, so we just knock out some of the egregious ones.
1445 else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
1446 {
1447 wxBell();
1448 }
1449 else
1450 {
1451 evt->SetPassEvent();
1452 }
1453 }
1454
1456 // Reset to normal for next route
1457 m_iface->SetCommitFlags( 0 );
1458
1460}
1461
1462
1464{
1466 DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
1467
1468 if( settingsDlg.ShowModal() == wxID_OK )
1469 {
1470 m_router->UpdateSizes( sizes );
1471 m_savedSizes = sizes;
1472
1475 bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
1477 }
1478
1479 return 0;
1480}
1481
1482
1484{
1485 DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
1486
1487 settingsDlg.ShowModal();
1488
1490
1491 return 0;
1492}
1493
1494
1496{
1497 PNS::PNS_MODE mode = aEvent.Parameter<PNS::PNS_MODE>();
1499
1500 settings.SetMode( mode );
1501
1502 return 0;
1503}
1504
1505
1507{
1509 PNS::PNS_MODE mode = settings.Mode();
1510
1511 switch( mode )
1512 {
1513 case PNS::RM_MarkObstacles: mode = PNS::RM_Shove; break;
1514 case PNS::RM_Shove: mode = PNS::RM_Walkaround; break;
1515 case PNS::RM_Walkaround: mode = PNS::RM_MarkObstacles; break;
1516 }
1517
1518 settings.SetMode( mode );
1519
1520 return 0;
1521}
1522
1523
1525{
1526 return m_router->Settings().Mode();
1527}
1528
1529
1531{
1532 return m_router->RoutingInProgress();
1533}
1534
1535
1537{
1540}
1541
1542
1544{
1546 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1548 PCB_LAYER_ID originalLayer = frame->GetActiveLayer();
1549 bool autoRoute = aEvent.Matches( PCB_ACTIONS::routerAutorouteSelected.MakeEvent() );
1550 bool otherEnd = aEvent.Matches( PCB_ACTIONS::routerRouteSelectedFromEnd.MakeEvent() );
1551
1553 return 0;
1554
1555 // Save selection then clear it for interactive routing
1557
1558 if( selection.Size() == 0 )
1559 return 0;
1560
1562
1563 frame->PushTool( aEvent );
1564
1565 auto setCursor =
1566 [&]()
1567 {
1569 };
1570
1571 Activate();
1572 // Must be done after Activate() so that it gets set into the correct context
1573 controls->ShowCursor( true );
1574 controls->ForceCursorPosition( false );
1575 // Set initial cursor
1576 setCursor();
1577
1578 // Get all connected board items, adding pads for any footprints selected
1579 std::vector<BOARD_CONNECTED_ITEM*> itemList;
1580
1582 {
1583 if( item->Type() == PCB_FOOTPRINT_T )
1584 {
1585 const PADS& fpPads = ( static_cast<FOOTPRINT*>( item ) )->Pads();
1586
1587 for( PAD* pad : fpPads )
1588 itemList.push_back( pad );
1589 }
1590 else if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) != nullptr )
1591 {
1592 itemList.push_back( static_cast<BOARD_CONNECTED_ITEM*>( item ) );
1593 }
1594 }
1595
1596 std::shared_ptr<CONNECTIVITY_DATA> connectivity = frame->GetBoard()->GetConnectivity();
1597
1598 // For putting sequential tracks that successfully autoroute into one undo commit
1599 bool groupStart = true;
1600
1601 for( BOARD_CONNECTED_ITEM* item : itemList )
1602 {
1603 // This code is similar to GetRatsnestForPad() but it only adds the anchor for
1604 // the side of the connectivity on this pad. It also checks for ratsnest points
1605 // inside the pad (like a trace end) and counts them.
1606 RN_NET* net = connectivity->GetRatsnestForNet( item->GetNetCode() );
1607 std::vector<std::shared_ptr<const CN_ANCHOR>> anchors;
1608
1609 for( const CN_EDGE& edge : net->GetEdges() )
1610 {
1611 std::shared_ptr<const CN_ANCHOR> target = edge.GetTargetNode();
1612 std::shared_ptr<const CN_ANCHOR> source = edge.GetSourceNode();
1613
1614 if( source->Parent() == item )
1615 anchors.push_back( edge.GetSourceNode() );
1616 else if( target->Parent() == item )
1617 anchors.push_back( edge.GetTargetNode() );
1618 }
1619
1620 // Route them
1621 for( std::shared_ptr<const CN_ANCHOR> anchor : anchors )
1622 {
1623 // Try to return to the original layer as indicating the user's preferred
1624 // layer for autorouting tracks. The layer can be changed by the user to
1625 // finish tracks that can't complete automatically, but should be changed
1626 // back after.
1627 if( frame->GetActiveLayer() != originalLayer )
1628 frame->SetActiveLayer( originalLayer );
1629
1630 VECTOR2I ignore;
1632 m_startSnapPoint = anchor->Pos();
1633 m_router->SetMode( mode );
1634
1635 // Prime the interactive routing to attempt finish if we are autorouting
1636 bool autoRouted = false;
1637
1638 if( autoRoute )
1640 else if( otherEnd )
1642
1643 // We want autorouted tracks to all be in one undo group except for
1644 // any tracks that need to be manually finished.
1645 // The undo appending for manually finished tracks is handled in peformRouting()
1646 if( groupStart )
1647 groupStart = false;
1648 else
1650
1651 // Start interactive routing. Will automatically finish if possible.
1653
1654 // Route didn't complete automatically, need to a new undo commit
1655 // for the next line so those can group as far as they autoroute
1656 if( !autoRouted )
1657 groupStart = true;
1658 }
1659 }
1660
1661 m_iface->SetCommitFlags( 0 );
1662 frame->PopTool( aEvent );
1663 return 0;
1664}
1665
1666
1668{
1669 if( m_inRouterTool )
1670 return 0;
1671
1673
1675 PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1677
1679 {
1680 if( m_router->Mode() == mode )
1681 return 0;
1682 else
1684 }
1685
1686 // Deselect all items
1688
1689 frame->PushTool( aEvent );
1690
1691 auto setCursor =
1692 [&]()
1693 {
1695 };
1696
1697 Activate();
1698 // Must be done after Activate() so that it gets set into the correct context
1699 controls->ShowCursor( true );
1700 controls->ForceCursorPosition( false );
1701 // Set initial cursor
1702 setCursor();
1703
1704 m_router->SetMode( mode );
1705 m_cancelled = false;
1706
1707 if( aEvent.HasPosition() )
1708 m_toolMgr->PrimeTool( aEvent.Position() );
1709
1710 // Main loop: keep receiving events
1711 while( TOOL_EVENT* evt = Wait() )
1712 {
1713 if( !evt->IsDrag() )
1714 setCursor();
1715
1716 if( evt->IsCancelInteractive() )
1717 {
1718 frame->PopTool( aEvent );
1719 break;
1720 }
1721 else if( evt->IsActivate() )
1722 {
1723 if( evt->IsMoveTool() || evt->IsEditorTool() )
1724 {
1725 // leave ourselves on the stack so we come back after the move
1726 break;
1727 }
1728 else
1729 {
1730 frame->PopTool( aEvent );
1731 break;
1732 }
1733 }
1734 else if( evt->Action() == TA_UNDO_REDO_PRE )
1735 {
1737 }
1738 else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
1739 {
1741 }
1742 else if( evt->IsMotion() )
1743 {
1744 updateStartItem( *evt );
1745 }
1746 else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
1747 {
1748 updateStartItem( *evt, true );
1750 }
1751 else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
1752 {
1753 updateStartItem( *evt, true );
1755 }
1756 else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
1757 {
1758 updateStartItem( *evt, true );
1759 breakTrack( );
1760 evt->SetPassEvent( false );
1761 }
1762 else if( evt->IsClick( BUT_LEFT )
1763 || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
1764 || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
1765 {
1766 updateStartItem( *evt );
1767
1768 if( evt->HasPosition() )
1769 {
1770 if( evt->Modifier( MD_SHIFT ) )
1772 else
1774 }
1775 }
1776 else if( evt->IsAction( &ACT_PlaceThroughVia ) )
1777 {
1779 }
1780 else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1781 {
1784 updateStartItem( *evt );
1785 }
1786 else if( evt->IsKeyPressed() )
1787 {
1788 // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
1789 // event so we need to process the wxEVT_CHAR event that will follow as long as we
1790 // pass the event.
1791 evt->SetPassEvent();
1792 }
1793 else if( evt->IsClick( BUT_RIGHT ) )
1794 {
1796 }
1797 else
1798 {
1799 evt->SetPassEvent();
1800 }
1801
1802 if( m_cancelled )
1803 {
1804 frame->PopTool( aEvent );
1805 break;
1806 }
1807 }
1808
1809 // Store routing settings till the next invocation
1812
1813 return 0;
1814}
1815
1816
1818{
1820
1822
1823 if( m_startItem && m_startItem->IsLocked() )
1824 {
1825 KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1826 wxOK | wxCANCEL | wxICON_WARNING );
1827 dlg.SetOKLabel( _( "Drag Anyway" ) );
1828 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1829
1830 if( dlg.ShowModal() == wxID_CANCEL )
1831 return;
1832 }
1833
1834 // We don't support dragging arcs inside the PNS right now
1836 {
1839
1840 m_startItem = nullptr;
1841
1842 m_gridHelper->SetAuxAxes( false );
1843 ctls->ForceCursorPosition( false );
1844 highlightNets( false );
1845
1846 m_cancelled = true;
1847
1849
1850 return;
1851 }
1852
1853 bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1854
1855 if( !dragStarted )
1856 return;
1857
1858 if( m_startItem && m_startItem->Net() > 0 )
1859 highlightNets( true, { m_startItem->Net() } );
1860
1861 ctls->SetAutoPan( true );
1863 frame()->UndoRedoBlock( true );
1864
1865 while( TOOL_EVENT* evt = Wait() )
1866 {
1867 ctls->ForceCursorPosition( false );
1868
1869 if( evt->IsMotion() )
1870 {
1871 updateEndItem( *evt );
1873 }
1874 else if( evt->IsClick( BUT_LEFT ) )
1875 {
1877 break;
1878 }
1879 else if( evt->IsClick( BUT_RIGHT ) )
1880 {
1882 }
1883 else if( evt->IsCancelInteractive() || evt->IsActivate() )
1884 {
1885 if( evt->IsCancelInteractive() && !m_startItem )
1886 m_cancelled = true;
1887
1888 if( evt->IsActivate() && !evt->IsMoveTool() )
1889 m_cancelled = true;
1890
1891 break;
1892 }
1893 else if( evt->IsUndoRedo() )
1894 {
1895 // We're in an UndoRedoBlock. If we get here, something's broken.
1896 wxFAIL;
1897 break;
1898 }
1899 else if( evt->Category() == TC_COMMAND )
1900 {
1901 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
1902 // but we don't at present have that, so we just knock out some of the egregious ones.
1903 if( evt->IsAction( &ACTIONS::cut )
1904 || evt->IsAction( &ACTIONS::copy )
1905 || evt->IsAction( &ACTIONS::paste )
1906 || evt->IsAction( &ACTIONS::pasteSpecial )
1908 {
1909 wxBell();
1910 }
1911 // treat an undo as an escape
1912 else if( evt->IsAction( &ACTIONS::undo ) )
1913 {
1914 if( m_startItem )
1915 break;
1916 else
1917 wxBell();
1918 }
1919 else
1920 {
1921 evt->SetPassEvent();
1922 }
1923 }
1924 else
1925 {
1926 evt->SetPassEvent();
1927 }
1928
1929 handleCommonEvents( *evt );
1930 }
1931
1934
1935 m_startItem = nullptr;
1936
1937 m_gridHelper->SetAuxAxes( false );
1938 frame()->UndoRedoBlock( false );
1939 ctls->SetAutoPan( false );
1940 ctls->ForceCursorPosition( false );
1941 highlightNets( false );
1942}
1943
1944
1946{
1947 /*
1948 * If the collection contains a trivial line corner (two connected segments)
1949 * or a non-fanout-via (a via with no more than two connected segments), then
1950 * trim the collection down to a single item (which one won't matter since
1951 * they're all connected).
1952 */
1953
1954 // First make sure we've got something that *might* match.
1955 int vias = aCollector.CountType( PCB_VIA_T );
1956 int traces = aCollector.CountType( PCB_TRACE_T );
1957 int arcs = aCollector.CountType( PCB_ARC_T );
1958
1959 if( arcs > 0 || vias > 1 || traces > 2 || vias + traces < 1 )
1960 return;
1961
1962 // Fetch first PCB_TRACK (via or trace) as our reference
1963 PCB_TRACK* reference = nullptr;
1964
1965 for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
1966 reference = dynamic_cast<PCB_TRACK*>( aCollector[i] );
1967
1968 int refNet = reference->GetNetCode();
1969
1970 VECTOR2I refPoint( aPt.x, aPt.y );
1971 EDA_ITEM_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
1972
1973 if( flags & STARTPOINT )
1974 refPoint = reference->GetStart();
1975 else if( flags & ENDPOINT )
1976 refPoint = reference->GetEnd();
1977
1978 // Check all items to ensure that any TRACKs are co-terminus with the reference and on
1979 // the same net.
1980 for( int i = 0; i < aCollector.GetCount(); i++ )
1981 {
1982 PCB_TRACK* neighbor = dynamic_cast<PCB_TRACK*>( aCollector[i] );
1983
1984 if( neighbor && neighbor != reference )
1985 {
1986 if( neighbor->GetNetCode() != refNet )
1987 return;
1988
1989 if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
1990 return;
1991 }
1992 }
1993
1994 // Selection meets criteria; trim it to the reference item.
1995 aCollector.Empty();
1996 aCollector.Append( reference );
1997}
1998
1999
2000bool ROUTER_TOOL::CanInlineDrag( int aDragMode )
2001{
2003 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2004
2005 if( selection.Size() == 1 )
2006 {
2007 const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
2008
2009 // Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using
2010 // DragArcTrack(), so PCB_ARC_T should never occur here.
2012 {
2013 // Footprints cannot be dragged freely.
2014 if( item->IsType( { PCB_FOOTPRINT_T } ) )
2015 return !( aDragMode & PNS::DM_FREE_ANGLE );
2016 else
2017 return true;
2018 }
2019 }
2020
2021 return false;
2022}
2023
2024
2026{
2027 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2028
2029 if( selection.Empty() )
2031
2032 if( selection.Size() != 1 )
2033 return 0;
2034
2035 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
2036
2037 if( item->Type() != PCB_TRACE_T
2038 && item->Type() != PCB_VIA_T
2039 && item->Type() != PCB_FOOTPRINT_T )
2040 {
2041 return 0;
2042 }
2043
2044 // If we overrode locks, we want to clear the flag from the source item before SyncWorld is
2045 // called so that virtual vias are not generated for the (now unlocked) track segment. Note in
2046 // this case the lock can't be reliably re-applied, because there is no guarantee that the end
2047 // state of the drag results in the same number of segments so it's not clear which segment to
2048 // apply the lock state to.
2049 bool wasLocked = false;
2050
2051 if( item->IsLocked() )
2052 {
2053 wasLocked = true;
2054 item->SetLocked( false );
2055 }
2056
2058
2059 Activate();
2060
2061 m_startItem = nullptr;
2062
2063 PNS::ITEM* startItem = nullptr;
2064 PNS::ITEM_SET itemsToDrag;
2065 FOOTPRINT* footprint = nullptr;
2066
2067 bool showCourtyardConflicts = frame()->GetPcbNewSettings()->m_ShowCourtyardCollisions;
2068
2069 std::shared_ptr<DRC_ENGINE> drcEngine = m_toolMgr->GetTool<DRC_TOOL>()->GetDRCEngine();
2070 DRC_INTERACTIVE_COURTYARD_CLEARANCE courtyardClearanceDRC( drcEngine );
2071
2072 std::shared_ptr<CONNECTIVITY_DATA> connectivityData = board()->GetConnectivity();
2073 std::vector<BOARD_ITEM*> dynamicItems;
2074 std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr;
2075 VECTOR2I lastOffset;
2076
2077 if( item->Type() == PCB_FOOTPRINT_T )
2078 {
2079 footprint = static_cast<FOOTPRINT*>( item );
2080
2081 for( PAD* pad : footprint->Pads() )
2082 {
2084
2085 if( solid )
2086 itemsToDrag.Add( solid );
2087
2088 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
2089 {
2090 if( connectivityData->GetRatsnestForPad( pad ).size() > 0 )
2091 dynamicItems.push_back( pad );
2092 }
2093 }
2094
2095 if( showCourtyardConflicts )
2096 {
2097 courtyardClearanceDRC.Init( board() );
2098 courtyardClearanceDRC.m_FpInMove.push_back( footprint );
2099 }
2100
2101 dynamicData = std::make_unique<CONNECTIVITY_DATA>( dynamicItems, true );
2102 connectivityData->BlockRatsnestItems( dynamicItems );
2103 }
2104 else
2105 {
2106 startItem = m_router->GetWorld()->FindItemByParent( item );
2107
2108 if( startItem )
2109 itemsToDrag.Add( startItem );
2110 }
2111
2112 GAL* gal = m_toolMgr->GetView()->GetGAL();
2113 VECTOR2I p0 = controls()->GetCursorPosition( false );
2114 VECTOR2I p = p0;
2115
2117 m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
2118
2119 if( startItem )
2120 {
2121 p = snapToItem( startItem, p0 );
2122 m_startItem = startItem;
2123
2124 if( m_startItem && m_startItem->Net() > 0 )
2125 highlightNets( true, { m_startItem->Net() } );
2126 }
2127 else if( footprint )
2128 {
2129 // The mouse is going to be moved on grid before dragging begins.
2130 VECTOR2I tweakedMousePos;
2131 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
2132
2133 // Check if user wants to warp the mouse to origin of moved object
2134
2135 if( editFrame->GetMoveWarpsCursor() )
2136 tweakedMousePos = footprint->GetPosition(); // Use footprint anchor to warp mouse
2137 else
2138 tweakedMousePos = controls()->GetCursorPosition(); // Just use current mouse pos
2139
2140 // We tweak the mouse position using the value from above, and then use that as the
2141 // start position to prevent the footprint from jumping when we start dragging.
2142 // First we move the visual cross hair cursor...
2143 controls()->ForceCursorPosition( true, tweakedMousePos );
2144 controls()->SetCursorPosition( tweakedMousePos ); // ...then the mouse pointer
2145
2146 // Now that the mouse is in the right position, get a copy of the position to use later
2147 p = controls()->GetCursorPosition();
2148 }
2149
2150 int dragMode = aEvent.Parameter<int64_t> ();
2151
2152 bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
2153
2154 if( !dragStarted )
2155 {
2156 if( wasLocked )
2157 item->SetLocked( true );
2158
2159 return 0;
2160 }
2161
2162 m_gridHelper->SetAuxAxes( true, p );
2163 controls()->ShowCursor( true );
2164 controls()->SetAutoPan( true );
2165 frame()->UndoRedoBlock( true );
2166
2167 view()->ClearPreview();
2168 view()->InitPreview();
2169
2170 auto setCursor =
2171 [&]()
2172 {
2174 };
2175
2176 // Set initial cursor
2177 setCursor();
2178
2179 // Set the initial visible area
2180 BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
2181 m_router->SetVisibleViewArea( BOX2I( viewAreaD.GetOrigin(), viewAreaD.GetSize() ) );
2182
2183 // Send an initial movement to prime the collision detection
2184 m_router->Move( p, nullptr );
2185
2186 bool hasMouseMoved = false;
2187
2188 while( TOOL_EVENT* evt = Wait() )
2189 {
2190 setCursor();
2191
2192 if( evt->IsCancelInteractive() )
2193 {
2194 if( wasLocked )
2195 item->SetLocked( true );
2196
2197 break;
2198 }
2199 else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
2200 {
2201 hasMouseMoved = true;
2202 updateEndItem( *evt );
2204
2205 if( footprint )
2206 {
2207 VECTOR2I offset = m_endSnapPoint - p;
2208 BOARD_ITEM* previewItem;
2209
2210 VECTOR2I fp_offset( offset );
2211 RotatePoint( fp_offset, -footprint->GetOrientation() );
2212
2213 view()->ClearPreview();
2214
2215 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2216 {
2217 previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() );
2218
2219 if( drawing->Type() == PCB_FP_SHAPE_T )
2220 {
2221 FP_SHAPE* shape = static_cast<FP_SHAPE*>( previewItem );
2222 shape->FP_SHAPE::Move( fp_offset );
2223 }
2224 else
2225 {
2226 previewItem->Move( offset );
2227 }
2228
2229 view()->AddToPreview( previewItem );
2230 view()->Hide( drawing, true );
2231 }
2232
2233 for( PAD* pad : footprint->Pads() )
2234 {
2235 if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none()
2236 && pad->GetDrillSize().x == 0 )
2237 {
2238 previewItem = static_cast<BOARD_ITEM*>( pad->Clone() );
2239 previewItem->Move( offset );
2240
2241 view()->AddToPreview( previewItem );
2242 }
2243 else
2244 {
2245 // Pads with copper or holes are handled by the router
2246 }
2247
2248 view()->Hide( pad, true );
2249 }
2250
2251 previewItem = static_cast<BOARD_ITEM*>( footprint->Reference().Clone() );
2252 previewItem->Move( offset );
2253 view()->AddToPreview( previewItem );
2254 view()->Hide( &footprint->Reference() );
2255
2256 previewItem = static_cast<BOARD_ITEM*>( footprint->Value().Clone() );
2257 previewItem->Move( offset );
2258 view()->AddToPreview( previewItem );
2259 view()->Hide( &footprint->Value() );
2260
2261 for( ZONE* zone : footprint->Zones() )
2262 {
2263 previewItem = static_cast<BOARD_ITEM*>( zone->Clone() );
2264 previewItem->Move( offset );
2265 view()->AddToPreview( previewItem );
2266 view()->Hide( zone, true );
2267 }
2268
2269 if( showCourtyardConflicts )
2270 {
2271 footprint->Move( offset );
2272 courtyardClearanceDRC.Run();
2273 courtyardClearanceDRC.UpdateConflicts( getView(), false );
2274 footprint->Move( -offset );
2275 }
2276
2277 // Update ratsnest
2278 dynamicData->Move( offset - lastOffset );
2279 lastOffset = offset;
2280 connectivityData->ComputeLocalRatsnest( dynamicItems, dynamicData.get(), offset );
2281 }
2282 }
2283 else if( hasMouseMoved && ( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
2284 {
2285 updateEndItem( *evt );
2287 break;
2288 }
2289 else if( evt->IsUndoRedo() )
2290 {
2291 // We're in an UndoRedoBlock. If we get here, something's broken.
2292 wxFAIL;
2293 break;
2294 }
2295 else if( evt->Category() == TC_COMMAND )
2296 {
2297 // TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
2298 // but we don't at present have that, so we just knock out some of the egregious ones.
2299 if( evt->IsAction( &ACTIONS::cut )
2300 || evt->IsAction( &ACTIONS::copy )
2301 || evt->IsAction( &ACTIONS::paste )
2302 || evt->IsAction( &ACTIONS::pasteSpecial )
2304 {
2305 wxBell();
2306 }
2307 // treat an undo as an escape
2308 else if( evt->IsAction( &ACTIONS::undo ) )
2309 {
2310 if( wasLocked )
2311 item->SetLocked( true );
2312
2313 break;
2314 }
2315 else
2316 {
2317 evt->SetPassEvent();
2318 }
2319 }
2320 else
2321 {
2322 evt->SetPassEvent();
2323 }
2324
2325 handleCommonEvents( *evt );
2326 }
2327
2328 if( footprint )
2329 {
2330 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2331 view()->Hide( drawing, false );
2332
2333 view()->Hide( &footprint->Reference(), false );
2334 view()->Hide( &footprint->Value(), false );
2335
2336 for( ZONE* zone : footprint->Zones() )
2337 view()->Hide( zone, false );
2338
2339 for( PAD* pad : footprint->Pads() )
2340 view()->Hide( pad, false );
2341
2342 view()->ClearPreview();
2343 view()->ShowPreview( false );
2344
2345 connectivityData->ClearLocalRatsnest();
2346 }
2347
2348 // Clear temporary COURTYARD_CONFLICT flag and ensure the conflict shadow is cleared
2349 courtyardClearanceDRC.ClearConflicts( getView() );
2350
2353
2354 m_gridHelper->SetAuxAxes( false );
2355 controls()->SetAutoPan( false );
2356 controls()->ForceCursorPosition( false );
2357 frame()->UndoRedoBlock( false );
2358 highlightNets( false );
2359
2360 return 0;
2361}
2362
2363
2365{
2366 const SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2367
2368 if( selection.Size() != 1 )
2369 return 0;
2370
2371 const BOARD_CONNECTED_ITEM* item =
2372 static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
2373
2374 if( item->Type() != PCB_TRACE_T )
2375 return 0;
2376
2378
2379 Activate();
2380
2382
2383 TOOL_MANAGER* toolManager = frame()->GetToolManager();
2384 GAL* gal = toolManager->GetView()->GetGAL();
2385
2387 m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
2388
2389 if( toolManager->IsContextMenuActive() )
2390 {
2391 // If we're here from a context menu then we need to get the position of the
2392 // cursor when the context menu was invoked. This is used to figure out the
2393 // break point on the track.
2395 }
2396 else
2397 {
2398 // If we're here from a hotkey, then get the current mouse position so we know
2399 // where to break the track.
2400 m_startSnapPoint = snapToItem( m_startItem, controls()->GetCursorPosition() );
2401 }
2402
2403 if( m_startItem && m_startItem->IsLocked() )
2404 {
2405 KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
2406 wxOK | wxCANCEL | wxICON_WARNING );
2407 dlg.SetOKLabel( _( "Break Track" ) );
2408 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
2409
2410 if( dlg.ShowModal() == wxID_CANCEL )
2411 return 0;
2412 }
2413
2414 frame()->UndoRedoBlock( true );
2415 breakTrack();
2416
2419
2420 frame()->UndoRedoBlock( false );
2421
2422 return 0;
2423}
2424
2425
2427{
2429 DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
2430
2431 if( sizeDlg.ShowModal() == wxID_OK )
2432 {
2433 bds.m_TempOverrideTrackWidth = true;
2434 bds.UseCustomTrackViaSize( true );
2435
2438 }
2439
2440 return 0;
2441}
2442
2443
2445{
2447
2448 if( !m_router->GetCurrentNets().empty() )
2450
2451 m_router->UpdateSizes( sizes );
2452
2453 // Changing the track width can affect the placement, so call the
2454 // move routine without changing the destination
2455 // Update end item first to avoid moving to an invalid/missing item
2456 updateEndItem( aEvent );
2458
2460
2461 return 0;
2462}
2463
2464
2466{
2467 std::vector<MSG_PANEL_ITEM> items;
2468
2470 {
2473 std::vector<int> nets = m_router->GetCurrentNets();
2474 wxString description;
2475 wxString secondary;
2476
2478 {
2479 wxASSERT( nets.size() >= 2 );
2480
2481 NETINFO_ITEM* netA = board()->FindNet( nets[0] );
2482 NETINFO_ITEM* netB = board()->FindNet( nets[1] );
2483 wxASSERT( netA );
2484 wxASSERT( netB );
2485
2486 description = wxString::Format( _( "Routing Diff Pair: %s" ),
2487 netA->GetNetname() + wxT( ", " ) + netB->GetNetname() );
2488
2489 wxString netclass;
2490 NETCLASS* netclassA = netA->GetNetClass();
2491 NETCLASS* netclassB = netB->GetNetClass();
2492
2493 if( netclassA == netclassB )
2494 netclass = netclassA->GetName();
2495 else
2496 netclass = netclassA->GetName() + wxT( ", " ) + netclassB->GetName();
2497
2498 secondary = wxString::Format( _( "Resolved Netclass: %s" ),
2499 UnescapeString( netclass ) );
2500 }
2501 else if( !nets.empty() )
2502 {
2503 NETINFO_ITEM* net = board()->FindNet( nets[0] );
2504 wxASSERT( net );
2505
2506 description = wxString::Format( _( "Routing Track: %s" ),
2507 net->GetNetname() );
2508
2509 secondary = wxString::Format( _( "Resolved Netclass: %s" ),
2510 UnescapeString( net->GetNetClass()->GetName() ) );
2511 }
2512 else
2513 {
2514 description = _( "Routing Track" );
2515 secondary = _( "(no net)" );
2516 }
2517
2518 items.emplace_back( description, secondary );
2519
2520 wxString cornerMode;
2521
2523 {
2524 cornerMode = _( "Free-angle" );
2525 }
2526 else
2527 {
2528 switch( m_router->Settings().GetCornerMode() )
2529 {
2530 case DIRECTION_45::CORNER_MODE::MITERED_45: cornerMode = _( "45-degree" ); break;
2531 case DIRECTION_45::CORNER_MODE::ROUNDED_45: cornerMode = _( "45-degree rounded" ); break;
2532 case DIRECTION_45::CORNER_MODE::MITERED_90: cornerMode = _( "90-degree" ); break;
2533 case DIRECTION_45::CORNER_MODE::ROUNDED_90: cornerMode = _( "90-degree rounded" ); break;
2534 default: break;
2535 }
2536 }
2537
2538 items.emplace_back( _( "Corner Style" ), cornerMode );
2539
2540#define FORMAT_VALUE( x ) frame()->MessageTextFromValue( x )
2541
2543 {
2544 items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2545 FORMAT_VALUE( sizes.DiffPairWidth() ) ),
2546 wxString::Format( _( "(from %s)" ),
2547 sizes.GetDiffPairWidthSource() ) );
2548
2549 items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2550 FORMAT_VALUE( sizes.Clearance() ) ),
2551 wxString::Format( _( "(from %s)" ),
2552 sizes.GetClearanceSource() ) );
2553
2554 items.emplace_back( wxString::Format( _( "Diff Pair Gap: %s" ),
2555 FORMAT_VALUE( sizes.DiffPairGap() ) ),
2556 wxString::Format( _( "(from %s)" ),
2557 sizes.GetDiffPairGapSource() ) );
2558 }
2559 else
2560 {
2561 items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2562 FORMAT_VALUE( sizes.TrackWidth() ) ),
2563 wxString::Format( _( "(from %s)" ),
2564 sizes.GetWidthSource() ) );
2565
2566 items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2567 FORMAT_VALUE( sizes.Clearance() ) ),
2568 wxString::Format( _( "(from %s)" ),
2569 sizes.GetClearanceSource() ) );
2570 }
2571
2572#undef FORMAT_VALUE
2573
2574 frame()->SetMsgPanel( items );
2575 }
2576 else
2577 {
2578 frame()->SetMsgPanel( board() );
2579 return;
2580 }
2581}
2582
2583
2585{
2587
2601
2608
2643
2646}
#define LEGACY_HK_NAME(x)
Definition: actions.h:32
@ select_w_layer
@ width_track_via
@ change_entry_orient
@ switch_corner_rounding_shape
@ via_microvia
#define APPEND_UNDO
Definition: board_commit.h:40
BOX2< VECTOR2I > BOX2I
Definition: box2.h:847
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 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,...
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
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:70
virtual void SetLocked(bool aLocked)
Definition: board_item.h:266
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition: board_item.h:278
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:226
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:43
virtual bool IsLocked() const
Definition: board_item.cpp:71
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1478
PROJECT * GetProject() const
Definition: board.h:446
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:430
const Vec & GetOrigin() const
Definition: box2.h:183
const Vec & GetSize() const
Definition: box2.h:179
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.
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
Update the board display after modifying it by a python script (note: it is automatically called by a...
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
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:181
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
PADS & Pads()
Definition: footprint.h:170
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:1558
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:567
FP_ZONES & Zones()
Definition: footprint.h:176
VECTOR2I GetPosition() const override
Definition: footprint.h:188
DRAWINGS & GraphicalItems()
Definition: footprint.h:173
FP_TEXT & Reference()
Definition: footprint.h:568
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: fp_text.cpp:343
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:270
void SetSnap(bool aSnap)
Definition: grid_helper.h:65
void SetUseGrid(bool aSnapToGrid)
Definition: grid_helper.h:68
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0))
Definition: grid_helper.cpp:75
const std::string FormatAsString() const
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:46
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:76
int ShowModal() override
Definition: confirm.cpp:120
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:1649
virtual int GetTopLayer() const
Definition: view.cpp:816
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1635
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:1550
void InitPreview()
Definition: view.cpp:1628
void ClearPreview()
Definition: view.cpp:1613
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:493
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
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
Definition: pad.h:60
bool m_ShowCourtyardCollisions
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:326
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:166
static TOOL_ACTION layerInner12
Definition: pcb_actions.h:302
static TOOL_ACTION routerUndoLastSegment
Definition: pcb_actions.h:222
static TOOL_ACTION layerInner8
Definition: pcb_actions.h:298
static TOOL_ACTION layerInner3
Definition: pcb_actions.h:293
static TOOL_ACTION layerPrev
Definition: pcb_actions.h:323
static TOOL_ACTION routerSettingsDialog
Activation of the Push and Shove settings dialogs.
Definition: pcb_actions.h:231
static TOOL_ACTION layerInner2
Definition: pcb_actions.h:292
static TOOL_ACTION routerAttemptFinish
Definition: pcb_actions.h:225
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:211
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:56
static TOOL_ACTION trackViaSizeChanged
Definition: pcb_actions.h:338
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:328
static TOOL_ACTION layerInner25
Definition: pcb_actions.h:315
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:164
static TOOL_ACTION routerRouteSelectedFromEnd
Definition: pcb_actions.h:227
static TOOL_ACTION routerHighlightMode
Actions to enable switching modes via hotkey assignments.
Definition: pcb_actions.h:236
static TOOL_ACTION routerWalkaroundMode
Definition: pcb_actions.h:238
static TOOL_ACTION routerShoveMode
Definition: pcb_actions.h:237
static TOOL_ACTION layerInner24
Definition: pcb_actions.h:314
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:149
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION layerInner29
Definition: pcb_actions.h:319
static TOOL_ACTION routerAutorouteSelected
Definition: pcb_actions.h:228
static TOOL_ACTION layerInner11
Definition: pcb_actions.h:301
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:232
static TOOL_ACTION routerContinueFromEnd
Definition: pcb_actions.h:224
static TOOL_ACTION layerInner16
Definition: pcb_actions.h:306
static TOOL_ACTION layerInner26
Definition: pcb_actions.h:316
static TOOL_ACTION layerInner18
Definition: pcb_actions.h:308
static TOOL_ACTION layerInner14
Definition: pcb_actions.h:304
static TOOL_ACTION selectLayerPair
Definition: pcb_actions.h:161
static TOOL_ACTION layerInner6
Definition: pcb_actions.h:296
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:167
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:496
static TOOL_ACTION layerInner22
Definition: pcb_actions.h:312
static TOOL_ACTION layerInner5
Definition: pcb_actions.h:295
static TOOL_ACTION layerInner20
Definition: pcb_actions.h:310
static TOOL_ACTION layerInner7
Definition: pcb_actions.h:297
static TOOL_ACTION layerInner27
Definition: pcb_actions.h:317
static TOOL_ACTION layerInner1
Definition: pcb_actions.h:291
static TOOL_ACTION layerInner10
Definition: pcb_actions.h:300
static TOOL_ACTION layerInner15
Definition: pcb_actions.h:305
static TOOL_ACTION layerInner17
Definition: pcb_actions.h:307
static TOOL_ACTION layerBottom
Definition: pcb_actions.h:321
static TOOL_ACTION layerInner19
Definition: pcb_actions.h:309
static TOOL_ACTION layerInner9
Definition: pcb_actions.h:299
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:242
static TOOL_ACTION layerInner30
Definition: pcb_actions.h:320
static TOOL_ACTION layerTop
Definition: pcb_actions.h:290
static TOOL_ACTION cycleRouterMode
Definition: pcb_actions.h:239
static TOOL_ACTION layerInner4
Definition: pcb_actions.h:294
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:208
static TOOL_ACTION layerInner13
Definition: pcb_actions.h:303
static TOOL_ACTION layerInner21
Definition: pcb_actions.h:311
static TOOL_ACTION layerNext
Definition: pcb_actions.h:322
static TOOL_ACTION routerRouteSelected
Definition: pcb_actions.h:226
static TOOL_ACTION layerInner23
Definition: pcb_actions.h:313
static TOOL_ACTION layerInner28
Definition: pcb_actions.h:318
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:274
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.
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
Definition: pcb_plugin.h:261
void Save(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:271
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
const VECTOR2I & GetStart() const
Definition: pcb_track.h:114
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:111
EDA_ITEM_FLAGS IsPointOnEnds(const VECTOR2I &point, int min_dist=0) const
Function IsPointOnEnds returns STARTPOINT if point if near (dist = min_dist) start point,...
Definition: pcb_track.cpp:236
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_layer contains the top layer, the other layer is in m_bottomLayer.
Definition: pcb_track.cpp:550
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:395
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
Base class for PNS router board items.
Definition: pns_item.h:56
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:132
@ SEGMENT_T
Definition: pns_item.h:66
const LAYER_RANGE & Layers() const
Definition: pns_item.h:156
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
Definition: pns_item.h:140
int Net() const
Definition: pns_item.h:154
bool IsLocked() const
Definition: pns_item.h:229
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
Definition: pns_node.cpp:1638
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:954
void StopRouting()
Definition: pns_router.cpp:911
void ClearViewDecorations()
Definition: pns_router.cpp:939
void ToggleCornerMode()
PLACEMENT_ALGO * Placer()
Definition: pns_router.h:213
void ClearWorld()
Definition: pns_router.cpp:102
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:728
LOGGER * Logger()
ROUTER_MODE Mode() const
Definition: pns_router.h:133
void UndoLastSegment()
Definition: pns_router.cpp:892
const std::vector< int > GetCurrentNets() const
Definition: pns_router.cpp:978
void CommitRouting()
Definition: pns_router.cpp:902
bool Finish()
Definition: pns_router.cpp:525
void SyncWorld()
Definition: pns_router.cpp:92
bool ContinueFromEnd()
Definition: pns_router.cpp:566
const wxString & FailureReason() const
Definition: pns_router.h:211
bool IsPlacingVia() const
void FlipPosture()
Definition: pns_router.cpp:945
RULE_RESOLVER * GetRuleResolver() const
Definition: pns_router.h:177
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:189
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:866
bool RoutingInProgress() const
Definition: pns_router.cpp:114
RouterState GetState() const
Definition: pns_router.h:135
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:151
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:392
void SetVisibleViewArea(const BOX2I &aExtents)
Definition: pns_router.h:217
int GetCurrentLayer() const
Definition: pns_router.cpp:989
void GetUpdatedItems(std::vector< PNS::ITEM * > &aRemoved, std::vector< PNS::ITEM * > &aAdded, std::vector< PNS::ITEM * > &aHeads)
Definition: pns_router.cpp:778
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:208
void ToggleViaPlacement()
Definition: pns_router.cpp:963
NODE * GetWorld() const
Definition: pns_router.h:161
bool Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:461
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 int DpCoupledNet(int 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)
virtual void highlightNets(bool aEnabled, std::set< int > aNetcodes={})
const VECTOR2I snapToItem(ITEM *aSnapToItem, const VECTOR2I &aP)
SIZES_SETTINGS m_savedSizes
Definition: pns_tool_base.h:69
PNS_KICAD_IFACE * m_iface
Definition: pns_tool_base.h:78
ITEM * m_startItem
Definition: pns_tool_base.h:70
virtual void updateEndItem(const TOOL_EVENT &aEvent)
ROUTER * m_router
Definition: pns_tool_base.h:79
VECTOR2I m_endSnapPoint
Definition: pns_tool_base.h:75
PCB_GRID_HELPER * m_gridHelper
Definition: pns_tool_base.h:77
VECTOR2I m_startSnapPoint
Definition: pns_tool_base.h:71
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, int 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)
Container for project specific data.
Definition: project.h:64
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:149
Describe ratsnest for a single net.
Definition: ratsnest_data.h:63
const std::vector< CN_EDGE > & GetEdges() const
Definition: ratsnest_data.h:85
int onViaCommand(const TOOL_EVENT &aEvent)
int InlineDrag(const TOOL_EVENT &aEvent)
std::shared_ptr< ACTION_MENU > m_trackViaMenu
Definition: router_tool.h:92
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)
PNS::PNS_MODE GetRouterMode()
void saveRouterDebugLog()
void performDragging(int aMode=PNS::DM_ANY)
PCB_LAYER_ID m_originalActiveLayer
Definition: router_tool.h:95
int onLayerCommand(const TOOL_EVENT &aEvent)
int CycleRouterMode(const TOOL_EVENT &aEvent)
bool m_inRouterTool
Definition: router_tool.h:97
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.
static void NeighboringSegmentFilter(const VECTOR2I &aPt, GENERAL_COLLECTOR &aCollector)
bool finishInteractive()
int ChangeRouterMode(const TOOL_EVENT &aEvent)
std::shared_ptr< ACTION_MENU > m_diffPairMenu
Definition: router_tool.h:91
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)
void updateSizesAfterLayerSwitch(PCB_LAYER_ID targetLayer)
int DpDimensionsDialog(const TOOL_EVENT &aEvent)
int m_lastTargetLayer
Definition: router_tool.h:94
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:326
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
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:153
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:54
Represent a single user action.
Definition: tool_action.h:68
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
Definition: tool_action.cpp:72
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:215
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:156
bool HasPosition() const
Definition: tool_event.h:243
bool DisableGridSnapping() const
Definition: tool_event.h:344
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:442
int KeyCode() const
Definition: tool_event.h:349
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition: tool_event.h:365
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:266
bool IsKeyPressed() const
Definition: tool_event.h:354
TOOL_EVENT_CATEGORY Category() const
Returns more specific information about the type of an event.
Definition: tool_event.h:230
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:339
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
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:239
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:55
VECTOR2D GetMenuCursorPos() const
Definition: tool_manager.h:442
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
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 IsContextMenuActive() const
True while processing a context menu.
Definition: tool_manager.h:413
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:285
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:128
static bool IsZoneFillAction(const TOOL_EVENT *aEvent)
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
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:273
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 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:827
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ In22_Cu
Definition: layer_ids.h:86
@ In11_Cu
Definition: layer_ids.h:75
@ In29_Cu
Definition: layer_ids.h:93
@ In30_Cu
Definition: layer_ids.h:94
@ In17_Cu
Definition: layer_ids.h:81
@ In9_Cu
Definition: layer_ids.h:73
@ In19_Cu
Definition: layer_ids.h:83
@ In7_Cu
Definition: layer_ids.h:71
@ In28_Cu
Definition: layer_ids.h:92
@ In26_Cu
Definition: layer_ids.h:90
@ B_Cu
Definition: layer_ids.h:95
@ In21_Cu
Definition: layer_ids.h:85
@ In23_Cu
Definition: layer_ids.h:87
@ In15_Cu
Definition: layer_ids.h:79
@ In2_Cu
Definition: layer_ids.h:66
@ In10_Cu
Definition: layer_ids.h:74
@ In4_Cu
Definition: layer_ids.h:68
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ In16_Cu
Definition: layer_ids.h:80
@ In24_Cu
Definition: layer_ids.h:88
@ In1_Cu
Definition: layer_ids.h:65
@ In13_Cu
Definition: layer_ids.h:77
@ In8_Cu
Definition: layer_ids.h:72
@ In14_Cu
Definition: layer_ids.h:78
@ In12_Cu
Definition: layer_ids.h:76
@ In27_Cu
Definition: layer_ids.h:91
@ In6_Cu
Definition: layer_ids.h:70
@ In5_Cu
Definition: layer_ids.h:69
@ In3_Cu
Definition: layer_ids.h:67
@ In20_Cu
Definition: layer_ids.h:84
@ F_Cu
Definition: layer_ids.h:64
@ In18_Cu
Definition: layer_ids.h:82
@ In25_Cu
Definition: layer_ids.h:89
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:246
PNS_MODE
< Routing modes
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
@ RM_Shove
Only shove.
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
VIATYPE
Definition: pcb_track.h:65
@ BLIND_BURIED
@ ID_POPUP_PCB_SELECT_WIDTH1
Definition: pcbnew_id.h:29
@ ID_POPUP_PCB_SELECT_DIFFPAIR16
Definition: pcbnew_id.h:78
@ ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES
Definition: pcbnew_id.h:28
@ ID_POPUP_PCB_SELECT_WIDTH16
Definition: pcbnew_id.h:44
@ ID_POPUP_PCB_SELECT_AUTO_WIDTH
Definition: pcbnew_id.h:27
@ ID_POPUP_PCB_SELECT_CUSTOM_WIDTH
Definition: pcbnew_id.h:26
@ ID_POPUP_PCB_SELECT_DIFFPAIR1
Definition: pcbnew_id.h:63
@ ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR
Definition: pcbnew_id.h:62
@ ID_POPUP_PCB_SELECT_VIASIZE1
Definition: pcbnew_id.h:45
@ ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR
Definition: pcbnew_id.h:61
@ ID_POPUP_PCB_SELECT_VIASIZE16
Definition: pcbnew_id.h:60
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Class that computes missing connections on a PCB.
#define FORMAT_VALUE(x)
static const TOOL_ACTION ACT_SelLayerAndPlaceThroughVia("pcbnew.InteractiveRouter.SelLayerAndPlaceVia", AS_CONTEXT, '<', LEGACY_HK_NAME("Select Layer and Add Through Via"), _("Select Layer and Place Through Via..."), _("Select a layer, then add a through-hole via at the end of currently routed track."), BITMAPS::select_w_layer, AF_NONE,(void *)(VIA_ACTION_FLAGS::VIA|VIA_ACTION_FLAGS::SELECT_LAYER))
static VIATYPE getViaTypeFromFlags(int aFlags)
static const TOOL_ACTION ACT_SwitchCornerMode("pcbnew.InteractiveRouter.SwitchRounding", AS_CONTEXT, MD_CTRL+'/', "", _("Track Corner Mode"), _("Switches between sharp/rounded and 45°/90° corners when routing tracks."), BITMAPS::switch_corner_rounding_shape)
VIA_ACTION_FLAGS
Flags used by via tool actions.
Definition: router_tool.cpp:87
@ BLIND_VIA
blind/buried via
Definition: router_tool.cpp:91
@ SELECT_LAYER
Ask user to select layer before adding via.
Definition: router_tool.cpp:95
@ MICROVIA
Microvia.
Definition: router_tool.cpp:92
@ VIA_MASK
Definition: router_tool.cpp:89
@ VIA
Normal via.
Definition: router_tool.cpp:90
static const TOOL_ACTION ACT_EndTrack("pcbnew.InteractiveRouter.EndTrack", AS_CONTEXT, WXK_END, "", _("Finish Track"), _("Stops laying the current track."), BITMAPS::checked_ok)
static const TOOL_ACTION ACT_SelLayerAndPlaceMicroVia("pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia", AS_CONTEXT, 0, "", _("Select Layer and Place Micro Via..."), _("Select a layer, then add a micro via at the end of currently routed track."), BITMAPS::select_w_layer, AF_NONE,(void *)(VIA_ACTION_FLAGS::MICROVIA|VIA_ACTION_FLAGS::SELECT_LAYER))
static PCB_LAYER_ID getTargetLayerFromEvent(const TOOL_EVENT &aEvent)
static const TOOL_ACTION ACT_PlaceMicroVia("pcbnew.InteractiveRouter.PlaceMicroVia", AS_CONTEXT, MD_CTRL+ 'V', LEGACY_HK_NAME("Add MicroVia"), _("Place Microvia"), _("Adds a microvia at the end of currently routed track."), BITMAPS::via_microvia, AF_NONE,(void *) VIA_ACTION_FLAGS::MICROVIA)
static const TOOL_ACTION ACT_PlaceThroughVia("pcbnew.InteractiveRouter.PlaceVia", AS_CONTEXT, 'V', LEGACY_HK_NAME("Add Through Via"), _("Place Through Via"), _("Adds a through-hole via at the end of currently routed track."), BITMAPS::via, AF_NONE,(void *) VIA_ACTION_FLAGS::VIA)
static const TOOL_ACTION ACT_SelLayerAndPlaceBlindVia("pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia", AS_CONTEXT, MD_ALT+'<', LEGACY_HK_NAME("Select Layer and Add Blind/Buried Via"), _("Select Layer and Place Blind/Buried Via..."), _("Select a layer, then add a blind or buried via at the end of currently routed track."), BITMAPS::select_w_layer, AF_NONE,(void *)(VIA_ACTION_FLAGS::BLIND_VIA|VIA_ACTION_FLAGS::SELECT_LAYER))
static const TOOL_ACTION ACT_SwitchPosture("pcbnew.InteractiveRouter.SwitchPosture", AS_CONTEXT, '/', LEGACY_HK_NAME("Switch Track Posture"), _("Switch Track Posture"), _("Switches posture of the currently routed track."), BITMAPS::change_entry_orient)
static const TOOL_ACTION ACT_PlaceBlindVia("pcbnew.InteractiveRouter.PlaceBlindVia", AS_CONTEXT, MD_ALT+MD_SHIFT+ 'V', LEGACY_HK_NAME("Add Blind/Buried Via"), _("Place Blind/Buried Via"), _("Adds a blind or buried via at the end of currently routed track."), BITMAPS::via_buried, AF_NONE,(void *) VIA_ACTION_FLAGS::BLIND_VIA)
static const TOOL_ACTION ACT_CustomTrackWidth("pcbnew.InteractiveRouter.CustomTrackViaSize", AS_CONTEXT, 'Q', LEGACY_HK_NAME("Custom Track/Via Size"), _("Custom Track/Via Size..."), _("Shows a dialog for changing the track width and via size."), BITMAPS::width_track)
#define _(s)
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:43
@ AF_NONE
Definition: tool_action.h:51
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:557
@ TA_MODEL_CHANGE
Definition: tool_event.h:116
@ TA_UNDO_REDO_PRE
Definition: tool_event.h:101
@ TA_UNDO_REDO_POST
Definition: tool_event.h:104
@ TC_COMMAND
Definition: tool_event.h:52
@ TC_MOUSE
Definition: tool_event.h:50
@ TC_VIEW
Definition: tool_event.h:54
@ MD_ALT
Definition: tool_event.h:140
@ MD_CTRL
Definition: tool_event.h:139
@ MD_SHIFT
Definition: tool_event.h:138
@ BUT_LEFT
Definition: tool_event.h:127
@ BUT_RIGHT
Definition: tool_event.h:128
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ 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:103
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101
wxPoint ToWxPoint(const VECTOR2I &aSize)
Definition: vector2wx.h:50