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-2021 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 using namespace std::placeholders;
28 #include <board.h>
29 #include <board_design_settings.h>
30 #include <board_item.h>
31 #include <footprint.h>
32 #include <fp_shape.h>
33 #include <pad.h>
34 #include <zone.h>
35 #include <pcb_edit_frame.h>
36 #include <pcbnew_id.h>
40 #include <widgets/infobar.h>
44 #include <confirm.h>
45 #include <bitmaps.h>
46 #include <tool/action_menu.h>
47 #include <tool/tool_manager.h>
48 #include <tool/tool_menu.h>
49 #include <tools/pcb_actions.h>
51 #include <tools/pcb_grid_helper.h>
52 
53 #include "router_tool.h"
54 #include "pns_segment.h"
55 #include "pns_router.h"
56 #include "pns_itemset.h"
57 #include "pns_logger.h"
58 
59 #include "pns_kicad_iface.h"
60 
62 
63 using namespace KIGFX;
64 
69 {
70  // Via type
71  VIA_MASK = 0x03,
72  VIA = 0x00,
73  BLIND_VIA = 0x01,
74  MICROVIA = 0x02,
75 
76  // Select layer
78 };
79 
80 
81 // Actions, being statically-defined, require specialized I18N handling. We continue to
82 // use the _() macro so that string harvesting by the I18N framework doesn't have to be
83 // specialized, but we don't translate on initialization and instead do it in the getters.
84 
85 #undef _
86 #define _(s) s
87 
88 static const TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack",
89  AS_CONTEXT,
90  WXK_END, "",
91  _( "Finish Track" ), _( "Stops laying the current track." ),
93 
94 static const TOOL_ACTION ACT_AutoEndRoute( "pcbnew.InteractiveRouter.AutoEndRoute",
95  AS_CONTEXT,
96  'F', "",
97  _( "Auto-finish Track" ), _( "Automatically finishes laying the current track." ) );
98 
99 static const TOOL_ACTION ACT_PlaceThroughVia( "pcbnew.InteractiveRouter.PlaceVia",
100  AS_CONTEXT,
101  'V', LEGACY_HK_NAME( "Add Through Via" ),
102  _( "Place Through Via" ),
103  _( "Adds a through-hole via at the end of currently routed track." ),
105 
106 static const TOOL_ACTION ACT_PlaceBlindVia( "pcbnew.InteractiveRouter.PlaceBlindVia",
107  AS_CONTEXT,
108  MD_ALT + MD_SHIFT + 'V', LEGACY_HK_NAME( "Add Blind/Buried Via" ),
109  _( "Place Blind/Buried Via" ),
110  _( "Adds a blind or buried via at the end of currently routed track."),
112 
113 static const TOOL_ACTION ACT_PlaceMicroVia( "pcbnew.InteractiveRouter.PlaceMicroVia",
114  AS_CONTEXT,
115  MD_CTRL + 'V', LEGACY_HK_NAME( "Add MicroVia" ),
116  _( "Place Microvia" ), _( "Adds a microvia at the end of currently routed track." ),
118 
120  "pcbnew.InteractiveRouter.SelLayerAndPlaceVia",
121  AS_CONTEXT,
122  '<', LEGACY_HK_NAME( "Select Layer and Add Through Via" ),
123  _( "Select Layer and Place Through Via..." ),
124  _( "Select a layer, then add a through-hole via at the end of currently routed track." ),
127 
129  "pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia",
130  AS_CONTEXT,
131  MD_ALT + '<', LEGACY_HK_NAME( "Select Layer and Add Blind/Buried Via" ),
132  _( "Select Layer and Place Blind/Buried Via..." ),
133  _( "Select a layer, then add a blind or buried via at the end of currently routed track." ),
136 
138  "pcbnew.InteractiveRouter.SelLayerAndPlaceMicroVia",
139  AS_CONTEXT,
140  0, "",
141  _( "Select Layer and Place Micro Via..." ),
142  _( "Select a layer, then add a micro via at the end of currently routed track." ),
145 
146 static const TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackViaSize",
147  AS_CONTEXT,
148  'Q', LEGACY_HK_NAME( "Custom Track/Via Size" ),
149  _( "Custom Track/Via Size..." ),
150  _( "Shows a dialog for changing the track width and via size." ),
152 
153 static const TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture",
154  AS_CONTEXT,
155  '/', LEGACY_HK_NAME( "Switch Track Posture" ),
156  _( "Switch Track Posture" ),
157  _( "Switches posture of the currently routed track." ),
159 
160 static const TOOL_ACTION ACT_SwitchCornerMode( "pcbnew.InteractiveRouter.SwitchRounding",
161  AS_CONTEXT,
162  MD_CTRL + '/', "",
163  _( "Track Corner Mode" ),
164  _( "Switches between sharp/rounded and 45°/90° corners when routing tracks." ),
166 
167 #undef _
168 #define _(s) wxGetTranslation((s))
169 
170 
172  TOOL_BASE( "pcbnew.InteractiveRouter" ),
173  m_lastTargetLayer( UNDEFINED_LAYER )
174 {
175 }
176 
177 
179 {
180 public:
182  ACTION_MENU( true ),
183  m_frame( aFrame )
184  {
186  SetTitle( _( "Select Track/Via Width" ) );
187  }
188 
189 protected:
190  ACTION_MENU* create() const override
191  {
192  return new TRACK_WIDTH_MENU( m_frame );
193  }
194 
195  void update() override
196  {
197  EDA_UNITS units = m_frame.GetUserUnits();
199  bool useIndex = !bds.m_UseConnectedTrackWidth &&
200  !bds.UseCustomTrackViaSize();
201  wxString msg;
202 
203  Clear();
204 
205  Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
206  _( "Route using the width of the starting track." ), wxITEM_CHECK );
209 
210  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
211  _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
213  useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
214 
215  Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
216  _( "Specify custom track and via sizes" ), wxITEM_CHECK );
218 
219  AppendSeparator();
220 
221  // Append the list of tracks & via sizes
222  for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
223  {
224  int width = bds.m_TrackWidthList[i];
225 
226  if( i == 0 )
227  msg = _( "Track netclass width" );
228  else
229  msg.Printf( _( "Track %s" ), MessageTextFromValue( units, width ) );
230 
231  int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
232  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
233  Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
234  }
235 
236  AppendSeparator();
237 
238  for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
239  {
241 
242  if( i == 0 )
243  msg = _( "Via netclass values" );
244  else
245  {
246  if( via.m_Drill > 0 )
247  msg.Printf( _("Via %s, drill %s" ),
248  MessageTextFromValue( units, via.m_Diameter ),
249  MessageTextFromValue( units, via.m_Drill ) );
250  else
251  msg.Printf( _( "Via %s" ), MessageTextFromValue( units, via.m_Diameter ) );
252  }
253 
254  int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
255  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
256  Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
257  }
258  }
259 
260  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
261  {
263  int id = aEvent.GetId();
264 
265  // On Windows, this handler can be called with an event ID not existing in any
266  // menuitem, so only set flags when we have an ID match.
267 
269  {
270  bds.UseCustomTrackViaSize( true );
271  bds.m_TempOverrideTrackWidth = true;
273  }
274  else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
275  {
276  bds.UseCustomTrackViaSize( false );
277  bds.m_UseConnectedTrackWidth = true;
278  bds.m_TempOverrideTrackWidth = false;
279  }
281  {
282  bds.UseCustomTrackViaSize( false );
283  bds.m_UseConnectedTrackWidth = false;
284  bds.SetViaSizeIndex( 0 );
285  bds.SetTrackWidthIndex( 0 );
286  }
288  {
289  bds.UseCustomTrackViaSize( false );
291  }
293  {
294  bds.UseCustomTrackViaSize( false );
295  bds.m_TempOverrideTrackWidth = true;
297  }
298 
299  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
300  }
301 
302 private:
304 };
305 
306 
308 {
309 public:
311  ACTION_MENU( true ),
312  m_frame( aFrame )
313  {
315  SetTitle( _( "Select Differential Pair Dimensions" ) );
316  }
317 
318 protected:
319  ACTION_MENU* create() const override
320  {
321  return new DIFF_PAIR_MENU( m_frame );
322  }
323 
324  void update() override
325  {
326  EDA_UNITS units = m_frame.GetUserUnits();
328 
329  Clear();
330 
331  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
332  _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
334  !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
335 
336  Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
337  _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
339 
340  AppendSeparator();
341 
342  // Append the list of differential pair dimensions
343 
344  // Drop index 0 which is the current netclass dimensions (which are handled above)
345  for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
346  {
348  wxString msg;
349 
350  if( diffPair.m_Gap <= 0 )
351  {
352  if( diffPair.m_ViaGap <= 0 )
353  {
354  msg.Printf( _( "Width %s" ),
355  MessageTextFromValue( units, diffPair.m_Width ) );
356  }
357  else
358  {
359  msg.Printf( _( "Width %s, via gap %s" ),
360  MessageTextFromValue( units, diffPair.m_Width ),
361  MessageTextFromValue( units, diffPair.m_ViaGap ) );
362  }
363  }
364  else
365  {
366  if( diffPair.m_ViaGap <= 0 )
367  {
368  msg.Printf( _( "Width %s, gap %s" ),
369  MessageTextFromValue( units, diffPair.m_Width ),
370  MessageTextFromValue( units, diffPair.m_Gap ) );
371  }
372  else
373  {
374  msg.Printf( _( "Width %s, gap %s, via gap %s" ),
375  MessageTextFromValue( units, diffPair.m_Width ),
376  MessageTextFromValue( units, diffPair.m_Gap ),
377  MessageTextFromValue( units, diffPair.m_ViaGap ) );
378  }
379  }
380 
381  int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
382  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
383  Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
384  }
385  }
386 
387  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
388  {
390  int id = aEvent.GetId();
391 
392  // On Windows, this handler can be called with an event ID not existing in any
393  // menuitem, so only set flags when we have an ID match.
394 
396  {
397  bds.UseCustomDiffPairDimensions( true );
398  TOOL_MANAGER* toolManager = m_frame.GetToolManager();
399  toolManager->RunAction( PCB_ACTIONS::routerDiffPairDialog, true );
400  }
402  {
403  bds.UseCustomDiffPairDimensions( false );
404  bds.SetDiffPairIndex( 0 );
405  }
407  {
408  bds.UseCustomDiffPairDimensions( false );
409  // remember that the menu doesn't contain index 0 (which is the netclass values)
411  }
412 
413  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
414  }
415 
416 private:
418 };
419 
420 
422 {
423 }
424 
425 
427 {
429 
430  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
431 
432  wxASSERT( frame );
433 
434  auto& menu = m_menu.GetMenu();
435  menu.SetTitle( _( "Interactive Router" ) );
436 
437  m_trackViaMenu = std::make_shared<TRACK_WIDTH_MENU>( *frame );
438  m_trackViaMenu->SetTool( this );
440 
441  m_diffPairMenu = std::make_shared<DIFF_PAIR_MENU>( *frame );
442  m_diffPairMenu->SetTool( this );
444 
445  auto notRoutingCond =
446  [this]( const SELECTION& )
447  {
448  return !m_router->RoutingInProgress();
449  };
450 
452 
453  menu.AddSeparator();
454 
455  menu.AddItem( PCB_ACTIONS::routeSingleTrack, notRoutingCond );
456  menu.AddItem( PCB_ACTIONS::routeDiffPair, notRoutingCond );
459  menu.AddItem( PCB_ACTIONS::breakTrack, notRoutingCond );
460 
461  menu.AddItem( PCB_ACTIONS::drag45Degree, notRoutingCond );
462  menu.AddItem( PCB_ACTIONS::dragFreeAngle, notRoutingCond );
463 
464 // Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry.
473 
474  menu.AddSeparator();
475 
476  auto diffPairCond =
477  [this]( const SELECTION& )
478  {
480  };
481 
482  menu.AddMenu( m_trackViaMenu.get(), SELECTION_CONDITIONS::ShowAlways );
483  menu.AddMenu( m_diffPairMenu.get(), diffPairCond );
484 
486 
487  menu.AddSeparator();
488 
490 
491  return true;
492 }
493 
494 
496 {
498 
499  if( aReason == RUN )
500  TOOL_BASE::Reset( aReason );
501 }
502 
503 // Saves the complete event log and the dump of the PCB, allowing us to
504 // recreate hard-to-find P&S quirks and bugs.
505 
507 {
508  auto logger = m_router->Logger();
509 
510  if( ! logger )
511  return;
512 
513  wxString cwd = wxGetCwd();
514 
515  wxFileName fname_log( cwd );
516  fname_log.SetName( "pns.log" );
517 
518  wxFileName fname_dump( cwd );
519  fname_dump.SetName( "pns.dump" );
520 
521  wxString msg = wxString::Format( _( "Event file: %s\nBoard dump: %s" ), fname_log.GetFullPath(), fname_log.GetFullPath() );
522 
523  int rv = OKOrCancelDialog( nullptr, _("Save router log"), _("Would you like to save the router\nevent log for debugging purposes?"), msg, _("OK"), _("Cancel") );
524 
525  if( !rv )
526  return;
527 
528  FILE *f = fopen( fname_log.GetFullPath().c_str(), "wb" );
529 
530  // save base router configuration (mode, etc.)
531  fprintf(f, "config %d %d %d %d\n",
532  m_router->Settings().Mode(),
533  m_router->Settings().RemoveLoops() ? 1 : 0,
534  m_router->Settings().GetFixAllSegments() ? 1 : 0,
535  static_cast<int>( m_router->Settings().GetCornerMode() )
536  );
537 
538  const auto& events = logger->GetEvents();
539 
540  for( auto evt : events)
541  {
542  fprintf( f, "event %d %d %d %s\n", evt.p.x, evt.p.y, evt.type,
543  static_cast<const char*>( evt.uuid.AsString().c_str() ) );
544  }
545 
546  fclose( f );
547 
548  // Export as *.kicad_pcb format, using a strategy which is specifically chosen
549  // as an example on how it could also be used to send it to the system clipboard.
550 
551  PCB_PLUGIN pcb_io;
552 
553  pcb_io.Save( fname_dump.GetFullPath(), m_iface->GetBoard(), nullptr );
554 }
555 
556 
558 {
559  if( aEvent.Category() == TC_VIEW || aEvent.Category() == TC_MOUSE )
560  {
561  BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
562  m_router->SetVisibleViewArea( BOX2I( viewAreaD.GetOrigin(), viewAreaD.GetSize() ) );
563  }
564 
565  if( !aEvent.IsKeyPressed() )
566  return;
567 
568  switch( aEvent.KeyCode() )
569  {
570  case '0':
572  return;
573 
575  aEvent.SetPassEvent( false );
576  break;
577  default:
578  break;
579  }
580 }
581 
582 
584 {
585  int tl = getView()->GetTopLayer();
586 
587  if( m_startItem )
588  {
589  const LAYER_RANGE& ls = m_startItem->Layers();
590 
591  if( ls.Overlaps( tl ) )
592  return tl;
593  else
594  return ls.Start();
595  }
596 
597  return tl;
598 }
599 
600 
602 {
603  int al = frame()->GetActiveLayer();
604  int cl = m_router->GetCurrentLayer();
605 
606  if( cl != al )
607  {
608  m_router->SwitchLayer( al );
609  }
610 
611  OPT<int> newLayer = m_router->Sizes().PairedLayer( cl );
612 
613  if( !newLayer )
614  newLayer = m_router->Sizes().GetLayerTop();
615 
616  m_router->SwitchLayer( *newLayer );
617  m_lastTargetLayer = *newLayer;
618 }
619 
620 
621 static VIATYPE getViaTypeFromFlags( int aFlags )
622 {
623  switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
624  {
626  return VIATYPE::THROUGH;
628  return VIATYPE::BLIND_BURIED;
630  return VIATYPE::MICROVIA;
631  default:
632  wxASSERT_MSG( false, wxT( "Unhandled via type" ) );
633  return VIATYPE::THROUGH;
634  }
635 }
636 
637 
639 {
640  if( aEvent.IsAction( &PCB_ACTIONS::layerTop ) )
641  return F_Cu;
642  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner1 ) )
643  return In1_Cu;
644  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner2 ) )
645  return In2_Cu;
646  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner3 ) )
647  return In3_Cu;
648  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner4 ) )
649  return In4_Cu;
650  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner5 ) )
651  return In5_Cu;
652  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner6 ) )
653  return In6_Cu;
654  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner7 ) )
655  return In7_Cu;
656  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner8 ) )
657  return In8_Cu;
658  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner9 ) )
659  return In9_Cu;
660  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner10 ) )
661  return In10_Cu;
662  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner11 ) )
663  return In11_Cu;
664  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner12 ) )
665  return In12_Cu;
666  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner13 ) )
667  return In13_Cu;
668  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner14 ) )
669  return In14_Cu;
670  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner15 ) )
671  return In15_Cu;
672  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner16 ) )
673  return In16_Cu;
674  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner17 ) )
675  return In17_Cu;
676  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner18 ) )
677  return In18_Cu;
678  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner19 ) )
679  return In19_Cu;
680  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner20 ) )
681  return In20_Cu;
682  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner21 ) )
683  return In21_Cu;
684  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner22 ) )
685  return In22_Cu;
686  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner23 ) )
687  return In23_Cu;
688  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner24 ) )
689  return In24_Cu;
690  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner25 ) )
691  return In25_Cu;
692  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner26 ) )
693  return In26_Cu;
694  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner27 ) )
695  return In27_Cu;
696  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner28 ) )
697  return In28_Cu;
698  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner29 ) )
699  return In29_Cu;
700  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner30 ) )
701  return In30_Cu;
702  else if( aEvent.IsAction( &PCB_ACTIONS::layerBottom ) )
703  return B_Cu;
704  else
705  return UNDEFINED_LAYER;
706 }
707 
708 
710 {
711  return handleLayerSwitch( aEvent, false );
712 }
713 
714 
716 {
717  return handleLayerSwitch( aEvent, true );
718 }
719 
720 
721 int ROUTER_TOOL::handleLayerSwitch( const TOOL_EVENT& aEvent, bool aForceVia )
722 {
723  wxCHECK( m_router, 0 );
724 
725  if( !IsToolActive() )
726  return 0;
727 
728  // First see if this is one of the switch layer commands
729  LSEQ layers = LSET( board()->GetEnabledLayers() & LSET::AllCuMask() ).Seq();
731  PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
732 
733  if( aEvent.IsAction( &PCB_ACTIONS::layerNext ) )
734  {
736  m_lastTargetLayer = currentLayer;
737 
738  size_t idx = 0;
739 
740  for( size_t i = 0; i < layers.size(); i++ )
741  {
742  if( layers[i] == m_lastTargetLayer )
743  {
744  idx = i;
745  break;
746  }
747  }
748 
749  idx = ( idx + 1 ) % layers.size();
750  targetLayer = layers[idx];
751  }
752  else if( aEvent.IsAction( &PCB_ACTIONS::layerPrev ) )
753  {
755  m_lastTargetLayer = currentLayer;
756 
757  size_t idx = 0;
758 
759  for( size_t i = 0; i < layers.size(); i++ )
760  {
761  if( layers[i] == m_lastTargetLayer )
762  {
763  idx = i;
764  break;
765  }
766  }
767 
768  idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers.size() - 1 );
769  targetLayer = layers[idx];
770  }
771  else
772  {
773  targetLayer = getTargetLayerFromEvent( aEvent );
774  }
775 
776  if( targetLayer != UNDEFINED_LAYER )
777  {
778  m_lastTargetLayer = targetLayer;
779 
780  if( targetLayer == currentLayer )
781  return 0;
782 
783  if( !aForceVia && m_router && m_router->SwitchLayer( targetLayer ) )
784  {
785  updateEndItem( aEvent );
786  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
787  return 0;
788  }
789  }
790 
792  const int layerCount = bds.GetCopperLayerCount();
793 
796 
798 
799  VIATYPE viaType = VIATYPE::THROUGH;
800  bool selectLayer = false;
801 
802  // Otherwise it is one of the router-specific via commands
803  if( targetLayer == UNDEFINED_LAYER )
804  {
805  const int actViaFlags = aEvent.Parameter<intptr_t>();
806  selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
807 
808  viaType = getViaTypeFromFlags( actViaFlags );
809 
810  // ask the user for a target layer
811  if( selectLayer )
812  {
813  wxPoint endPoint = (wxPoint) view()->ToScreen( m_endSnapPoint );
814  endPoint = frame()->GetCanvas()->ClientToScreen( endPoint );
815 
816  // Build the list of not allowed layer for the target layer
817  LSET not_allowed_ly = LSET::AllNonCuMask();
818 
819  if( viaType != VIATYPE::THROUGH )
820  {
821  not_allowed_ly.set( currentLayer );
822  }
823 
824  if( viaType == VIATYPE::MICROVIA )
825  {
826  // Allows only the previous or the next layer from the current layer
827  int previous_layer = currentLayer == B_Cu ? layerCount - 2
828  : currentLayer - 1;
829 
830  int next_layer = currentLayer >= layerCount-2 ? B_Cu
831  : currentLayer + 1;
832 
833  not_allowed_ly = LSET::AllLayersMask();
834 
835  if( previous_layer >= F_Cu && previous_layer != currentLayer )
836  not_allowed_ly.reset( previous_layer );
837 
838  if( next_layer != currentLayer )
839  not_allowed_ly.reset( next_layer );
840  }
841 
842  targetLayer = frame()->SelectOneLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
843  not_allowed_ly, endPoint );
844 
845  // Reset the cursor to the end of the track
847 
848  if( targetLayer == UNDEFINED_LAYER ) // cancelled by user
849  return 0;
850 
851  // One cannot place a blind/buried via on only one layer:
852  if( viaType != VIATYPE::THROUGH )
853  {
854  if( currentLayer == targetLayer )
855  return 0;
856  }
857  }
858  }
859 
860  // fixme: P&S supports more than one fixed layer pair. Update the dialog?
861  sizes.ClearLayerPairs();
862 
863  if( !m_router->IsPlacingVia() )
864  {
865  // Cannot place microvias or blind vias if not allowed (obvious)
866  if( ( viaType == VIATYPE::BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
867  {
868  WX_INFOBAR* infobar = frame()->GetInfoBar();
869  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY,
870  _( "Show board setup" ),
871  wxEmptyString );
872 
873  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
874  [&]( wxHyperlinkEvent& aEvent )
875  {
876  getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Constraints" ) );
877  } ) );
878 
879  infobar->RemoveAllButtons();
880  infobar->AddButton( button );
881 
882  infobar->ShowMessageFor( _( "Blind/buried vias must first be enabled in "
883  "Board Setup > Design Rules > Constraints." ),
884  10000, wxICON_ERROR, WX_INFOBAR::MESSAGE_TYPE::DRC_VIOLATION );
885  return false;
886  }
887 
888  if( ( viaType == VIATYPE::MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
889  {
890  WX_INFOBAR* infobar = frame()->GetInfoBar();
891  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY,
892  _( "Show board setup" ), wxEmptyString );
893 
894  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
895  [&]( wxHyperlinkEvent& aEvent )
896  {
897  getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Constraints" ) );
898  } ) );
899 
900  infobar->RemoveAllButtons();
901  infobar->AddButton( button );
902 
903  infobar->ShowMessageFor( _( "Microvias must first be enabled in "
904  "Board Setup > Design Rules > Constraints." ),
905  10000, wxICON_ERROR, WX_INFOBAR::MESSAGE_TYPE::DRC_VIOLATION );
906  return false;
907  }
908  }
909 
910  // Convert blind/buried via to a through hole one, if it goes through all layers
911  if( viaType == VIATYPE::BLIND_BURIED
912  && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
913  || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
914  {
915  viaType = VIATYPE::THROUGH;
916  }
917 
918  if( targetLayer == UNDEFINED_LAYER )
919  {
920  // Implicic layer selection
921 
922  switch( viaType )
923  {
924  case VIATYPE::THROUGH:
925  // use the default layer pair
926  currentLayer = pairTop;
927  targetLayer = pairBottom;
928  break;
929 
930  case VIATYPE::MICROVIA:
931  // Try to use the layer pair preset, if the layers are adjacent,
932  // because a microvia is usually restricted to 2 adjacent copper layers
933  if( pairTop > pairBottom ) std::swap( pairTop, pairBottom );
934 
935  if( currentLayer == pairTop && pairBottom == pairTop+1 )
936  {
937  targetLayer = pairBottom;
938  }
939  else if( currentLayer == pairBottom && pairBottom == pairTop+1 )
940  {
941  targetLayer = pairTop;
942  }
943  else if( currentLayer == F_Cu || currentLayer == In1_Cu )
944  {
945  // front-side microvia
946  currentLayer = F_Cu;
947 
948  if( layerCount > 2 ) // Ensure the inner layer In1_Cu exists
949  targetLayer = In1_Cu;
950  else
951  targetLayer = B_Cu;
952  }
953  else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
954  {
955  // back-side microvia
956  currentLayer = B_Cu,
957  targetLayer = (PCB_LAYER_ID) ( layerCount - 2 );
958  }
959  else
960  {
961  // This is not optimal: from an internal layer one can want to switch
962  // to the previous or the next internal layer
963  // but at this point we do not know what the user want.
964  targetLayer = PCB_LAYER_ID( currentLayer + 1 );
965  }
966  break;
967 
969  if( currentLayer == pairTop || currentLayer == pairBottom )
970  {
971  // the current layer is on the defined layer pair,
972  // swap to the other side
973  currentLayer = pairTop;
974  targetLayer = pairBottom;
975  }
976  else
977  {
978  // the current layer is not part of the current layer pair,
979  // so fallback and swap to the top layer of the pair by default
980  targetLayer = pairTop;
981  }
982 
983  // Do not create a broken via (i.e. a via on only one copper layer)
984  if( currentLayer == targetLayer )
985  {
986  WX_INFOBAR* infobar = frame()->GetInfoBar();
987  infobar->ShowMessageFor( _( "Blind/buried via need 2 different layers." ),
988  2000, wxICON_ERROR,
990  return 0;
991  }
992 
993  break;
994 
995  default:
996  wxFAIL_MSG( wxT( "unexpected via type" ) );
997  return 0;
998  break;
999  }
1000  }
1001 
1002  sizes.SetViaDiameter( bds.m_ViasMinSize );
1003  sizes.SetViaDrill( bds.m_MinThroughDrill );
1004 
1005  if( bds.UseNetClassVia() || viaType == VIATYPE::MICROVIA )
1006  {
1007  PCB_VIA dummyVia( board() );
1008  dummyVia.SetViaType( viaType );
1009  dummyVia.SetLayerPair( currentLayer, targetLayer );
1010 
1011  if( !m_router->GetCurrentNets().empty() )
1012  dummyVia.SetNetCode( m_router->GetCurrentNets()[0] );
1013 
1014  DRC_CONSTRAINT constraint;
1015 
1016  constraint = bds.m_DRCEngine->EvalRules( VIA_DIAMETER_CONSTRAINT, &dummyVia, nullptr,
1017  currentLayer );
1018 
1019  if( !constraint.IsNull() )
1020  sizes.SetViaDiameter( constraint.m_Value.Opt() );
1021 
1022  constraint = bds.m_DRCEngine->EvalRules( HOLE_SIZE_CONSTRAINT, &dummyVia, nullptr,
1023  currentLayer );
1024 
1025  if( !constraint.IsNull() )
1026  sizes.SetViaDrill( constraint.m_Value.Opt() );
1027  }
1028  else
1029  {
1030  sizes.SetViaDiameter( bds.GetCurrentViaSize() );
1031  sizes.SetViaDrill( bds.GetCurrentViaDrill() );
1032  }
1033 
1034  sizes.SetViaType( viaType );
1035  sizes.AddLayerPair( currentLayer, targetLayer );
1036 
1037  m_router->UpdateSizes( sizes );
1038 
1039  if( !m_router->IsPlacingVia() )
1041 
1042  m_lastTargetLayer = targetLayer;
1043 
1044  if( m_router->RoutingInProgress() )
1045  {
1046  updateEndItem( aEvent );
1048  }
1049  else
1050  {
1051  updateStartItem( aEvent );
1052  }
1053 
1054  return 0;
1055 }
1056 
1057 
1059 {
1060  PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1061  int routingLayer = getStartLayer( m_startItem );
1062 
1063  if( !IsCopperLayer( routingLayer ) )
1064  {
1065  editFrame->ShowInfoBarError( _( "Tracks on Copper layers only." ) );
1066  return false;
1067  }
1068 
1069  editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
1070 
1071  if( !getView()->IsLayerVisible( routingLayer ) )
1072  {
1073  editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1074  editFrame->GetCanvas()->Refresh();
1075  }
1076 
1077  if( m_startItem && m_startItem->Net() > 0 )
1078  highlightNet( true, m_startItem->Net() );
1079 
1080  controls()->SetAutoPan( true );
1081 
1082  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
1083 
1084  m_iface->SetStartLayer( routingLayer );
1085 
1087  m_iface->ImportSizes( sizes, m_startItem, -1 );
1088  sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
1089  frame()->GetScreen()->m_Route_Layer_BOTTOM );
1090 
1091  m_router->UpdateSizes( sizes );
1092 
1093  if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
1094  {
1095  // It would make more sense to leave the net highlighted as the higher-contrast mode
1096  // makes the router clearances more visible. However, since we just started routing
1097  // the conversion of the screen from low contrast to high contrast is a bit jarring and
1098  // makes the infobar coming up less noticeable.
1099  highlightNet( false );
1100 
1102  [&]()
1103  {
1105  } );
1106 
1107  controls()->SetAutoPan( false );
1108  return false;
1109  }
1110 
1111  m_endItem = nullptr;
1113 
1115  frame()->UndoRedoBlock( true );
1116 
1117  return true;
1118 }
1119 
1120 
1122 {
1123  m_router->StopRouting();
1124 
1125  m_startItem = nullptr;
1126  m_endItem = nullptr;
1127 
1130  controls()->SetAutoPan( false );
1131  controls()->ForceCursorPosition( false );
1132  frame()->UndoRedoBlock( false );
1133  highlightNet( false );
1134 
1135  return true;
1136 }
1137 
1138 
1140 {
1142 
1143  if( !prepareInteractive() )
1144  return;
1145 
1146  auto setCursor =
1147  [&]()
1148  {
1150  };
1151 
1152  // Set initial cursor
1153  setCursor();
1154 
1155  while( TOOL_EVENT* evt = Wait() )
1156  {
1157  setCursor();
1158 
1159  // Don't crash if we missed an operation that canceled routing.
1160  if( !m_router->RoutingInProgress() )
1161  {
1162  if( evt->IsCancelInteractive() )
1163  m_cancelled = true;
1164 
1165  break;
1166  }
1167 
1168  handleCommonEvents( *evt );
1169 
1170  if( evt->IsMotion() )
1171  {
1172  updateEndItem( *evt );
1174  }
1175  else if( evt->IsAction( &PCB_ACTIONS::routerUndoLastSegment ) )
1176  {
1178  updateEndItem( *evt );
1180  }
1181  else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
1182  {
1183  updateEndItem( *evt );
1184  bool needLayerSwitch = m_router->IsPlacingVia();
1185  bool forceFinish = evt->Modifier( MD_SHIFT );
1186 
1187  if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) )
1188  {
1189  break;
1190  }
1191 
1192  if( needLayerSwitch )
1194 
1195  // Synchronize the indicated layer
1196  PCB_LAYER_ID routingLayer = ToLAYER_ID( m_router->GetCurrentLayer() );
1197  PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
1198 
1199  editFrame->SetActiveLayer( routingLayer );
1200 
1201  if( !getView()->IsLayerVisible( routingLayer ) )
1202  {
1203  editFrame->GetAppearancePanel()->SetLayerVisible( routingLayer, true );
1204  editFrame->GetCanvas()->Refresh();
1205  }
1206 
1207  updateEndItem( *evt );
1209  m_startItem = nullptr;
1210  }
1211  else if( evt->IsAction( &ACT_SwitchCornerMode ) )
1212  {
1215  updateEndItem( *evt );
1216  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1217  }
1218  else if( evt->IsAction( &ACT_SwitchPosture ) )
1219  {
1220  m_router->FlipPosture();
1221  updateEndItem( *evt );
1222  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1223  }
1224  else if( evt->IsAction( &PCB_ACTIONS::properties ) )
1225  {
1227  controls()->SetAutoPan( false );
1228  {
1230  }
1231  controls()->SetAutoPan( true );
1232  setCursor();
1234  }
1235  else if( evt->IsAction( &ACT_EndTrack ) || evt->IsDblClick( BUT_LEFT ) )
1236  {
1237  // Stop current routing:
1239  break;
1240  }
1241  else if( evt->IsCancelInteractive() || evt->IsActivate()
1242  || evt->IsUndoRedo()
1243  || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
1244  {
1245  if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
1246  m_cancelled = true;
1247 
1248  if( evt->IsActivate() && !evt->IsMoveTool() )
1249  m_cancelled = true;
1250 
1251  break;
1252  }
1253  else if( evt->IsClick( BUT_RIGHT ) )
1254  {
1256  }
1257  else
1258  {
1259  evt->SetPassEvent();
1260  }
1261  }
1262 
1264 
1266 }
1267 
1268 
1270 {
1271  PNS::SIZES_SETTINGS sizes = m_router->Sizes();
1272  DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
1273 
1274  if( settingsDlg.ShowModal() == wxID_OK )
1275  {
1276  m_router->UpdateSizes( sizes );
1277  m_savedSizes = sizes;
1278 
1280  bds.SetCustomDiffPairWidth( sizes.DiffPairWidth() );
1281  bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
1282  bds.SetCustomDiffPairViaGap( sizes.DiffPairViaGap() );
1283  }
1284 
1285  return 0;
1286 }
1287 
1288 
1290 {
1291  DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
1292 
1293  settingsDlg.ShowModal();
1294 
1296 
1297  return 0;
1298 }
1299 
1300 
1302 {
1303  PNS::PNS_MODE mode = aEvent.Parameter<PNS::PNS_MODE>();
1304  PNS::ROUTING_SETTINGS& settings = m_router->Settings();
1305 
1306  settings.SetMode( mode );
1307 
1308  return 0;
1309 }
1310 
1311 
1313 {
1314  PNS::ROUTING_SETTINGS& settings = m_router->Settings();
1315  PNS::PNS_MODE mode = settings.Mode();
1316 
1317  switch( mode )
1318  {
1319  case PNS::RM_MarkObstacles: mode = PNS::RM_Shove; break;
1320  case PNS::RM_Shove: mode = PNS::RM_Walkaround; break;
1321  case PNS::RM_Walkaround: mode = PNS::RM_MarkObstacles; break;
1322  }
1323 
1324  settings.SetMode( mode );
1325 
1326  return 0;
1327 }
1328 
1329 
1331 {
1332  return m_router->Settings().Mode();
1333 }
1334 
1335 
1337 {
1338  return m_router->RoutingInProgress();
1339 }
1340 
1341 
1343 {
1346 }
1347 
1348 
1349 int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
1350 {
1351  PNS::ROUTER_MODE mode = aEvent.Parameter<PNS::ROUTER_MODE>();
1352  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1354 
1355  if( m_router->RoutingInProgress() )
1356  {
1357  if( m_router->Mode() == mode )
1358  return 0;
1359  else
1360  m_router->StopRouting();
1361  }
1362 
1363  // Deselect all items
1365 
1366  std::string tool = aEvent.GetCommandStr().get();
1367  frame->PushTool( tool );
1368 
1369  auto setCursor =
1370  [&]()
1371  {
1373  };
1374 
1375  Activate();
1376  // Must be done after Activate() so that it gets set into the correct context
1377  controls->ShowCursor( true );
1378  controls->ForceCursorPosition( false );
1379  // Set initial cursor
1380  setCursor();
1381 
1382  m_router->SetMode( mode );
1383  m_cancelled = false;
1384 
1385  // Prime the pump
1386  if( aEvent.HasPosition() )
1388 
1389  // Main loop: keep receiving events
1390  while( TOOL_EVENT* evt = Wait() )
1391  {
1392  if( !evt->IsDrag() )
1393  setCursor();
1394 
1395  if( evt->IsCancelInteractive() )
1396  {
1397  frame->PopTool( tool );
1398  break;
1399  }
1400  else if( evt->IsActivate() )
1401  {
1402  if( evt->IsMoveTool() )
1403  {
1404  // leave ourselves on the stack so we come back after the move
1405  break;
1406  }
1407  else
1408  {
1409  frame->PopTool( tool );
1410  break;
1411  }
1412  }
1413  else if( evt->Action() == TA_UNDO_REDO_PRE )
1414  {
1415  m_router->ClearWorld();
1416  }
1417  else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
1418  {
1419  m_router->SyncWorld();
1420  }
1421  else if( evt->IsMotion() )
1422  {
1423  updateStartItem( *evt );
1424  }
1425  else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
1426  {
1427  updateStartItem( *evt, true );
1429  }
1430  else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
1431  {
1432  updateStartItem( *evt, true );
1434  }
1435  else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
1436  {
1437  updateStartItem( *evt, true );
1438  breakTrack( );
1439  evt->SetPassEvent( false );
1440  }
1441  else if( evt->IsClick( BUT_LEFT )
1442  || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
1443  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
1444  {
1445  updateStartItem( *evt );
1446 
1447  if( evt->HasPosition() )
1448  {
1449  if( evt->Modifier( MD_SHIFT ) )
1451  else
1452  performRouting();
1453  }
1454  }
1455  else if( evt->IsAction( &ACT_PlaceThroughVia ) )
1456  {
1458  }
1459  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1460  {
1462  updateStartItem( *evt );
1463  }
1464  else if( evt->IsKeyPressed() )
1465  {
1466  // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
1467  // event so we need to process the wxEVT_CHAR event that will follow as long as we
1468  // pass the event.
1469  evt->SetPassEvent();
1470  }
1471  else if( evt->IsClick( BUT_RIGHT ) )
1472  {
1474  }
1475  else
1476  {
1477  evt->SetPassEvent();
1478  }
1479 
1480  if( m_cancelled )
1481  {
1482  frame->PopTool( tool );
1483  break;
1484  }
1485  }
1486 
1487  // Store routing settings till the next invocation
1490 
1491  return 0;
1492 }
1493 
1494 
1496 {
1498 
1499  VIEW_CONTROLS* ctls = getViewControls();
1500 
1501  if( m_startItem && m_startItem->IsLocked() )
1502  {
1503  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1504  wxOK | wxCANCEL | wxICON_WARNING );
1505  dlg.SetOKLabel( _( "Drag Anyway" ) );
1506  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1507 
1508  if( dlg.ShowModal() == wxID_CANCEL )
1509  return;
1510  }
1511 
1512  // We don't support dragging arcs inside the PNS right now
1514  {
1515  if( m_router->RoutingInProgress() )
1516  m_router->StopRouting();
1517 
1518  m_startItem = nullptr;
1519 
1520  m_gridHelper->SetAuxAxes( false );
1521  frame()->UndoRedoBlock( false );
1522  ctls->SetAutoPan( false );
1523  ctls->ForceCursorPosition( false );
1524  highlightNet( false );
1525 
1526  m_cancelled = true;
1527 
1529 
1530  return;
1531  }
1532 
1533  bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1534 
1535  if( !dragStarted )
1536  return;
1537 
1538  if( m_startItem && m_startItem->Net() > 0 )
1539  highlightNet( true, m_startItem->Net() );
1540 
1541  ctls->SetAutoPan( true );
1543  frame()->UndoRedoBlock( true );
1544 
1545  while( TOOL_EVENT* evt = Wait() )
1546  {
1547  ctls->ForceCursorPosition( false );
1548 
1549  if( evt->IsMotion() )
1550  {
1551  updateEndItem( *evt );
1553  }
1554  else if( evt->IsClick( BUT_LEFT ) )
1555  {
1557  break;
1558  }
1559  else if( evt->IsClick( BUT_RIGHT ) )
1560  {
1562  }
1563  else if( evt->IsCancelInteractive() || evt->IsActivate() || evt->IsUndoRedo() )
1564  {
1565  if( evt->IsCancelInteractive() && !m_startItem )
1566  m_cancelled = true;
1567 
1568  if( evt->IsActivate() && !evt->IsMoveTool() )
1569  m_cancelled = true;
1570 
1571  break;
1572  }
1573  else
1574  {
1575  evt->SetPassEvent();
1576  }
1577 
1578  handleCommonEvents( *evt );
1579  }
1580 
1581  if( m_router->RoutingInProgress() )
1582  m_router->StopRouting();
1583 
1584  m_startItem = nullptr;
1585 
1586  m_gridHelper->SetAuxAxes( false );
1587  frame()->UndoRedoBlock( false );
1588  ctls->SetAutoPan( false );
1589  ctls->ForceCursorPosition( false );
1590  highlightNet( false );
1591 }
1592 
1593 
1595 {
1596  /*
1597  * If the collection contains a trivial line corner (two connected segments)
1598  * or a non-fanout-via (a via with no more than two connected segments), then
1599  * trim the collection down to a single item (which one won't matter since
1600  * they're all connected).
1601  */
1602 
1603  // First make sure we've got something that *might* match.
1604  int vias = aCollector.CountType( PCB_VIA_T );
1605  int traces = aCollector.CountType( PCB_TRACE_T );
1606  int arcs = aCollector.CountType( PCB_ARC_T );
1607 
1608  if( arcs > 0 || vias > 1 || traces > 2 || vias + traces < 1 )
1609  return;
1610 
1611  // Fetch first PCB_TRACK (via or trace) as our reference
1612  PCB_TRACK* reference = nullptr;
1613 
1614  for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
1615  reference = dynamic_cast<PCB_TRACK*>( aCollector[i] );
1616 
1617  int refNet = reference->GetNetCode();
1618 
1619  wxPoint refPoint( aPt.x, aPt.y );
1620  EDA_ITEM_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
1621 
1622  if( flags & STARTPOINT )
1623  refPoint = reference->GetStart();
1624  else if( flags & ENDPOINT )
1625  refPoint = reference->GetEnd();
1626 
1627  // Check all items to ensure that any TRACKs are co-terminus with the reference and on
1628  // the same net.
1629  for( int i = 0; i < aCollector.GetCount(); i++ )
1630  {
1631  PCB_TRACK* neighbor = dynamic_cast<PCB_TRACK*>( aCollector[i] );
1632 
1633  if( neighbor && neighbor != reference )
1634  {
1635  if( neighbor->GetNetCode() != refNet )
1636  return;
1637 
1638  if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
1639  return;
1640  }
1641  }
1642 
1643  // Selection meets criteria; trim it to the reference item.
1644  aCollector.Empty();
1645  aCollector.Append( reference );
1646 }
1647 
1648 
1649 bool ROUTER_TOOL::CanInlineDrag( int aDragMode )
1650 {
1652  const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1653 
1654  if( selection.Size() == 1 )
1655  {
1656  const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
1657 
1658  // Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using
1659  // DragArcTrack(), so PCB_ARC_T should never occur here.
1661  {
1662  static const KICAD_T footprints[] = { PCB_FOOTPRINT_T, EOT };
1663 
1664  // Footprints cannot be dragged freely.
1665  if( item->IsType( footprints ) )
1666  return !( aDragMode & PNS::DM_FREE_ANGLE );
1667  else
1668  return true;
1669  }
1670  }
1671 
1672  return false;
1673 }
1674 
1675 
1677 {
1678  const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1679 
1680  if( selection.Empty() )
1682 
1683  if( selection.Size() != 1 )
1684  return 0;
1685 
1686  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
1687 
1688  if( item->Type() != PCB_TRACE_T
1689  && item->Type() != PCB_VIA_T
1690  && item->Type() != PCB_FOOTPRINT_T )
1691  {
1692  return 0;
1693  }
1694 
1695  // If we overrode locks, we want to clear the flag from the source item before SyncWorld is
1696  // called so that virtual vias are not generated for the (now unlocked) track segment. Note in
1697  // this case the lock can't be reliably re-applied, because there is no guarantee that the end
1698  // state of the drag results in the same number of segments so it's not clear which segment to
1699  // apply the lock state to.
1700  bool wasLocked = false;
1701 
1702  if( item->IsLocked() )
1703  {
1704  wasLocked = true;
1705  item->SetLocked( false );
1706  }
1707 
1708  Activate();
1709 
1711  m_router->SyncWorld();
1712  m_startItem = nullptr;
1713 
1714  PNS::ITEM* startItem = nullptr;
1715  PNS::ITEM_SET itemsToDrag;
1716  const FOOTPRINT* footprint = nullptr;
1717 
1718  std::shared_ptr<CONNECTIVITY_DATA> connectivityData = board()->GetConnectivity();
1719  std::vector<BOARD_ITEM*> dynamicItems;
1720  std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr;
1721  VECTOR2I lastOffset;
1722 
1723  if( item->Type() == PCB_FOOTPRINT_T )
1724  {
1725  footprint = static_cast<const FOOTPRINT*>(item);
1726 
1727  for( PAD* pad : footprint->Pads() )
1728  {
1730 
1731  if( solid )
1732  itemsToDrag.Add( solid );
1733 
1734  if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1735  {
1736  if( connectivityData->GetRatsnestForPad( pad ).size() > 0 )
1737  dynamicItems.push_back( pad );
1738  }
1739  }
1740 
1741  dynamicData = std::make_unique<CONNECTIVITY_DATA>( dynamicItems, true );
1742  connectivityData->BlockRatsnestItems( dynamicItems );
1743  }
1744  else
1745  {
1746  startItem = m_router->GetWorld()->FindItemByParent( item );
1747 
1748  if( startItem )
1749  itemsToDrag.Add( startItem );
1750  }
1751 
1752  GAL* gal = m_toolMgr->GetView()->GetGAL();
1753  VECTOR2I p0 = controls()->GetCursorPosition( false );
1754  VECTOR2I p = p0;
1755 
1757  m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
1758 
1759  if( startItem )
1760  {
1761  p = snapToItem( startItem, p0 );
1762  m_startItem = startItem;
1763 
1764  if( m_startItem && m_startItem->Net() > 0 )
1765  highlightNet( true, m_startItem->Net() );
1766  }
1767  else if( footprint )
1768  {
1769  // The mouse is going to be moved on grid before dragging begins.
1770  VECTOR2I tweakedMousePos;
1771  PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1772 
1773  // Check if user wants to warp the mouse to origin of moved object
1774 
1775  if( editFrame->GetMoveWarpsCursor() )
1776  tweakedMousePos = footprint->GetPosition(); // Use footprint anchor to warp mouse
1777  else
1778  tweakedMousePos = controls()->GetCursorPosition(); // Just use current mouse pos
1779 
1780  // We tweak the mouse position using the value from above, and then use that as the
1781  // start position to prevent the footprint from jumping when we start dragging.
1782  // First we move the visual cross hair cursor...
1783  controls()->ForceCursorPosition( true, tweakedMousePos );
1784  controls()->SetCursorPosition( tweakedMousePos ); // ...then the mouse pointer
1785 
1786  // Now that the mouse is in the right position, get a copy of the position to use later
1787  p = controls()->GetCursorPosition();
1788  }
1789 
1790  int dragMode = aEvent.Parameter<int64_t> ();
1791 
1792  bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
1793 
1794  if( !dragStarted )
1795  {
1796  if( wasLocked )
1797  item->SetLocked( true );
1798 
1799  return 0;
1800  }
1801 
1802  m_gridHelper->SetAuxAxes( true, p );
1803  controls()->ShowCursor( true );
1804  controls()->SetAutoPan( true );
1805  frame()->UndoRedoBlock( true );
1806 
1807  view()->ClearPreview();
1808  view()->InitPreview();
1809 
1810  auto setCursor =
1811  [&]()
1812  {
1814  };
1815 
1816  // Set initial cursor
1817  setCursor();
1818 
1819  // Set the initial visible area
1820  BOX2D viewAreaD = getView()->GetGAL()->GetVisibleWorldExtents();
1821  m_router->SetVisibleViewArea( BOX2I( viewAreaD.GetOrigin(), viewAreaD.GetSize() ) );
1822 
1823  // Send an initial movement to prime the collision detection
1824  m_router->Move( p, nullptr );
1825 
1826  bool hasMouseMoved = false;
1827 
1828  while( TOOL_EVENT* evt = Wait() )
1829  {
1830  setCursor();
1831 
1832  if( evt->IsCancelInteractive() )
1833  {
1834  if( wasLocked )
1835  item->SetLocked( true );
1836 
1837  break;
1838  }
1839  else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
1840  {
1841  hasMouseMoved = true;
1842  updateEndItem( *evt );
1844 
1845  if( footprint )
1846  {
1847  VECTOR2I offset = m_endSnapPoint - p;
1848  BOARD_ITEM* previewItem;
1849  wxPoint fp_offset = wxPoint( offset.Rotate( footprint->GetOrientationRadians() ) );
1850 
1851  view()->ClearPreview();
1852 
1853  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1854  {
1855  previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() );
1856 
1857  if( drawing->Type() == PCB_FP_SHAPE_T )
1858  {
1859  FP_SHAPE* shape = static_cast<FP_SHAPE*>( previewItem );
1860  shape->FP_SHAPE::Move( fp_offset );
1861  }
1862  else
1863  {
1864  previewItem->Move( offset );
1865  }
1866 
1867  view()->AddToPreview( previewItem );
1868  view()->Hide( drawing, true );
1869  }
1870 
1871  for( PAD* pad : footprint->Pads() )
1872  {
1873  if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none()
1874  && pad->GetDrillSize().x == 0 )
1875  {
1876  previewItem = static_cast<BOARD_ITEM*>( pad->Clone() );
1877  previewItem->Move( offset );
1878 
1879  view()->AddToPreview( previewItem );
1880  }
1881  else
1882  {
1883  // Pads with copper or holes are handled by the router
1884  }
1885 
1886  view()->Hide( pad, true );
1887  }
1888 
1889  previewItem = static_cast<BOARD_ITEM*>( footprint->Reference().Clone() );
1890  previewItem->Move( offset );
1891  view()->AddToPreview( previewItem );
1892  view()->Hide( &footprint->Reference() );
1893 
1894  previewItem = static_cast<BOARD_ITEM*>( footprint->Value().Clone() );
1895  previewItem->Move( offset );
1896  view()->AddToPreview( previewItem );
1897  view()->Hide( &footprint->Value() );
1898 
1899  for( ZONE* zone : footprint->Zones() )
1900  {
1901  previewItem = static_cast<BOARD_ITEM*>( zone->Clone() );
1902  previewItem->Move( offset );
1903  view()->AddToPreview( previewItem );
1904  view()->Hide( zone, true );
1905  }
1906 
1907  // Update ratsnest
1908  dynamicData->Move( offset - lastOffset );
1909  lastOffset = offset;
1910  connectivityData->ComputeDynamicRatsnest( dynamicItems, dynamicData.get(), offset );
1911  }
1912  }
1913  else if( hasMouseMoved && ( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
1914  {
1915  updateEndItem( *evt );
1917  break;
1918  }
1919  else if( evt->Category() == TC_COMMAND )
1920  {
1921  // disallow editing commands
1922  if( evt->IsAction( &ACTIONS::cut )
1923  || evt->IsAction( &ACTIONS::copy )
1924  || evt->IsAction( &ACTIONS::paste )
1925  || evt->IsAction( &ACTIONS::pasteSpecial ) )
1926  {
1927  wxBell();
1928  }
1929  else
1930  {
1931  evt->SetPassEvent();
1932  }
1933  }
1934  else
1935  {
1936  evt->SetPassEvent();
1937  }
1938 
1939  handleCommonEvents( *evt );
1940  }
1941 
1942  if( footprint )
1943  {
1944  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1945  view()->Hide( drawing, false );
1946 
1947  view()->Hide( &footprint->Reference(), false );
1948  view()->Hide( &footprint->Value(), false );
1949 
1950  for( ZONE* zone : footprint->Zones() )
1951  view()->Hide( zone, false );
1952 
1953  for( PAD* pad : footprint->Pads() )
1954  view()->Hide( pad, false );
1955 
1956  view()->ClearPreview();
1957  view()->ShowPreview( false );
1958 
1959  connectivityData->ClearDynamicRatsnest();
1960  }
1961 
1962  if( m_router->RoutingInProgress() )
1963  m_router->StopRouting();
1964 
1965  m_gridHelper->SetAuxAxes( false );
1966  controls()->SetAutoPan( false );
1967  controls()->ForceCursorPosition( false );
1968  frame()->UndoRedoBlock( false );
1969  highlightNet( false );
1970 
1971  return 0;
1972 }
1973 
1974 
1976 {
1977  const SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1978 
1979  if( selection.Size() != 1 )
1980  return 0;
1981 
1982  const BOARD_CONNECTED_ITEM* item =
1983  static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
1984 
1985  if( item->Type() != PCB_TRACE_T )
1986  return 0;
1987 
1988  Activate();
1989 
1991  m_router->SyncWorld();
1993 
1994  TOOL_MANAGER* toolManager = frame()->GetToolManager();
1995  GAL* gal = toolManager->GetView()->GetGAL();
1996 
1998  m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) );
1999 
2000  if( toolManager->IsContextMenuActive() )
2001  {
2002  // If we're here from a context menu then we need to get the position of the
2003  // cursor when the context menu was invoked. This is used to figure out the
2004  // break point on the track.
2006  }
2007  else
2008  {
2009  // If we're here from a hotkey, then get the current mouse position so we know
2010  // where to break the track.
2011  m_startSnapPoint = snapToItem( m_startItem, controls()->GetCursorPosition() );
2012  }
2013 
2014  if( m_startItem && m_startItem->IsLocked() )
2015  {
2016  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
2017  wxOK | wxCANCEL | wxICON_WARNING );
2018  dlg.SetOKLabel( _( "Break Track" ) );
2019  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
2020 
2021  if( dlg.ShowModal() == wxID_CANCEL )
2022  return 0;
2023  }
2024 
2025  frame()->UndoRedoBlock( true );
2026  breakTrack();
2027 
2028  if( m_router->RoutingInProgress() )
2029  m_router->StopRouting();
2030 
2031  frame()->UndoRedoBlock( false );
2032 
2033  return 0;
2034 }
2035 
2036 
2038 {
2040  DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
2041 
2042  if( sizeDlg.ShowModal() == wxID_OK )
2043  {
2044  bds.m_TempOverrideTrackWidth = true;
2045  bds.UseCustomTrackViaSize( true );
2046 
2047  TOOL_EVENT dummy;
2049  }
2050 
2051  return 0;
2052 }
2053 
2054 
2056 {
2057  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
2058 
2059  if( !m_router->GetCurrentNets().empty() )
2061 
2062  m_router->UpdateSizes( sizes );
2063 
2064  // Changing the track width can affect the placement, so call the
2065  // move routine without changing the destination
2066  // Update end item first to avoid moving to an invalid/missing item
2067  updateEndItem( aEvent );
2069 
2071 
2072  return 0;
2073 }
2074 
2075 
2077 {
2078  if( !m_router->RoutingInProgress() )
2079  {
2080  frame()->SetMsgPanel( board() );
2081  return;
2082  }
2083 
2084  std::vector<MSG_PANEL_ITEM> items;
2085  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
2088 
2089  if( m_startItem && m_startItem->Net() > 0 )
2090  {
2091  wxString description = isDiffPair ? _( "Routing Diff Pair: %s" ) : _( "Routing Track: %s" );
2092 
2093  NETINFO_ITEM* netInfo = board()->FindNet( m_startItem->Net() );
2094  wxASSERT( netInfo );
2095 
2096  items.emplace_back( wxString::Format( description, netInfo->GetNetname() ),
2097  wxString::Format( _( "Net Class: %s" ), netInfo->GetNetClassName() ) );
2098  }
2099  else
2100  {
2101  items.emplace_back( _( "Routing Track" ), _( "(no net)" ) );
2102  }
2103 
2104  wxString cornerMode;
2105 
2107  {
2108  cornerMode = _( "Free-angle" );
2109  }
2110  else
2111  {
2112  switch( m_router->Settings().GetCornerMode() )
2113  {
2114  case DIRECTION_45::CORNER_MODE::MITERED_45: cornerMode = _( "45-degree" ); break;
2115  case DIRECTION_45::CORNER_MODE::ROUNDED_45: cornerMode = _( "45-degree rounded" ); break;
2116  case DIRECTION_45::CORNER_MODE::MITERED_90: cornerMode = _( "90-degree" ); break;
2117  case DIRECTION_45::CORNER_MODE::ROUNDED_90: cornerMode = _( "90-degree rounded" ); break;
2118  default: break;
2119  }
2120  }
2121 
2122  items.emplace_back( _( "Corner Style" ), cornerMode );
2123 
2124  EDA_UNITS units = frame()->GetUserUnits();
2125 
2126  int width = isDiffPair ? sizes.DiffPairWidth() : sizes.TrackWidth();
2127  items.emplace_back( wxString::Format( _( "Track Width: %s" ),
2128  MessageTextFromValue( units, width ) ),
2129  wxString::Format( _( "(from %s)" ), sizes.GetWidthSource() ) );
2130 
2131  if( m_startItem )
2132  {
2134  dummy.SetNet( m_startItem->Net() );
2135 
2136  PNS::CONSTRAINT constraint;
2137 
2138  if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, &dummy, nullptr,
2139  m_router->GetCurrentLayer(), &constraint ) )
2140  {
2141  items.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
2142  MessageTextFromValue( units, constraint.m_Value.Min() ) ),
2143  wxString::Format( _( "(from %s)" ), constraint.m_RuleName ) );
2144  }
2145  }
2146 
2147  if( isDiffPair )
2148  {
2149  items.emplace_back( _( "Diff Pair Gap" ),
2150  MessageTextFromValue( units, sizes.DiffPairGap() ) );
2151  }
2152 
2153  frame()->SetMsgPanel( items );
2154 }
2155 
2156 
2158 {
2160 
2171 
2178 
2213 
2216 }
void Empty()
Clear the list.
Definition: collector.h:90
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
const wxString & FailureReason() const
Definition: pns_router.h:204
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
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:759
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
static TOOL_ACTION layerBottom
Definition: pcb_actions.h:282
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
void Hide(VIEW_ITEM *aItem, bool aHide=true)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1537
Base class for PNS router board items.
Definition: pns_item.h:55
static TOOL_ACTION layerInner26
Definition: pcb_actions.h:277
Contain all persistent settings of the router, such as the mode, optimization effort,...
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1328
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
BOARD * GetBoard() const
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: fp_text.cpp:339
int onLayerCommand(const TOOL_EVENT &aEvent)
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:104
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:283
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
BOX2< VECTOR2I > BOX2I
Definition: box2.h:506
void SetMode(PNS_MODE aMode)
Return the optimizer effort. Bigger means cleaner traces, but slower routing.
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: confirm.cpp:55
void SetTrackWidthIndex(unsigned aIndex)
Set the current track width list index to aIndex.
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:245
void SetStartLayer(int aLayer)
static TOOL_ACTION layerNext
Definition: pcb_actions.h:283
double GetOrientationRadians() const
Definition: footprint.h:193
PNS::PNS_MODE GetRouterMode()
PNS::RULE_RESOLVER * GetRuleResolver() override
static TOOL_ACTION layerInner2
Definition: pcb_actions.h:253
int MainLoop(const TOOL_EVENT &aEvent)
static TOOL_ACTION selectLayerPair
Definition: pcb_actions.h:129
#define STARTPOINT
When a line is selected, these flags indicate which.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
PCB_EDIT_FRAME & m_frame
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:236
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.
BOARD * board() const
#define LEGACY_HK_NAME(x)
Definition: actions.h:32
int DpDimensionsDialog(const TOOL_EVENT &aEvent)
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))
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:243
PNS_MODE
< Routing modes
static TOOL_ACTION layerInner5
Definition: pcb_actions.h:256
DIRECTION_45::CORNER_MODE GetCornerMode() const
blind/buried via
Definition: router_tool.cpp:73
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:45
const wxPoint & GetEnd() const
Definition: pcb_track.h:105
bool finishInteractive()
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)
void SetCustomDiffPairViaGap(int aGap)
Sets custom via gap for differential pairs (i.e.
void ToggleCornerMode()
Definition: pns_router.cpp:818
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)
Microvia.
Definition: router_tool.cpp:74
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:48
This file is part of the common library.
static TOOL_ACTION layerInner6
Definition: pcb_actions.h:257
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:193
wxString GetNetClassName() const
Definition: netinfo.h:115
std::vector< int > m_TrackWidthList
static TOOL_ACTION layerInner7
Definition: pcb_actions.h:258
static TOOL_ACTION layerInner8
Definition: pcb_actions.h:259
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1614
static TOOL_ACTION layerInner21
Definition: pcb_actions.h:272
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
VECTOR2I m_startSnapPoint
Definition: pns_tool_base.h:70
int InlineDrag(const TOOL_EVENT &aEvent)
static TOOL_ACTION routerUndoLastSegment
Definition: pcb_actions.h:189
void CommitRouting()
Definition: pns_router.cpp:710
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:413
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void ClearViewDecorations()
Definition: pns_router.cpp:747
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:135
Tool is invoked after being inactive.
Definition: tool_base.h:79
int CycleRouterMode(const TOOL_EVENT &aEvent)
virtual void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *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:338
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
void UseCustomDiffPairDimensions(bool aEnabled)
Enables/disables custom differential pair dimensions.
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:782
static TOOL_ACTION cancelInteractive
Definition: actions.h:62
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:117
SIZES_SETTINGS m_savedSizes
Definition: pns_tool_base.h:68
void SyncWorld()
Definition: pns_router.cpp:92
bool IsPlacingVia() const
Definition: pns_router.cpp:809
void InitPreview()
Definition: view.cpp:1607
Ask user to select layer before adding via.
Definition: router_tool.cpp:77
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
bool IsKeyPressed() const
Definition: tool_event.h:351
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
bool CanInlineDrag(int aDragMode)
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)
static TOOL_ACTION routerHighlightMode
Actions to enable switching modes via hotkey assignments.
Definition: pcb_actions.h:197
const std::vector< int > GetCurrentNets() const
Definition: pns_router.cpp:781
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
Definition: pcb_plugin.h:141
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:190
T Opt() const
Definition: minoptmax.h:35
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...
static TOOL_ACTION trackViaSizeChanged
Definition: pcb_actions.h:299
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:134
wxString m_RuleName
Definition: pns_node.h:72
TOOL_EVENT_CATEGORY Category() const
Returns more specific information about the type of an event.
Definition: tool_event.h:227
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.
TRACK_WIDTH_MENU(PCB_EDIT_FRAME &aFrame)
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
std::uint32_t EDA_ITEM_FLAGS
virtual void SetLocked(bool aLocked)
Modify the 'lock' status for of the item.
Definition: board_item.h:218
void UndoRedoBlock(bool aBlock=true)
Enable/disable undo and redo operations.
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: infobar.cpp:128
#define ENDPOINT
ends. (Used to support dragging.)
void SetViaDrill(int aDrill)
T Min() const
Definition: minoptmax.h:33
bool m_ShowRouterDebugGraphics
Show PNS router debug graphics.
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:201
bool Init() override
Init() is called once upon a registration of the tool.
int CountType(KICAD_T aType)
Count the number of items matching aType.
Definition: collector.h:228
void breakTrack()
virtual bool IsLocked() const
Definition: board_item.cpp:64
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
APPEARANCE_CONTROLS * GetAppearancePanel()
static TOOL_ACTION layerInner3
Definition: pcb_actions.h:254
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
static const TOOL_ACTION ACT_AutoEndRoute("pcbnew.InteractiveRouter.AutoEndRoute", AS_CONTEXT, 'F', "", _("Auto-finish Track"), _("Automatically finishes laying the current track."))
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
static TOOL_ACTION layerInner24
Definition: pcb_actions.h:275
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).
int ChangeRouterMode(const TOOL_EVENT &aEvent)
Container to handle a stock of specific differential pairs each with unique track width,...
static TOOL_ACTION layerInner11
Definition: pcb_actions.h:262
bool RemoveLoops() const
Enable/disable loop (redundant track) removal.
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
void ToggleViaPlacement()
Definition: pns_router.cpp:771
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
PADS & Pads()
Definition: footprint.h:169
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:88
void ClearWorld()
Definition: pns_router.cpp:102
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:502
static TOOL_ACTION layerTop
Definition: pcb_actions.h:251
int Start() const
Definition: pns_layerset.h:82
void ShowPreview(bool aShow=true)
Definition: view.cpp:1628
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition: collector.h:100
static const TOOL_ACTION ACT_EndTrack("pcbnew.InteractiveRouter.EndTrack", AS_CONTEXT, WXK_END, "", _("Finish Track"), _("Stops laying the current track."), BITMAPS::checked_ok)
FP_TEXT & Reference()
Definition: footprint.h:503
PCB_BASE_EDIT_FRAME * frame() const
void UndoLastSegment()
Definition: pns_router.cpp:701
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
virtual PCB_LAYER_ID GetActiveLayer() const
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...
virtual void updateStartItem(const TOOL_EVENT &aEvent, bool aIgnorePads=false)
static TOOL_ACTION layerInner23
Definition: pcb_actions.h:274
void SetViaSizeIndex(unsigned aIndex)
Set the current via size list index to aIndex.
MINOPTMAX< int > m_Value
Definition: drc_rule.h:145
int onViaCommand(const TOOL_EVENT &aEvent)
static VIATYPE getViaTypeFromFlags(int aFlags)
Master controller class:
Definition: tool_manager.h:54
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:82
virtual void Reset(RESET_REASON aReason)=0
Bring the tool to a known, initial state.
FP_ZONES & Zones()
Definition: footprint.h:175
static TOOL_ACTION copy
Definition: actions.h:67
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
virtual void updateEndItem(const TOOL_EVENT &aEvent)
bool prepareInteractive()
bool GetGridSnapping() const
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0))
Definition: grid_helper.cpp:67
const VECTOR2I snapToItem(ITEM *aSnapToItem, const VECTOR2I &aP)
static TOOL_ACTION routerSettingsDialog
Activation of the Push and Shove settings dialogs.
Definition: pcb_actions.h:192
PCB_GRID_HELPER * m_gridHelper
Definition: pns_tool_base.h:76
#define _(s)
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:516
static TOOL_ACTION layerInner13
Definition: pcb_actions.h:264
void performRouting()
const PCB_SELECTION & selection() const
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
Definition: pns_router.cpp:854
static TOOL_ACTION layerPrev
Definition: pcb_actions.h:284
Normal via.
Definition: router_tool.cpp:72
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
static PCB_LAYER_ID getTargetLayerFromEvent(const TOOL_EVENT &aEvent)
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
Definition: pns_node.cpp:1592
void update() override
Update menu state stub.
virtual void Move(const wxPoint &aMoveVector)
Move this object.
Definition: board_item.h:233
unsigned GetViaSizeIndex() const
virtual void PopTool(const std::string &actionName)
static TOOL_ACTION layerInner25
Definition: pcb_actions.h:276
int Net() const
Definition: pns_item.h:152
static TOOL_ACTION layerInner18
Definition: pcb_actions.h:269
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:432
virtual int GetTopLayer() const
Definition: view.cpp:817
bool UseNetClassVia() const
Return true if netclass values should be used to obtain appropriate via size.
void SetCustomDiffPairWidth(int aWidth)
Sets custom track width for differential pairs (i.e.
void handleCommonEvents(TOOL_EVENT &evt)
Generic, UI-independent tool event.
Definition: tool_event.h:152
ITEM * m_startItem
Definition: pns_tool_base.h:69
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:675
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
FOOTPRINT * footprint() const
unsigned GetTrackWidthIndex() const
void SetVisibleViewArea(const BOX2I &aExtents)
Definition: pns_router.h:210
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:345
DIFF_PAIR_MENU(PCB_EDIT_FRAME &aFrame)
static TOOL_ACTION layerInner30
Definition: pcb_actions.h:281
void ClearPreview()
Definition: view.cpp:1592
static TOOL_ACTION cut
Definition: actions.h:66
KIGFX::PCB_VIEW * view() const
bool IsContextMenuActive() const
True while processing a context menu.
Definition: tool_manager.h:411
static TOOL_ACTION layerInner29
Definition: pcb_actions.h:280
const wxString & GetNetname() const
Definition: netinfo.h:126
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)
ROUTER * m_router
Definition: pns_tool_base.h:78
PNS_MODE Mode() const
Set the routing mode.
An interface for classes handling user events controlling the view behavior such as zooming,...
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:44
void switchLayerOnViaPlacement()
static TOOL_ACTION layerInner10
Definition: pcb_actions.h:261
DRAWINGS & GraphicalItems()
Definition: footprint.h:172
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual bool IsType(const KICAD_T aScanTypes[]) const
Check whether the item is one of the listed types.
Definition: eda_item.h:182
static LSET AllLayersMask()
Definition: lset.cpp:796
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
bool DisableGridSnapping() const
Definition: tool_event.h:341
int SettingsDialog(const TOOL_EVENT &aEvent)
void SetDiffPairIndex(unsigned aIndex)
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:355
int CustomTrackWidthDialog(const TOOL_EVENT &aEvent)
bool RoutingInProgress()
Returns whether routing is currently active.
static TOOL_ACTION cycleRouterMode
Definition: pcb_actions.h:200
void SetCustomDiffPairGap(int aGap)
Sets custom gap for differential pairs (i.e.
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:252
static TOOL_ACTION routerWalkaroundMode
Definition: pcb_actions.h:199
void Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:428
static TOOL_ACTION layerInner15
Definition: pcb_actions.h:266
int onTrackViaSizeChanged(const TOOL_EVENT &aEvent)
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:203
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:371
VECTOR2D ToScreen(const VECTOR2D &aCoord, bool aAbsolute=true) const
Convert a world space point/vector to a point/vector in screen space coordinates.
Definition: view.cpp:468
static TOOL_ACTION layerInner28
Definition: pcb_actions.h:279
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:286
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:477
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
static TOOL_ACTION layerInner27
Definition: pcb_actions.h:278
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:808
void SetViaType(VIATYPE aViaType)
bool IsNull() const
Definition: drc_rule.h:117
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:98
const PCB_DISPLAY_OPTIONS & displayOptions() const
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
static TOOL_ACTION layerInner17
Definition: pcb_actions.h:268
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
void SetSnap(bool aSnap)
Definition: grid_helper.h:64
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:132
static TOOL_ACTION layerInner20
Definition: pcb_actions.h:271
static TOOL_ACTION pasteSpecial
Definition: actions.h:69
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))
void StopRouting()
Definition: pns_router.cpp:719
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
virtual void highlightNet(bool aEnabled, int aNetcode=-1)
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:336
EDA_UNITS
Definition: eda_units.h:38
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:460
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)
ROUTER_MODE
Definition: pns_router.h:62
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:73
PCB_EDIT_FRAME & m_frame
static const KICAD_T DraggableItems[]
A scan list for items that can be dragged.
Definition: collectors.h:313
static TOOL_ACTION layerInner22
Definition: pcb_actions.h:273
Handle the data for a net.
Definition: netinfo.h:66
int handleLayerSwitch(const TOOL_EVENT &aEvent, bool aForceVia)
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:289
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
VIATYPE
Definition: pcb_track.h:60
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:570
void SetUseGrid(bool aSnapToGrid)
Definition: grid_helper.h:67
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:87
Ignore collisions, mark obstacles.
KIGFX::VIEW_CONTROLS * controls() const
void SetMode(ROUTER_MODE aMode)
Definition: pns_router.cpp:843
void update() override
Update menu state stub.
Common, abstract interface for edit frames.
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:175
VECTOR2I m_endSnapPoint
Definition: pns_tool_base.h:74
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
void UpdateMessagePanel()
LOGGER * Logger()
Definition: pns_router.cpp:803
EDA_ITEM_FLAGS IsPointOnEnds(const wxPoint &point, int min_dist=0) const
Function IsPointOnEnds returns STARTPOINT if point if near (dist = min_dist) start point,...
Definition: pcb_track.cpp:181
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
void saveRouterDebugLog()
Definition: layer_ids.h:71
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:52
Base abstract interface for all kinds of tools.
Definition: tool_base.h:65
bool IsToolActive() const
Definition: tool_base.cpp:31
static TOOL_ACTION layerInner14
Definition: pcb_actions.h:265
Represent a single user action.
Definition: tool_action.h:67
static TOOL_ACTION layerInner9
Definition: pcb_actions.h:260
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:149
static void NeighboringSegmentFilter(const VECTOR2I &aPt, GENERAL_COLLECTOR &aCollector)
void performDragging(int aMode=PNS::DM_ANY)
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
Definition: pns_item.h:138
bool SwitchLayer(int layer)
Definition: pns_router.cpp:762
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...
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))
The main frame for Pcbnew.
void Clear()
Remove all the entries from the menu (as well as its title).
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
Definition: tool_action.cpp:72
int Size() const
Returns the number of selected parts.
Definition: selection.h:104
The selection tool: currently supports:
Only walk around.
bool IsLocked() const
Definition: pns_item.h:227
wxPoint GetPosition() const override
Definition: footprint.h:187
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int InlineBreakTrack(const TOOL_EVENT &aEvent)
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
static TOOL_ACTION layerInner16
Definition: pcb_actions.h:267
BOX2D GetVisibleWorldExtents() const
std::vector< VIA_DIMENSION > m_ViasDimensionsList
boost::optional< T > OPT
Definition: optional.h:7
int ShowModal() override
Definition: confirm.cpp:99
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:130
bool GetMoveWarpsCursor() const
Indicate that a move operation should warp the mouse pointer to the origin of the move object.
Definition: tools_holder.h:141
void Activate()
Run the tool.
WX_INFOBAR * GetInfoBar()
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Implementing DIALOG_TRACK_VIA_SIZE_BASE.
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:326
static TOOL_ACTION layerInner4
Definition: pcb_actions.h:255
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
unsigned GetDiffPairIndex() const
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
std::shared_ptr< ACTION_MENU > m_trackViaMenu
Definition: router_tool.h:89
bool HasPosition() const
Definition: tool_event.h:240
void AddLayerPair(int aL1, int aL2)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
MINOPTMAX< int > m_Value
Definition: pns_node.h:70
const Vec & GetSize() const
Definition: box2.h:172
int m_lastTargetLayer
Definition: router_tool.h:91
std::shared_ptr< ACTION_MENU > m_diffPairMenu
Definition: router_tool.h:88
bool m_MicroViasAllowed
true to allow micro vias
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
void FlipPosture()
Definition: pns_router.cpp:753
const Vec & GetOrigin() const
Definition: box2.h:176
bool RoutingInProgress() const
Definition: pns_router.cpp:114
int KeyCode() const
Definition: tool_event.h:346
static TOOL_ACTION layerInner19
Definition: pcb_actions.h:270
Definition: pad.h:57
VECTOR2D GetMenuCursorPos() const
Definition: tool_manager.h:440
void SetViaDiameter(int aDiameter)
static FILENAME_RESOLVER * resolver
Definition: export_idf.cpp:57
int getStartLayer(const PNS::ITEM *aItem)
static TOOL_ACTION layerInner1
Definition: pcb_actions.h:252
ROUTER_MODE Mode() const
Definition: pns_router.h:132
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, int aNet) override
static TOOL_ACTION routerShoveMode
Definition: pcb_actions.h:198
NODE * GetWorld() const
Definition: pns_router.h:154
OPT< int > PairedLayer(int aLayerId)
PNS_KICAD_IFACE * m_iface
Definition: pns_tool_base.h:77
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:59
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:182
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:914
static TOOL_ACTION paste
Definition: actions.h:68
VIA_ACTION_FLAGS
Flags used by via tool actions.
Definition: router_tool.cpp:68
std::shared_ptr< DRC_ENGINE > m_DRCEngine
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:56
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:31
const LAYER_RANGE & Layers() const
Definition: pns_item.h:154
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:43
const wxPoint & GetStart() const
Definition: pcb_track.h:108
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:145
static TOOL_ACTION layerInner12
Definition: pcb_actions.h:263
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:548
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
Abstract interface for drawing on a 2D-surface.
Container for design settings for a BOARD object.
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:287
int GetCurrentLayer() const
Definition: pns_router.cpp:792
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:178