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-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <wx/hyperlink.h>
23 #include <functional>
24 using namespace std::placeholders;
25 #include <board.h>
26 #include <board_item.h>
27 #include <footprint.h>
28 #include <fp_shape.h>
29 #include <pad.h>
30 #include <pcb_edit_frame.h>
31 #include <pcbnew_id.h>
35 #include <widgets/infobar.h>
36 #include <confirm.h>
37 #include <bitmaps.h>
38 #include <tool/action_menu.h>
39 #include <tool/tool_manager.h>
40 #include <tool/tool_menu.h>
41 #include <tools/pcb_actions.h>
42 #include <tools/selection_tool.h>
43 #include <tools/grid_helper.h>
44 
45 #include "router_tool.h"
46 #include "pns_segment.h"
47 #include "pns_router.h"
48 #include "pns_itemset.h"
49 #include "pns_logger.h"
50 
51 #include "pns_kicad_iface.h"
52 
53 #ifdef DEBUG
55 #endif
56 
57 using namespace KIGFX;
58 
63 {
64  // Via type
65  VIA_MASK = 0x03,
66  VIA = 0x00,
67  BLIND_VIA = 0x01,
68  MICROVIA = 0x02,
69 
70  // Select layer
72 };
73 
74 
75 // Actions, being statically-defined, require specialized I18N handling. We continue to
76 // use the _() macro so that string harvesting by the I18N framework doesn't have to be
77 // specialized, but we don't translate on initialization and instead do it in the getters.
78 
79 #undef _
80 #define _(s) s
81 
82 static const TOOL_ACTION ACT_UndoLastSegment( "pcbnew.InteractiveRouter.UndoLastSegment",
83  AS_CONTEXT,
84  WXK_BACK, "",
85  _( "Undo last segment" ), _( "Stops laying the current track." ),
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" ), _( "Automagically 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 
119 static const TOOL_ACTION ACT_SelLayerAndPlaceThroughVia( "pcbnew.InteractiveRouter.SelLayerAndPlaceVia",
120  AS_CONTEXT,
121  '<', LEGACY_HK_NAME( "Select Layer and Add Through Via" ),
122  _( "Select Layer and Place Through Via..." ),
123  _( "Select a layer, then add a through-hole via at the end of currently routed track." ),
126 
127 static const TOOL_ACTION ACT_SelLayerAndPlaceBlindVia( "pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia",
128  AS_CONTEXT,
129  MD_ALT + '<', LEGACY_HK_NAME( "Select Layer and Add Blind/Buried Via" ),
130  _( "Select Layer and Place Blind/Buried Via..." ),
131  _( "Select a layer, then add a blind or buried via at the end of currently routed track."),
134 
135 static const TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackViaSize",
136  AS_CONTEXT,
137  'Q', LEGACY_HK_NAME( "Custom Track/Via Size" ),
138  _( "Custom Track/Via Size..." ),
139  _( "Shows a dialog for changing the track width and via size." ),
140  width_track_xpm );
141 
142 static const TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture",
143  AS_CONTEXT,
144  '/', LEGACY_HK_NAME( "Switch Track Posture" ),
145  _( "Switch Track Posture" ),
146  _( "Switches posture of the currently routed track." ),
148 
149 static const TOOL_ACTION ACT_SwitchRounding( "pcbnew.InteractiveRouter.SwitchRounding",
150  AS_CONTEXT,
151  0, LEGACY_HK_NAME( "Switch Corner Rounding" ),
152  _( "Switch Corner Rounding" ),
153  _( "Switches the corner type of the currently routed track." ),
155 
156 #undef _
157 #define _(s) wxGetTranslation((s))
158 
159 
161  TOOL_BASE( "pcbnew.InteractiveRouter" )
162 {
163 }
164 
165 
167 {
168 public:
170  ACTION_MENU( true ),
171  m_frame( aFrame )
172  {
174  SetTitle( _( "Select Track/Via Width" ) );
175  }
176 
177 protected:
178  ACTION_MENU* create() const override
179  {
180  return new TRACK_WIDTH_MENU( m_frame );
181  }
182 
183  void update() override
184  {
185  EDA_UNITS units = m_frame.GetUserUnits();
187  bool useIndex = !bds.m_UseConnectedTrackWidth &&
188  !bds.UseCustomTrackViaSize();
189  wxString msg;
190 
191  Clear();
192 
193  Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
194  _( "Route using the width of the starting track." ), wxITEM_CHECK );
197 
198  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
199  _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
201  useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
202 
203  Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
204  _( "Specify custom track and via sizes" ), wxITEM_CHECK );
206 
207  AppendSeparator();
208 
209  // Append the list of tracks & via sizes
210  for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
211  {
212  int width = bds.m_TrackWidthList[i];
213 
214  if( i == 0 )
215  msg = _( "Track netclass width" );
216  else
217  msg.Printf( _( "Track %s" ), MessageTextFromValue( units, width ) );
218 
219  int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
220  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
221  Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
222  }
223 
224  AppendSeparator();
225 
226  for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
227  {
228  VIA_DIMENSION via = bds.m_ViasDimensionsList[i];
229 
230  if( i == 0 )
231  msg = _( "Via netclass values" );
232  else
233  {
234  if( via.m_Drill > 0 )
235  msg.Printf( _("Via %s, drill %s" ),
236  MessageTextFromValue( units, via.m_Diameter ),
237  MessageTextFromValue( units, via.m_Drill ) );
238  else
239  msg.Printf( _( "Via %s" ), MessageTextFromValue( units, via.m_Diameter ) );
240  }
241 
242  int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
243  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
244  Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
245  }
246  }
247 
248  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
249  {
251  int id = aEvent.GetId();
252 
253  // On Windows, this handler can be called with an event ID not existing in any
254  // menuitem, so only set flags when we have an ID match.
255 
257  {
258  bds.UseCustomTrackViaSize( true );
259  bds.m_UseConnectedTrackWidth = false;
261  }
262  else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
263  {
264  bds.UseCustomTrackViaSize( false );
265  bds.m_UseConnectedTrackWidth = true;
266  }
268  {
269  bds.UseCustomTrackViaSize( false );
270  bds.m_UseConnectedTrackWidth = false;
271  bds.SetViaSizeIndex( 0 );
272  bds.SetTrackWidthIndex( 0 );
273  }
275  {
276  bds.UseCustomTrackViaSize( false );
277  bds.m_UseConnectedTrackWidth = false;
279  }
281  {
282  bds.UseCustomTrackViaSize( false );
283  bds.m_UseConnectedTrackWidth = false;
285  }
286 
287  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
288  }
289 
290 private:
292 };
293 
294 
296 {
297 public:
299  ACTION_MENU( true ),
300  m_frame( aFrame )
301  {
303  SetTitle( _( "Select Differential Pair Dimensions" ) );
304  }
305 
306 protected:
307  ACTION_MENU* create() const override
308  {
309  return new DIFF_PAIR_MENU( m_frame );
310  }
311 
312  void update() override
313  {
314  EDA_UNITS units = m_frame.GetUserUnits();
316 
317  Clear();
318 
319  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
320  _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
322  !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
323 
324  Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
325  _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
327 
328  AppendSeparator();
329 
330  // Append the list of differential pair dimensions
331 
332  // Drop index 0 which is the current netclass dimensions (which are handled above)
333  for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
334  {
336  wxString msg;
337 
338  if( diffPair.m_Gap <= 0 )
339  {
340  if( diffPair.m_ViaGap <= 0 )
341  {
342  msg.Printf( _( "Width %s" ),
343  MessageTextFromValue( units, diffPair.m_Width ) );
344  }
345  else
346  {
347  msg.Printf( _( "Width %s, via gap %s" ),
348  MessageTextFromValue( units, diffPair.m_Width ),
349  MessageTextFromValue( units, diffPair.m_ViaGap ) );
350  }
351  }
352  else
353  {
354  if( diffPair.m_ViaGap <= 0 )
355  {
356  msg.Printf( _( "Width %s, gap %s" ),
357  MessageTextFromValue( units, diffPair.m_Width ),
358  MessageTextFromValue( units, diffPair.m_Gap ) );
359  }
360  else
361  {
362  msg.Printf( _( "Width %s, gap %s, via gap %s" ),
363  MessageTextFromValue( units, diffPair.m_Width ),
364  MessageTextFromValue( units, diffPair.m_Gap ),
365  MessageTextFromValue( units, diffPair.m_ViaGap ) );
366  }
367  }
368 
369  int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
370  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
371  Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
372  }
373  }
374 
375  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
376  {
378  int id = aEvent.GetId();
379 
380  // On Windows, this handler can be called with an event ID not existing in any
381  // menuitem, so only set flags when we have an ID match.
382 
384  {
385  bds.UseCustomDiffPairDimensions( true );
386  TOOL_MANAGER* toolManager = m_frame.GetToolManager();
387  toolManager->RunAction( PCB_ACTIONS::routerDiffPairDialog, true );
388  }
390  {
391  bds.UseCustomDiffPairDimensions( false );
392  bds.SetDiffPairIndex( 0 );
393  }
395  {
396  bds.UseCustomDiffPairDimensions( false );
397  // remember that the menu doesn't contain index 0 (which is the netclass values)
399  }
400 
401  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
402  }
403 
404 private:
406 };
407 
408 
410 {
411 }
412 
413 
415 {
416  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
417 
418  wxASSERT( frame );
419 
420  auto& menu = m_menu.GetMenu();
421  menu.SetTitle( _( "Interactive Router" ) );
422 
423  auto trackViaMenu = std::make_shared<TRACK_WIDTH_MENU>( *frame );
424  trackViaMenu->SetTool( this );
425  m_menu.AddSubMenu( trackViaMenu );
426 
427  auto diffPairMenu = std::make_shared<DIFF_PAIR_MENU>( *frame );
428  diffPairMenu->SetTool( this );
429  m_menu.AddSubMenu( diffPairMenu );
430 
432 
433  menu.AddSeparator();
434 
440 
443 
444 // Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry.
452 
453  menu.AddSeparator();
454 
455  auto diffPairCond =
456  [this]( const SELECTION& )
457  {
459  };
460 
461  menu.AddMenu( trackViaMenu.get(), SELECTION_CONDITIONS::ShowAlways );
462  menu.AddMenu( diffPairMenu.get(), diffPairCond );
463 
465 
466  menu.AddSeparator();
467 
469 
470  return true;
471 }
472 
473 
475 {
476  if( aReason == RUN )
477  TOOL_BASE::Reset( aReason );
478 }
479 
480 
482 {
483 #ifdef DEBUG
484  if( aEvent.IsKeyPressed() )
485  {
486  switch( aEvent.KeyCode() )
487  {
488  case '0':
489  {
490  auto logger = m_router->Logger();
491  if( ! logger )
492  return;
493 
494  FILE *f = fopen("/tmp/pns.log", "wb");
495  wxLogTrace( "PNS", "saving drag/route log...\n" );
496 
497  const auto& events = logger->GetEvents();
498 
499  for( auto evt : events)
500  {
501  wxString id = "null";
502  if( evt.item && evt.item->Parent() )
503  id = evt.item->Parent()->m_Uuid.AsString();
504 
505  fprintf(f, "event %d %d %d %s\n", evt.p.x, evt.p.y, evt.type, (const char*) id.c_str() );
506  }
507 
508  fclose(f);
509 
510  // Export as *.kicad_pcb format, using a strategy which is specifically chosen
511  // as an example on how it could also be used to send it to the system clipboard.
512 
513  PCB_IO pcb_io;
514 
515  pcb_io.Save("/tmp/pns.dump", m_iface->GetBoard(), nullptr );
516 
517  break;
518  }
519  }
520  }
521 #endif
522 }
523 
524 
526 {
527  int tl = getView()->GetTopLayer();
528 
529  if( m_startItem )
530  {
531  const LAYER_RANGE& ls = m_startItem->Layers();
532 
533  if( ls.Overlaps( tl ) )
534  return tl;
535  else
536  return ls.Start();
537  }
538 
539  return tl;
540 }
541 
542 
544 {
545  int al = frame()->GetActiveLayer();
546  int cl = m_router->GetCurrentLayer();
547 
548  if( cl != al )
549  {
550  m_router->SwitchLayer( al );
551  }
552 
553  OPT<int> newLayer = m_router->Sizes().PairedLayer( cl );
554 
555  if( !newLayer )
556  newLayer = m_router->Sizes().GetLayerTop();
557 
558  m_router->SwitchLayer( *newLayer );
559  frame()->SetActiveLayer( ToLAYER_ID( *newLayer ) );
560 }
561 
562 
563 static VIATYPE getViaTypeFromFlags( int aFlags )
564 {
565  switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
566  {
568  return VIATYPE::THROUGH;
570  return VIATYPE::BLIND_BURIED;
572  return VIATYPE::MICROVIA;
573  default:
574  wxASSERT_MSG( false, "Unhandled via type" );
575  return VIATYPE::THROUGH;
576  }
577 }
578 
579 
581 {
582  if( aEvent.IsAction( &PCB_ACTIONS::layerTop ) )
583  return F_Cu;
584  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner1 ) )
585  return In1_Cu;
586  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner2 ) )
587  return In2_Cu;
588  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner3 ) )
589  return In3_Cu;
590  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner4 ) )
591  return In4_Cu;
592  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner5 ) )
593  return In5_Cu;
594  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner6 ) )
595  return In6_Cu;
596  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner7 ) )
597  return In7_Cu;
598  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner8 ) )
599  return In8_Cu;
600  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner9 ) )
601  return In9_Cu;
602  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner10 ) )
603  return In10_Cu;
604  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner11 ) )
605  return In11_Cu;
606  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner12 ) )
607  return In12_Cu;
608  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner13 ) )
609  return In13_Cu;
610  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner14 ) )
611  return In14_Cu;
612  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner15 ) )
613  return In15_Cu;
614  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner16 ) )
615  return In16_Cu;
616  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner17 ) )
617  return In17_Cu;
618  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner18 ) )
619  return In18_Cu;
620  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner19 ) )
621  return In19_Cu;
622  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner20 ) )
623  return In20_Cu;
624  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner21 ) )
625  return In21_Cu;
626  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner22 ) )
627  return In22_Cu;
628  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner23 ) )
629  return In23_Cu;
630  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner24 ) )
631  return In24_Cu;
632  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner25 ) )
633  return In25_Cu;
634  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner26 ) )
635  return In26_Cu;
636  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner27 ) )
637  return In27_Cu;
638  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner28 ) )
639  return In28_Cu;
640  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner29 ) )
641  return In29_Cu;
642  else if( aEvent.IsAction( &PCB_ACTIONS::layerInner30 ) )
643  return In30_Cu;
644  else if( aEvent.IsAction( &PCB_ACTIONS::layerBottom ) )
645  return B_Cu;
646  else
647  return UNDEFINED_LAYER;
648 }
649 
650 
652 {
653  if( !IsToolActive() )
654  return 0;
655 
656  // First see if this is one of the switch layer commands
657  LSEQ layers = LSET( board()->GetEnabledLayers() & LSET::AllCuMask() ).Seq();
659  PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
660 
661  if( aEvent.IsAction( &PCB_ACTIONS::layerNext ) )
662  {
663  size_t idx = 0;
664 
665  for( size_t i = 0; i < layers.size(); i++ )
666  {
667  if( layers[i] == currentLayer )
668  {
669  idx = i;
670  break;
671  }
672  }
673 
674  idx = ( idx + 1 ) % layers.size();
675  targetLayer = layers[idx];
676  }
677  else if( aEvent.IsAction( &PCB_ACTIONS::layerPrev ) )
678  {
679  size_t idx = 0;
680 
681  for( size_t i = 0; i < layers.size(); i++ )
682  {
683  if( layers[i] == currentLayer )
684  {
685  idx = i;
686  break;
687  }
688  }
689 
690  idx = ( idx > 0 ) ? ( idx - 1 ) : ( layers.size() - 1 );
691  targetLayer = layers[idx];
692  }
693  else
694  {
695  targetLayer = getTargetLayerFromEvent( aEvent );
696 
697  if( targetLayer != UNDEFINED_LAYER )
698  {
699  if( targetLayer == currentLayer )
700  return 0;
701  }
702  }
703 
705  const int layerCount = bds.GetCopperLayerCount();
706 
709 
711 
712  VIATYPE viaType = VIATYPE::THROUGH;
713  bool selectLayer = false;
714 
715  // Otherwise it is one of the router-specific via commands
716  if( targetLayer == UNDEFINED_LAYER )
717  {
718  const int actViaFlags = aEvent.Parameter<intptr_t>();
719  selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
720 
721  viaType = getViaTypeFromFlags( actViaFlags );
722 
723  // ask the user for a target layer
724  if( selectLayer )
725  {
726  wxPoint dlgPosition = wxGetMousePosition();
727 
728  targetLayer = frame()->SelectLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
729  LSET::AllNonCuMask(), dlgPosition );
730 
731  // Reset the cursor to the position where the event occured
732  controls()->SetCursorPosition( aEvent.HasPosition() ? aEvent.Position() : dlgPosition );
733  }
734  }
735 
736  // fixme: P&S supports more than one fixed layer pair. Update the dialog?
737  sizes.ClearLayerPairs();
738 
739  if( !m_router->IsPlacingVia() )
740  {
741  // Cannot place microvias or blind vias if not allowed (obvious)
742  if( ( viaType == VIATYPE::BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
743  {
744  WX_INFOBAR* infobar = frame()->GetInfoBar();
745  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY,
746  _("Show board setup"), wxEmptyString );
747 
748  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
749  [&]( wxHyperlinkEvent& aEvent )
750  {
751  getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Constraints" ) );
752  } ) );
753 
754  infobar->RemoveAllButtons();
755  infobar->AddButton( button );
756 
757  infobar->ShowMessageFor( _( "Blind/buried vias have to be enabled in "
758  "Board Setup > Design Rules > Constraints." ),
759  10000, wxICON_ERROR );
760  return false;
761  }
762 
763  if( ( viaType == VIATYPE::MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
764  {
765  WX_INFOBAR* infobar = frame()->GetInfoBar();
766  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY,
767  _("Show board setup"), wxEmptyString );
768 
769  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
770  [&]( wxHyperlinkEvent& aEvent )
771  {
772  getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Constraints" ) );
773  } ) );
774 
775  infobar->RemoveAllButtons();
776  infobar->AddButton( button );
777 
778  infobar->ShowMessageFor( _( "Microvias have to be enabled in "
779  "Board Setup > Design Rules > Constraints." ),
780  10000, wxICON_ERROR );
781  return false;
782  }
783 
784  // Can only place through vias on 2-layer boards
785  if( ( viaType != VIATYPE::THROUGH ) && ( layerCount <= 2 ) )
786  {
787  frame()->ShowInfoBarError( _( "Only through vias are allowed on 2 layer boards." ) );
788  return false;
789  }
790 
791  // Can only place microvias if we're on an outer layer, or directly adjacent to one
792  if( ( viaType == VIATYPE::MICROVIA ) && ( currentLayer > In1_Cu )
793  && ( currentLayer < layerCount - 2 ) )
794  {
795  frame()->ShowInfoBarError( _( "Microvias can only be placed between the outer layers "
796  "(F.Cu/B.Cu) and the ones directly adjacent to them." ) );
797  return false;
798  }
799  }
800 
801  // Convert blind/buried via to a through hole one, if it goes through all layers
802  if( viaType == VIATYPE::BLIND_BURIED
803  && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
804  || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
805  {
806  viaType = VIATYPE::THROUGH;
807  }
808 
809  switch( viaType )
810  {
811  case VIATYPE::THROUGH:
812  if( targetLayer == UNDEFINED_LAYER )
813  {
814  // use the default layer pair
815  currentLayer = pairTop;
816  targetLayer = pairBottom;
817  }
818  break;
819 
820  case VIATYPE::MICROVIA:
821  wxASSERT_MSG( !selectLayer,
822  "Unexpected select layer for microvia (microvia layers are implicit)" );
823 
824  if( currentLayer == F_Cu || currentLayer == In1_Cu )
825  {
826  // front-side microvia
827  currentLayer = F_Cu;
828  targetLayer = In1_Cu;
829  }
830  else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
831  {
832  // back-side microvia
833  currentLayer = B_Cu,
834  targetLayer = (PCB_LAYER_ID) ( layerCount - 2 );
835  }
836  else
837  {
838  wxASSERT_MSG( false,
839  "Invalid layer pair for microvia (must be on or adjacent to an outer layer)" );
840  }
841  break;
842 
844  if( targetLayer == UNDEFINED_LAYER )
845  {
846  if( currentLayer == pairTop || currentLayer == pairBottom )
847  {
848  // the current layer is on the defined layer pair,
849  // swap to the other side
850  currentLayer = pairTop;
851  targetLayer = pairBottom;
852  }
853  else
854  {
855  // the current layer is not part of the current layer pair,
856  // so fallback and swap to the top layer of the pair by default
857  targetLayer = pairTop;
858  }
859  }
860  break;
861 
862  default:
863  wxASSERT( false );
864  break;
865  }
866 
867  sizes.SetViaDiameter( bds.m_ViasMinSize );
868  sizes.SetViaDrill( bds.m_MinThroughDrill );
869 
870  if( bds.UseNetClassVia() || viaType == VIATYPE::MICROVIA )
871  {
872  class VIA dummyVia( board() );
873  dummyVia.SetViaType( viaType );
874  dummyVia.SetLayerPair( currentLayer, targetLayer );
875 
876  if( !m_router->GetCurrentNets().empty() )
877  dummyVia.SetNetCode( m_router->GetCurrentNets()[0] );
878 
879  DRC_CONSTRAINT constraint;
880 
881  constraint = bds.m_DRCEngine->EvalRulesForItems( VIA_DIAMETER_CONSTRAINT, &dummyVia,
882  nullptr, currentLayer );
883 
884  if( !constraint.IsNull() )
885  sizes.SetViaDiameter( constraint.m_Value.Opt() );
886 
887  constraint = bds.m_DRCEngine->EvalRulesForItems( HOLE_SIZE_CONSTRAINT, &dummyVia, nullptr,
888  currentLayer );
889 
890  if( !constraint.IsNull() )
891  sizes.SetViaDrill( constraint.m_Value.Opt() );
892  }
893  else
894  {
895  sizes.SetViaDiameter( bds.GetCurrentViaSize() );
896  sizes.SetViaDrill( bds.GetCurrentViaDrill() );
897  }
898 
899  sizes.SetViaType( viaType );
900  sizes.AddLayerPair( currentLayer, targetLayer );
901 
902  m_router->UpdateSizes( sizes );
904 
905  if( m_router->RoutingInProgress() )
906  updateEndItem( aEvent );
907  else
908  updateStartItem( aEvent );
909 
910  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
911 
912  return 0;
913 }
914 
915 
917 {
918  int routingLayer = getStartLayer( m_startItem );
919 
920  if( !IsCopperLayer( routingLayer ) )
921  {
922  frame()->ShowInfoBarError( _( "Tracks on Copper layers only" ) );
923  return false;
924  }
925 
926  PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
927 
928  editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
929 
930  if( m_startItem && m_startItem->Net() >= 0 )
931  highlightNet( true, m_startItem->Net() );
932 
933  controls()->ForceCursorPosition( false );
934  controls()->SetAutoPan( true );
935 
936  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
937 
938  m_iface->ImportSizes( sizes, m_startItem, -1 );
939  sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
940  frame()->GetScreen()->m_Route_Layer_BOTTOM );
941 
942  m_router->UpdateSizes( sizes );
943 
944  if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
945  {
947  highlightNet( false );
948  controls()->SetAutoPan( false );
949  return false;
950  }
951 
952  m_endItem = nullptr;
954 
955  frame()->UndoRedoBlock( true );
956 
957  return true;
958 }
959 
960 
962 {
964 
966  controls()->SetAutoPan( false );
967  controls()->ForceCursorPosition( false );
968  frame()->UndoRedoBlock( false );
969  highlightNet( false );
970 
971  return true;
972 }
973 
974 
976 {
977  if( !prepareInteractive() )
978  return;
979 
980  auto setCursor =
981  [&]()
982  {
984  };
985 
986  // Set initial cursor
987  setCursor();
988 
989  while( TOOL_EVENT* evt = Wait() )
990  {
991  setCursor();
992 
993  // Don't crash if we missed an operation that cancelled routing.
994  if( !m_router->RoutingInProgress() )
995  {
996  if( evt->IsCancelInteractive() )
997  m_cancelled = true;
998 
999  break;
1000  }
1001 
1002  handleCommonEvents( *evt );
1003 
1004  if( evt->IsMotion() )
1005  {
1006  m_router->SetOrthoMode( evt->Modifier( MD_CTRL ) );
1007  updateEndItem( *evt );
1009  }
1010  else if( evt->IsAction( &ACT_UndoLastSegment ) )
1011  {
1013  updateEndItem( *evt );
1015  }
1016  else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
1017  {
1018  updateEndItem( *evt );
1019  bool needLayerSwitch = m_router->IsPlacingVia();
1020  bool forceFinish = evt->Modifier( MD_SHIFT );
1021 
1022  if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) )
1023  {
1024  break;
1025  }
1026 
1027  if( needLayerSwitch )
1029 
1030  // Synchronize the indicated layer
1032  updateEndItem( *evt );
1034  m_startItem = nullptr;
1035  }
1036  else if( evt->IsAction( &ACT_SwitchRounding ) )
1037  {
1039  updateEndItem( *evt );
1040  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1041  }
1042  else if( evt->IsAction( &ACT_SwitchPosture ) )
1043  {
1044  m_router->FlipPosture();
1045  updateEndItem( *evt );
1046  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1047  }
1048  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1049  {
1050  m_router->SwitchLayer( frame()->GetActiveLayer() );
1051  updateEndItem( *evt );
1052  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
1053  }
1054  else if( evt->IsAction( &ACT_EndTrack ) || evt->IsDblClick( BUT_LEFT ) )
1055  {
1056  // Stop current routing:
1058  break;
1059  }
1060  else if( evt->IsCancelInteractive() || evt->IsActivate()
1061  || evt->IsUndoRedo()
1062  || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
1063  {
1064  if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
1065  m_cancelled = true;
1066 
1067  if( evt->IsActivate() && !evt->IsMoveTool() )
1068  m_cancelled = true;
1069 
1070  break;
1071  }
1072  else if( evt->IsClick( BUT_RIGHT ) )
1073  {
1075  }
1076  else
1077  {
1078  evt->SetPassEvent();
1079  }
1080  }
1081 
1083  m_router->StopRouting();
1084 
1086 }
1087 
1088 
1090 {
1091  PNS::SIZES_SETTINGS sizes = m_router->Sizes();
1092  DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
1093 
1094  if( settingsDlg.ShowModal() == wxID_OK )
1095  {
1096  m_router->UpdateSizes( sizes );
1097  m_savedSizes = sizes;
1098 
1100  bds.SetCustomDiffPairWidth( sizes.DiffPairWidth() );
1101  bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
1102  bds.SetCustomDiffPairViaGap( sizes.DiffPairViaGap() );
1103  }
1104 
1105  return 0;
1106 }
1107 
1108 
1110 {
1111  DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
1112 
1113  settingsDlg.ShowModal();
1114 
1115  return 0;
1116 }
1117 
1118 
1120 {
1121  PNS::PNS_MODE mode = aEvent.Parameter<PNS::PNS_MODE>();
1122  PNS::ROUTING_SETTINGS& settings = m_router->Settings();
1123 
1124  settings.SetMode( mode );
1125 
1126  return 0;
1127 }
1128 
1129 
1131 {
1132  return m_router->Settings().Mode();
1133 }
1134 
1135 
1137 {
1140 }
1141 
1142 
1143 int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
1144 {
1145  PNS::ROUTER_MODE mode = aEvent.Parameter<PNS::ROUTER_MODE>();
1146  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
1147 
1148  // Deselect all items
1150 
1151  std::string tool = aEvent.GetCommandStr().get();
1152  frame->PushTool( tool );
1153  Activate();
1154 
1155  m_router->SetMode( mode );
1156 
1157  VIEW_CONTROLS* ctls = getViewControls();
1158  ctls->ShowCursor( true );
1159  ctls->ForceCursorPosition( false );
1160  m_cancelled = false;
1161 
1162  // Prime the pump
1163  if( aEvent.HasPosition() )
1164  m_toolMgr->PrimeTool( ctls->GetCursorPosition( false ) );
1165 
1166  auto setCursor =
1167  [&]()
1168  {
1170  };
1171 
1172  // Set initial cursor
1173  setCursor();
1174 
1175  // Main loop: keep receiving events
1176  while( TOOL_EVENT* evt = Wait() )
1177  {
1178  setCursor();
1179 
1180  if( evt->IsCancelInteractive() )
1181  {
1182  frame->PopTool( tool );
1183  break;
1184  }
1185  else if( evt->IsActivate() )
1186  {
1187  if( evt->IsMoveTool() )
1188  {
1189  // leave ourselves on the stack so we come back after the move
1190  break;
1191  }
1192  else
1193  {
1194  frame->PopTool( tool );
1195  break;
1196  }
1197  }
1198  else if( evt->Action() == TA_UNDO_REDO_PRE )
1199  {
1200  m_router->ClearWorld();
1201  }
1202  else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
1203  {
1204  m_router->SyncWorld();
1205  }
1206  else if( evt->IsMotion() )
1207  {
1208  updateStartItem( *evt );
1209  }
1210  else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
1211  {
1212  updateStartItem( *evt, true );
1214  }
1215  else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
1216  {
1217  updateStartItem( *evt, true );
1219  }
1220  else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
1221  {
1222  updateStartItem( *evt, true );
1223  breakTrack( );
1224  }
1225  else if( evt->IsClick( BUT_LEFT )
1226  || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
1227  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
1228  {
1229  if( evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
1230  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
1231  {
1232  mode = evt->Parameter<PNS::ROUTER_MODE>();
1233  }
1234 
1235  updateStartItem( *evt );
1236 
1237  if( evt->HasPosition() )
1238  {
1239  if( evt->Modifier( MD_CTRL ) )
1241  else
1242  performRouting();
1243  }
1244  }
1245  else if( evt->IsAction( &ACT_PlaceThroughVia ) )
1246  {
1248  }
1249  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1250  {
1252  updateStartItem( *evt );
1253  }
1254  else if( evt->IsKeyPressed() )
1255  {
1256  // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
1257  // event so we need to process the wxEVT_CHAR event that will follow as long as we
1258  // pass the event.
1259  evt->SetPassEvent();
1260  }
1261  else if( evt->IsClick( BUT_RIGHT ) )
1262  {
1264  }
1265  else
1266  {
1267  evt->SetPassEvent();
1268  }
1269 
1270  if( m_cancelled )
1271  {
1272  frame->PopTool( tool );
1273  break;
1274  }
1275  }
1276 
1277  // Store routing settings till the next invocation
1279 
1280  return 0;
1281 }
1282 
1283 
1285 {
1286  VIEW_CONTROLS* ctls = getViewControls();
1287 
1288  if( m_startItem && m_startItem->IsLocked() )
1289  {
1290  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1291  wxOK | wxCANCEL | wxICON_WARNING );
1292  dlg.SetOKLabel( _( "Drag Anyway" ) );
1293  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1294 
1295  if( dlg.ShowModal() == wxID_CANCEL )
1296  return;
1297  }
1298 
1299  bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1300 
1301  if( !dragStarted )
1302  return;
1303 
1304  if( m_startItem && m_startItem->Net() >= 0 )
1305  highlightNet( true, m_startItem->Net() );
1306 
1307  ctls->SetAutoPan( true );
1309  frame()->UndoRedoBlock( true );
1310 
1311  while( TOOL_EVENT* evt = Wait() )
1312  {
1313  ctls->ForceCursorPosition( false );
1314 
1315  if( evt->IsMotion() )
1316  {
1317  updateEndItem( *evt );
1319  }
1320  else if( evt->IsClick( BUT_LEFT ) )
1321  {
1323  break;
1324  }
1325  else if( evt->IsClick( BUT_RIGHT ) )
1326  {
1328  }
1329  else if( evt->IsCancelInteractive() || evt->IsActivate() || evt->IsUndoRedo() )
1330  {
1331  if( evt->IsCancelInteractive() && !m_startItem )
1332  m_cancelled = true;
1333 
1334  if( evt->IsActivate() && !evt->IsMoveTool() )
1335  m_cancelled = true;
1336 
1337  break;
1338  }
1339  else
1340  {
1341  evt->SetPassEvent();
1342  }
1343 
1344  handleCommonEvents( *evt );
1345  }
1346 
1347  if( m_router->RoutingInProgress() )
1348  m_router->StopRouting();
1349 
1350  m_startItem = nullptr;
1351 
1352  m_gridHelper->SetAuxAxes( false );
1353  frame()->UndoRedoBlock( false );
1354  ctls->SetAutoPan( false );
1355  ctls->ForceCursorPosition( false );
1356  highlightNet( false );
1357 }
1358 
1359 
1361 {
1362  /*
1363  * If the collection contains a trivial line corner (two connected segments)
1364  * or a non-fanout-via (a via with no more than two connected segments), then
1365  * trim the collection down to a single item (which one won't matter since
1366  * they're all connected).
1367  */
1368 
1369  // First make sure we've got something that *might* match.
1370  int vias = aCollector.CountType( PCB_VIA_T );
1371  int traces = aCollector.CountType( PCB_TRACE_T );
1372  int arcs = aCollector.CountType( PCB_ARC_T );
1373 
1374  if( arcs > 0 || vias > 1 || traces > 2 || vias + traces < 1 )
1375  return;
1376 
1377  // Fetch first TRACK (via or trace) as our reference
1378  TRACK* reference = nullptr;
1379 
1380  for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
1381  reference = dynamic_cast<TRACK*>( aCollector[i] );
1382 
1383  int refNet = reference->GetNetCode();
1384 
1385  wxPoint refPoint( aPt.x, aPt.y );
1386  STATUS_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
1387 
1388  if( flags & STARTPOINT )
1389  refPoint = reference->GetStart();
1390  else if( flags & ENDPOINT )
1391  refPoint = reference->GetEnd();
1392 
1393  // Check all items to ensure that any TRACKs are co-terminus with the reference and on
1394  // the same net.
1395  for( int i = 0; i < aCollector.GetCount(); i++ )
1396  {
1397  TRACK* neighbor = dynamic_cast<TRACK*>( aCollector[i] );
1398 
1399  if( neighbor && neighbor != reference )
1400  {
1401  if( neighbor->GetNetCode() != refNet )
1402  return;
1403 
1404  if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
1405  return;
1406  }
1407  }
1408 
1409  // Selection meets criteria; trim it to the reference item.
1410  aCollector.Empty();
1411  aCollector.Append( reference );
1412 }
1413 
1414 
1416 {
1418  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1419 
1420  if( selection.Size() == 1 )
1421  {
1422  const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
1423 
1424  if( item->Type() == PCB_TRACE_T
1425  || item->Type() == PCB_VIA_T
1426  || item->Type() == PCB_FOOTPRINT_T )
1427  {
1428  return true;
1429  }
1430  }
1431 
1432  return false;
1433 }
1434 
1435 
1437 {
1438  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1439 
1440  if( selection.Empty() )
1442 
1443  if( selection.Size() != 1 )
1444  return 0;
1445 
1446  const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
1447 
1448  if( item->Type() != PCB_TRACE_T
1449  && item->Type() != PCB_VIA_T
1450  && item->Type() != PCB_FOOTPRINT_T )
1451  {
1452  return 0;
1453  }
1454 
1455  Activate();
1456 
1458  m_router->SyncWorld();
1459  m_startItem = nullptr;
1460 
1461  PNS::ITEM* startItem = nullptr;
1462  PNS::ITEM_SET itemsToDrag;
1463  const FOOTPRINT* footprint = nullptr;
1464 
1465  if( item->Type() == PCB_FOOTPRINT_T )
1466  {
1467  footprint = static_cast<const FOOTPRINT*>(item);
1468 
1469  for( const PAD* pad : footprint->Pads() )
1470  {
1471  PNS::ITEM* solid = m_router->GetWorld()->FindItemByParent( pad );
1472 
1473  if( solid )
1474  itemsToDrag.Add( solid );
1475  }
1476  }
1477  else
1478  {
1479  startItem = m_router->GetWorld()->FindItemByParent( item );
1480 
1481  if( startItem)
1482  itemsToDrag.Add( startItem );
1483  }
1484 
1485  if( startItem && startItem->IsLocked() )
1486  {
1487  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1488  wxOK | wxCANCEL | wxICON_WARNING );
1489  dlg.SetOKLabel( _( "Drag Anyway" ) );
1490  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1491 
1492  if( dlg.ShowModal() == wxID_CANCEL )
1493  return 0;
1494  }
1495 
1496  VECTOR2I p0 = controls()->GetCursorPosition( false );
1497  VECTOR2I p = p0;
1498 
1499  if( startItem )
1500  p = snapToItem( true, startItem, p0 );
1501 
1502  int dragMode = aEvent.Parameter<int64_t> ();
1503 
1504  bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
1505 
1506  if( !dragStarted )
1507  return 0;
1508 
1509  m_gridHelper->SetAuxAxes( true, p );
1510  controls()->ShowCursor( true );
1511  controls()->ForceCursorPosition( false );
1512  controls()->SetAutoPan( true );
1513  frame()->UndoRedoBlock( true );
1514 
1515  view()->ClearPreview();
1516  view()->InitPreview();
1517 
1518  auto setCursor =
1519  [&]()
1520  {
1522  };
1523 
1524  // Set initial cursor
1525  setCursor();
1526 
1527  while( TOOL_EVENT* evt = Wait() )
1528  {
1529  setCursor();
1530 
1531  if( evt->IsCancelInteractive() )
1532  {
1533  break;
1534  }
1535  else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
1536  {
1537  updateEndItem( *evt );
1539 
1540  if( footprint )
1541  {
1542  VECTOR2I offset = m_endSnapPoint - p;
1543  BOARD_ITEM* previewItem;
1544 
1545  view()->ClearPreview();
1546 
1547  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1548  {
1549  previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() );
1550 
1551  if( drawing->Type() == PCB_FP_SHAPE_T )
1552  {
1553  FP_SHAPE* shape = static_cast<FP_SHAPE*>( previewItem );
1554  shape->PCB_SHAPE::Move( (wxPoint) offset );
1555  }
1556  else
1557  {
1558  previewItem->Move( offset );
1559  }
1560 
1561  view()->AddToPreview( previewItem );
1562  view()->Hide( drawing, true );
1563  }
1564 
1565  previewItem = static_cast<BOARD_ITEM*>( footprint->Reference().Clone() );
1566  previewItem->Move( offset );
1567  view()->AddToPreview( previewItem );
1568  view()->Hide( &footprint->Reference() );
1569 
1570  previewItem = static_cast<BOARD_ITEM*>( footprint->Value().Clone() );
1571  previewItem->Move( offset );
1572  view()->AddToPreview( previewItem );
1573  view()->Hide( &footprint->Value() );
1574 
1575  for( ZONE* zone : footprint->Zones() )
1576  {
1577  previewItem = static_cast<BOARD_ITEM*>( zone->Clone() );
1578  previewItem->Move( offset );
1579  view()->AddToPreview( previewItem );
1580  view()->Hide( zone, true );
1581  }
1582  }
1583  }
1584  else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
1585  {
1586  updateEndItem( *evt );
1588  break;
1589  }
1590  else if( evt->Category() == TC_COMMAND )
1591  {
1592  // disallow editing commands
1593  if( evt->IsAction( &ACTIONS::cut )
1594  || evt->IsAction( &ACTIONS::copy )
1595  || evt->IsAction( &ACTIONS::paste )
1596  || evt->IsAction( &ACTIONS::pasteSpecial ) )
1597  {
1598  wxBell();
1599  }
1600  }
1601  }
1602 
1603  if( footprint )
1604  {
1605  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1606  view()->Hide( drawing, false );
1607 
1608  view()->Hide( &footprint->Reference(), false );
1609  view()->Hide( &footprint->Value(), false );
1610 
1611  for( ZONE* zone : footprint->Zones() )
1612  view()->Hide( zone, false );
1613 
1614  view()->ClearPreview();
1615  view()->ShowPreview( false );
1616  }
1617 
1618  if( m_router->RoutingInProgress() )
1619  m_router->StopRouting();
1620 
1621  m_gridHelper->SetAuxAxes( false );
1622  controls()->SetAutoPan( false );
1623  controls()->ForceCursorPosition( false );
1624  frame()->UndoRedoBlock( false );
1625 
1626  return 0;
1627 }
1628 
1629 
1631 {
1632  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1633 
1634  if( selection.Size() != 1 )
1635  return 0;
1636 
1637  const BOARD_CONNECTED_ITEM* item = static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
1638 
1639  if( item->Type() != PCB_TRACE_T )
1640  return 0;
1641 
1642  Activate();
1643 
1645  m_router->SyncWorld();
1647 
1648  TOOL_MANAGER* toolManager = frame()->GetToolManager();
1649 
1650  if( toolManager->IsContextMenuActive() )
1651  {
1652  // If we're here from a context menu then we need to get the position of the
1653  // cursor when the context menu was invoked. This is used to figure out the
1654  // break point on the track.
1655  VECTOR2I CurrPos = toolManager->GetMenuCursorPos();
1656  m_startSnapPoint = snapToItem( true, m_startItem, toolManager->GetMenuCursorPos() );
1657  }
1658  else
1659  {
1660  // If we're here from a hotkey, then get the current mouse position so we know
1661  // where to break the track.
1662  m_startSnapPoint = snapToItem( true, m_startItem, controls()->GetCursorPosition() );
1663  }
1664 
1665  if( m_startItem && m_startItem->IsLocked() )
1666  {
1667  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1668  wxOK | wxCANCEL | wxICON_WARNING );
1669  dlg.SetOKLabel( _( "Break Track" ) );
1670  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1671 
1672  if( dlg.ShowModal() == wxID_CANCEL )
1673  return 0;
1674  }
1675 
1676  frame()->UndoRedoBlock( true );
1677  breakTrack();
1678 
1679  if( m_router->RoutingInProgress() )
1680  m_router->StopRouting();
1681 
1682  frame()->UndoRedoBlock( false );
1683 
1684  return 0;
1685 }
1686 
1687 
1689 {
1691  DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
1692 
1693  if( sizeDlg.ShowModal() )
1694  {
1695  bds.UseCustomTrackViaSize( true );
1696 
1697  TOOL_EVENT dummy;
1699  }
1700 
1701  return 0;
1702 }
1703 
1704 
1706 {
1707  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
1708 
1709  if( !m_router->GetCurrentNets().empty() )
1710  m_iface->ImportSizes( sizes, nullptr, m_router->GetCurrentNets()[0] );
1711 
1712  m_router->UpdateSizes( sizes );
1713 
1714  // Changing the track width can affect the placement, so call the
1715  // move routine without changing the destination
1717 
1718  return 0;
1719 }
1720 
1721 
1723 {
1725 
1735 
1741 
1776 
1779 }
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:113
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:62
const wxString & FailureReason() const
Definition: pns_router.h:227
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables 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 ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION)
Show the infobar with the provided message and icon for a specific period of time.
Definition: infobar.cpp:109
void Hide(VIEW_ITEM *aItem, bool aHide=true)
Temporarily hides the item in the view (e.g.
Definition: view.cpp:1480
ITEM.
Definition: pns_item.h:54
static TOOL_ACTION layerInner26
Definition: pcb_actions.h:277
void AddStandardSubMenus(TOOL_MENU &aMenu)
Function CreateBasicMenu.
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
BOARD * GetBoard() const
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: fp_text.cpp:355
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Definition: base_units.cpp:123
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
Definition: track.h:354
void SetMode(PNS_MODE aMode)
Sets the routing mode.
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox
Definition: confirm.cpp:54
void SetTrackWidthIndex(unsigned aIndex)
Function SetTrackWidthIndex sets the current track width list index to aIndex.
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:185
int GetNetCode() const
Function GetNetCode.
static TOOL_ACTION layerNext
Definition: pcb_actions.h:283
PNS::PNS_MODE GetRouterMode()
static TOOL_ACTION layerInner2
Definition: pcb_actions.h:253
int MainLoop(const TOOL_EVENT &aEvent)
static TOOL_ACTION selectLayerPair
Definition: pcb_actions.h:132
PCB_IO is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
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."), via_microvia_xpm, AF_NONE,(void *) VIA_ACTION_FLAGS::MICROVIA)
PCB_EDIT_FRAME & m_frame
GRID_HELPER * m_gridHelper
Definition: pns_tool_base.h:76
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
BOARD * board() const
int GetCurrentViaDrill() const
Function GetCurrentViaDrill.
#define LEGACY_HK_NAME(x)
Definition: actions.h:35
int DpDimensionsDialog(const TOOL_EVENT &aEvent)
Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:175
PNS_MODE
Routing modes
static TOOL_ACTION layerInner5
Definition: pcb_actions.h:256
Normal via
Definition: router_tool.cpp:67
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:44
bool finishInteractive()
void SetCustomDiffPairViaGap(int aGap)
Function SetCustomDiffPairViaGap Sets custom via gap for differential pairs (i.e.
blind/buried via
Definition: router_tool.cpp:68
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:43
This file is part of the common library.
static TOOL_ACTION layerInner6
Definition: pcb_actions.h:257
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
Definition: board_item.h:86
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:197
std::vector< int > m_TrackWidthList
static TOOL_ACTION layerInner7
Definition: pcb_actions.h:258
static TOOL_ACTION layerInner8
Definition: pcb_actions.h:259
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1554
const wxPoint & GetStart() const
Definition: track.h:116
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)
void CommitRouting()
Definition: pns_router.cpp:440
SELECTION_TOOL.
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.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:141
Tool is invoked after being inactive.
Definition: tool_base.h:81
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
void UseCustomDiffPairDimensions(bool aEnabled)
Function UseCustomDiffPairDimensions Enables/disables custom differential pair dimensions.
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:773
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
SIZES_SETTINGS m_savedSizes
Definition: pns_tool_base.h:68
void SyncWorld()
Definition: pns_router.cpp:93
bool IsPlacingVia() const
Definition: pns_router.cpp:537
void InitPreview()
Definition: view.cpp:1547
void ToggleRounded()
Definition: pns_router.cpp:546
Microvia
Definition: router_tool.cpp:71
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
bool IsKeyPressed() const
Definition: tool_event.h:352
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:141
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:68
static TOOL_ACTION routerHighlightMode
Actions to enable switching modes via hotkey assignments.
Definition: pcb_actions.h:200
const std::vector< int > GetCurrentNets() const
Definition: pns_router.cpp:509
T Opt() const
Definition: minoptmax.h:33
void PrimeTool(const VECTOR2D &aPosition)
Function PrimeTool() "Primes" a tool by sending a cursor left-click event with the mouse position set...
static TOOL_ACTION trackViaSizeChanged
Definition: pcb_actions.h:299
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:559
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:140
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."), change_entry_orient_xpm)
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Moves 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:94
static const TOOL_ACTION ACT_SwitchRounding("pcbnew.InteractiveRouter.SwitchRounding", AS_CONTEXT, 0, LEGACY_HK_NAME("Switch Corner Rounding"), _("Switch Corner Rounding"), _("Switches the corner type of the currently routed track."), switch_corner_rounding_shape_xpm)
void UndoRedoBlock(bool aBlock=true)
Function UndoRedoBlock Enables/disable undo and redo operations.
void SetViaDrill(int aDrill)
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:219
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
bool IsContextMenuActive()
True while processing a context menu.
Definition: tool_manager.h:407
void SwitchLayer(int layer)
Definition: pns_router.cpp:486
int CountType(KICAD_T aType)
Function CountType counts the number of items matching aType.
Definition: collector.h:252
void breakTrack()
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 TOOL_ACTION layerInner3
Definition: pcb_actions.h:254
BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected and have...
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
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))
Function Go()
int ChangeRouterMode(const TOOL_EVENT &aEvent)
void SetOrthoMode(bool aEnable)
Definition: pns_router.cpp:552
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
static TOOL_ACTION layerInner11
Definition: pcb_actions.h:262
void SetCurrentCursor(KICURSOR cursor)
Function SetCurrentCursor Set the current cursor shape for this panel.
const VECTOR2I snapToItem(bool aEnabled, ITEM *aItem, VECTOR2I aP)
static const TOOL_ACTION ACT_EndTrack("pcbnew.InteractiveRouter.EndTrack", AS_CONTEXT, WXK_END, "", _("Finish Track"), _("Stops laying the current track."), checked_ok_xpm)
void ToggleViaPlacement()
Definition: pns_router.cpp:499
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
void handleCommonEvents(const TOOL_EVENT &evt)
const BITMAP_OPAQUE via_microvia_xpm[1]
PADS & Pads()
Definition: footprint.h:182
bool IsAction(const TOOL_ACTION *aAction) const
Function IsAction() Tests if the event contains an action issued upon activation of the given TOOL_AC...
Definition: tool_event.cpp:67
void ClearWorld()
Definition: pns_router.cpp:102
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:473
static TOOL_ACTION layerTop
Definition: pcb_actions.h:251
int Start() const
Definition: pns_layerset.h:83
void ShowPreview(bool aShow=true)
Definition: view.cpp:1568
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:123
FP_TEXT & Reference()
Definition: footprint.h:474
PCB_BASE_EDIT_FRAME * frame() const
void UndoLastSegment()
Definition: pns_router.cpp:431
virtual PCB_LAYER_ID GetActiveLayer() const
virtual void updateStartItem(const TOOL_EVENT &aEvent, bool aIgnorePads=false)
static TOOL_ACTION layerInner23
Definition: pcb_actions.h:274
void SetViaSizeIndex(unsigned aIndex)
Function SetViaSizeIndex sets the current via size list index to aIndex.
MINOPTMAX< int > m_Value
Definition: drc_rule.h:141
int onViaCommand(const TOOL_EVENT &aEvent)
static VIATYPE getViaTypeFromFlags(int aFlags)
TOOL_MANAGER.
Definition: tool_manager.h:51
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:104
virtual void Reset(RESET_REASON aReason)=0
Function Reset() Brings the tool to a known, initial state.
FP_ZONES & Zones()
Definition: footprint.h:188
static TOOL_ACTION copy
Definition: actions.h:70
ACTION_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes.
virtual void updateEndItem(const TOOL_EVENT &aEvent)
bool prepareInteractive()
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0))
PCB_LAYER_ID
A quick note on layer IDs:
static TOOL_ACTION routerSettingsDialog
Activation of the Push and Shove settings dialogs.
Definition: pcb_actions.h:196
#define _(s)
LSET is a set of PCB_LAYER_IDs.
static TOOL_ACTION layerInner13
Definition: pcb_actions.h:264
const PCBNEW_SELECTION & selection() const
void performRouting()
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
Definition: pns_router.cpp:572
static TOOL_ACTION layerPrev
Definition: pcb_actions.h:284
static const TOOL_ACTION ACT_AutoEndRoute("pcbnew.InteractiveRouter.AutoEndRoute", AS_CONTEXT, 'F', "", _("Auto-finish Track"), _("Automagically finishes laying the current track."))
const BITMAP_OPAQUE select_w_layer_xpm[1]
static const TOOL_ACTION ACT_UndoLastSegment("pcbnew.InteractiveRouter.UndoLastSegment", AS_CONTEXT, WXK_BACK, "", _("Undo last segment"), _("Stops laying the current track."), checked_ok_xpm)
static PCB_LAYER_ID getTargetLayerFromEvent(const TOOL_EVENT &aEvent)
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
Definition: pns_node.cpp:1455
void update() override
Update menu state stub.
virtual void Move(const wxPoint &aMoveVector)
Function Move move this object.
Definition: board_item.h:292
unsigned GetViaSizeIndex() const
Function GetViaSizeIndex.
virtual void PopTool(const std::string &actionName)
static TOOL_ACTION layerInner25
Definition: pcb_actions.h:276
int Net() const
Definition: pns_item.h:150
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."), width_track_xpm)
static TOOL_ACTION layerInner18
Definition: pcb_actions.h:269
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
virtual int GetTopLayer() const
Definition: view.cpp:829
bool UseNetClassVia() const
Function UseNetClassVia returns true if netclass values should be used to obtain appropriate via size...
void SetCustomDiffPairWidth(int aWidth)
Function SetCustomDiffPairWidth Sets custom track width for differential pairs (i....
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assigns an icon for the entry.
Definition: action_menu.cpp:71
TOOL_EVENT.
Definition: tool_event.h:171
ITEM * m_startItem
Definition: pns_tool_base.h:69
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:404
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
FOOTPRINT * footprint() const
unsigned GetTrackWidthIndex() const
Function GetTrackWidthIndex.
DIFF_PAIR_MENU(PCB_EDIT_FRAME &aFrame)
static TOOL_ACTION layerInner30
Definition: pcb_actions.h:281
void ClearPreview()
Definition: view.cpp:1535
static TOOL_ACTION cut
Definition: actions.h:69
KIGFX::PCB_VIEW * view() const
unsigned STATUS_FLAGS
Definition: eda_item.h:142
static TOOL_ACTION layerInner29
Definition: pcb_actions.h:280
ROUTER * m_router
Definition: pns_tool_base.h:78
bool CanInlineDrag()
PNS_MODE Mode() const
Returns the routing mode.
VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (such a...
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:39
void switchLayerOnViaPlacement()
static TOOL_ACTION layerInner10
Definition: pcb_actions.h:261
DRAWINGS & GraphicalItems()
Definition: footprint.h:185
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
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: track.cpp:401
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
int SettingsDialog(const TOOL_EVENT &aEvent)
void SetDiffPairIndex(unsigned aIndex)
Function SetDiffPairIndex.
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."), select_w_layer_xpm, AF_NONE,(void *)(VIA_ACTION_FLAGS::VIA|VIA_ACTION_FLAGS::SELECT_LAYER))
int CustomTrackWidthDialog(const TOOL_EVENT &aEvent)
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
void SetCustomDiffPairGap(int aGap)
Function SetCustomDiffPairGap Sets custom gap for differential pairs (i.e.
const BITMAP_OPAQUE via_buried_xpm[1]
Definition: via_buried.cpp:55
void ShowInfoBarError(const wxString &aErrorMsg)
const BITMAP_OPAQUE switch_corner_rounding_shape_xpm[1]
static TOOL_ACTION routerWalkaroundMode
Definition: pcb_actions.h:202
void Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:256
static TOOL_ACTION layerInner15
Definition: pcb_actions.h:266
const BITMAP_OPAQUE width_track_via_xpm[1]
int onTrackViaSizeChanged(const TOOL_EVENT &aEvent)
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:205
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:205
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:226
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
static TOOL_ACTION layerInner27
Definition: pcb_actions.h:278
void SetViaType(VIATYPE aViaType)
bool IsNull() const
Definition: drc_rule.h:115
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:120
static TOOL_ACTION inlineBreakTrack
Breaks track when router is not activated.
Definition: pcb_actions.h:138
ACTION_MENU * create() const override
Returns 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:89
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:135
static TOOL_ACTION layerInner20
Definition: pcb_actions.h:271
static TOOL_ACTION pasteSpecial
Definition: actions.h:72
void StopRouting()
Definition: pns_router.cpp:449
virtual void highlightNet(bool aEnabled, int aNetcode=-1)
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."), via_xpm, AF_NONE,(void *) VIA_ACTION_FLAGS::VIA)
EDA_UNITS
Definition: eda_units.h:38
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: eda_item.h:111
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
ROUTER_MODE
Definition: pns_router.h:68
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:70
PCB_EDIT_FRAME & m_frame
static TOOL_ACTION layerInner22
Definition: pcb_actions.h:273
int GetCurrentViaSize() const
Function GetCurrentViaSize.
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:289
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:345
void SetTitle(const wxString &aTitle) override
Sets title for the menu.
Definition: action_menu.cpp:89
KIGFX::VIEW_CONTROLS * controls() const
void SetMode(ROUTER_MODE aMode)
Definition: pns_router.cpp:561
void update() override
Update menu state stub.
STATUS_FLAGS IsPointOnEnds(const wxPoint &point, int min_dist=0) const
Function IsPointOnEnds returns STARTPOINT if point if near (dist = min_dist) start point,...
Definition: track.cpp:185
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:179
VECTOR2I m_endSnapPoint
Definition: pns_tool_base.h:74
LOGGER * Logger()
Definition: pns_router.cpp:531
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:241
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Function CreateSubMenu.
Definition: tool_menu.cpp:52
TOOL_BASE.
Definition: tool_base.h:67
bool IsToolActive() const
Definition: tool_base.cpp:31
static TOOL_ACTION layerInner14
Definition: pcb_actions.h:265
Represents a single user action.
Definition: tool_action.h:44
static TOOL_ACTION layerInner9
Definition: pcb_actions.h:260
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:128
static void NeighboringSegmentFilter(const VECTOR2I &aPt, GENERAL_COLLECTOR &aCollector)
void performDragging(int aMode=PNS::DM_ANY)
bool OfKind(int aKindMask) const
Function OfKind()
Definition: pns_item.h:134
PCB_EDIT_FRAME is the main frame for Pcbnew.
void Clear()
Removes all the entries from the menu (as well as its title).
TOOL_EVENT MakeEvent() const
Returns the event associated with the action (i.e.
Definition: tool_action.h:113
int Size() const
Returns the number of selected parts.
Definition: selection.h:126
bool IsLocked() const
Definition: pns_item.h:242
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
Determines the reason of reset for a tool
Definition: tool_base.h:79
static TOOL_ACTION layerInner16
Definition: pcb_actions.h:267
const wxPoint & GetEnd() const
Definition: track.h:113
std::vector< VIA_DIMENSION > m_ViasDimensionsList
boost::optional< T > OPT
Definition: optional.h:7
int ShowModal() override
Definition: confirm.cpp:96
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
void Activate()
Function Activate() Runs the tool.
WX_INFOBAR * GetInfoBar()
#define ENDPOINT
ends. (Used to support dragging.)
Definition: eda_item.h:112
Implementing DIALOG_TRACK_VIA_SIZE_BASE.
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:259
static TOOL_ACTION layerInner4
Definition: pcb_actions.h:255
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
unsigned GetDiffPairIndex() const
Function GetDiffPairIndex.
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."), via_buried_xpm, AF_NONE,(void *) VIA_ACTION_FLAGS::BLIND_VIA)
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition: tool_event.h:260
void AddLayerPair(int aL1, int aL2)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:76
bool m_MicroViasAllowed
true to allow micro vias
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
void FlipPosture()
Definition: pns_router.cpp:477
const BITMAP_OPAQUE change_entry_orient_xpm[1]
bool RoutingInProgress() const
Definition: pns_router.cpp:114
int KeyCode() const
Definition: tool_event.h:347
static TOOL_ACTION layerInner19
Definition: pcb_actions.h:270
VIATYPE
Definition: track.h:68
Definition: pad.h:59
void SetViaDiameter(int aDiameter)
int getStartLayer(const PNS::ITEM *aItem)
static TOOL_ACTION layerInner1
Definition: pcb_actions.h:252
VECTOR2D GetMenuCursorPos()
Definition: tool_manager.h:436
ROUTER_MODE Mode() const
Definition: pns_router.h:136
bool ImportSizes(PNS::SIZES_SETTINGS &aSizes, PNS::ITEM *aStartItem, int aNet) override
void SetViaType(VIATYPE aViaType)
Definition: track.h:385
static TOOL_ACTION routerShoveMode
Definition: pcb_actions.h:201
NODE * GetWorld() const
Definition: pns_router.h:155
int GetCopperLayerCount() const
Function GetCopperLayerCount.
OPT< int > PairedLayer(int aLayerId)
const BITMAP_OPAQUE width_track_xpm[1]
Definition: width_track.cpp:39
PNS_KICAD_IFACE * m_iface
Definition: pns_tool_base.h:77
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
PCB_LAYER_ID SelectLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Install the dialog box for layer selection.
Definition: sel_layer.cpp:204
const BITMAP_OPAQUE via_xpm[1]
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Function SetActiveLayer will change the currently active layer to aLayer and also update the APPEARAN...
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:200
const BITMAP_OPAQUE checked_ok_xpm[1]
Definition: checked_ok.cpp:51
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:898
static TOOL_ACTION paste
Definition: actions.h:71
VIA_ACTION_FLAGS
Flags used by via tool actions.
Definition: router_tool.cpp:62
std::shared_ptr< DRC_ENGINE > m_DRCEngine
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:274
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:59
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
LAYER_RANGE.
Definition: pns_layerset.h:32
const LAYER_RANGE & Layers() const
Definition: pns_item.h:152
Definition: track.h:83
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:38
void UseCustomTrackViaSize(bool aEnabled)
Function UseCustomTrackViaSize Enables/disables custom track/via size settings.
virtual void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL) override
Function Save will write aBoard to a storage file in a format that this PLUGIN implementation knows a...
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:201
static TOOL_ACTION layerInner12
Definition: pcb_actions.h:263
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."), select_w_layer_xpm, AF_NONE,(void *)(VIA_ACTION_FLAGS::BLIND_VIA|VIA_ACTION_FLAGS::SELECT_LAYER))
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:556
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:287
int GetCurrentLayer() const
Definition: pns_router.cpp:520
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:182