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 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/numdlg.h>
23 #include <core/optional.h>
24 #include <functional>
25 using namespace std::placeholders;
26 #include "class_board.h"
27 #include <pcb_edit_frame.h>
28 #include <id.h>
29 #include <macros.h>
30 #include <pcbnew_id.h>
31 #include <view/view_controls.h>
32 #include <pcb_layer_widget.h>
33 #include <pcb_painter.h>
37 #include <base_units.h>
38 #include <confirm.h>
39 #include <bitmaps.h>
40 #include <collectors.h>
41 #include <tool/action_menu.h>
42 #include <tool/tool_manager.h>
43 #include <tool/grid_menu.h>
44 #include <tool/zoom_menu.h>
45 #include <tools/pcb_actions.h>
46 #include <tools/selection_tool.h>
47 #include <tools/grid_helper.h>
48 
49 #include "router_tool.h"
50 #include "pns_segment.h"
51 #include "pns_router.h"
52 
53 using namespace KIGFX;
54 
59 {
60  // Via type
61  VIA_MASK = 0x03,
62  VIA = 0x00,
63  BLIND_VIA = 0x01,
64  MICROVIA = 0x02,
65 
66  // Select layer
68 };
69 
70 
71 // Actions, being statically-defined, require specialized I18N handling. We continue to
72 // use the _() macro so that string harvesting by the I18N framework doesn't have to be
73 // specialized, but we don't translate on initialization and instead do it in the getters.
74 
75 #undef _
76 #define _(s) s
77 
78 static const TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack",
79  AS_CONTEXT,
80  WXK_END, "",
81  _( "Finish Track" ), _( "Stops laying the current track." ),
82  checked_ok_xpm );
83 
84 static const TOOL_ACTION ACT_AutoEndRoute( "pcbnew.InteractiveRouter.AutoEndRoute",
85  AS_CONTEXT,
86  'F', "",
87  _( "Auto-finish Track" ), _( "Automagically finishes laying the current track." ) );
88 
89 static const TOOL_ACTION ACT_PlaceThroughVia( "pcbnew.InteractiveRouter.PlaceVia",
90  AS_CONTEXT,
91  'V', LEGACY_HK_NAME( "Add Through Via" ),
92  _( "Place Through Via" ),
93  _( "Adds a through-hole via at the end of currently routed track." ),
94  via_xpm, AF_NONE, (void*) VIA_ACTION_FLAGS::VIA );
95 
96 static const TOOL_ACTION ACT_PlaceBlindVia( "pcbnew.InteractiveRouter.PlaceBlindVia",
97  AS_CONTEXT,
98  MD_ALT + MD_SHIFT + 'V', LEGACY_HK_NAME( "Add Blind/Buried Via" ),
99  _( "Place Blind/Buried Via" ),
100  _( "Adds a blind or buried via at the end of currently routed track."),
101  via_buried_xpm, AF_NONE, (void*) VIA_ACTION_FLAGS::BLIND_VIA );
102 
103 static const TOOL_ACTION ACT_PlaceMicroVia( "pcbnew.InteractiveRouter.PlaceMicroVia",
104  AS_CONTEXT,
105  MD_CTRL + 'V', LEGACY_HK_NAME( "Add MicroVia" ),
106  _( "Place Microvia" ), _( "Adds a microvia at the end of currently routed track." ),
107  via_microvia_xpm, AF_NONE, (void*) VIA_ACTION_FLAGS::MICROVIA );
108 
109 static const TOOL_ACTION ACT_SelLayerAndPlaceThroughVia( "pcbnew.InteractiveRouter.SelLayerAndPlaceVia",
110  AS_CONTEXT,
111  '<', LEGACY_HK_NAME( "Select Layer and Add Through Via" ),
112  _( "Select Layer and Place Through Via..." ),
113  _( "Select a layer, then add a through-hole via at the end of currently routed track." ),
114  select_w_layer_xpm, AF_NONE,
116 
117 static const TOOL_ACTION ACT_SelLayerAndPlaceBlindVia( "pcbnew.InteractiveRouter.SelLayerAndPlaceBlindVia",
118  AS_CONTEXT,
119  MD_ALT + '<', LEGACY_HK_NAME( "Select Layer and Add Blind/Buried Via" ),
120  _( "Select Layer and Place Blind/Buried Via..." ),
121  _( "Select a layer, then add a blind or buried via at the end of currently routed track."),
122  select_w_layer_xpm, AF_NONE,
124 
125 static const TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackViaSize",
126  AS_CONTEXT,
127  'Q', LEGACY_HK_NAME( "Custom Track/Via Size" ),
128  _( "Custom Track/Via Size..." ),
129  _( "Shows a dialog for changing the track width and via size." ),
130  width_track_xpm );
131 
132 static const TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture",
133  AS_CONTEXT,
134  '/', LEGACY_HK_NAME( "Switch Track Posture" ),
135  _( "Switch Track Posture" ),
136  _( "Switches posture of the currently routed track." ),
137  change_entry_orient_xpm );
138 
139 #undef _
140 #define _(s) wxGetTranslation((s))
141 
142 
144  TOOL_BASE( "pcbnew.InteractiveRouter" )
145 {
146 }
147 
148 
150 {
151 public:
153  ACTION_MENU( true ),
154  m_frame( aFrame )
155  {
156  SetIcon( width_track_via_xpm );
157  SetTitle( _( "Select Track/Via Width" ) );
158  }
159 
160 protected:
161  ACTION_MENU* create() const override
162  {
163  return new TRACK_WIDTH_MENU( m_frame );
164  }
165 
166  void update() override
167  {
168  EDA_UNITS_T units = m_frame.GetUserUnits();
170  bool useIndex = !bds.m_UseConnectedTrackWidth &&
171  !bds.UseCustomTrackViaSize();
172  wxString msg;
173 
174  Clear();
175 
176  Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
177  _( "Route using the width of the starting track." ), wxITEM_CHECK );
180 
181  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
182  _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
184  useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
185 
186  Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
187  _( "Specify custom track and via sizes" ), wxITEM_CHECK );
189 
190  AppendSeparator();
191 
192  // Append the list of tracks & via sizes
193  for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
194  {
195  int width = bds.m_TrackWidthList[i];
196 
197  if( i == 0 )
198  msg = _( "Track netclass width" );
199  else
200  msg.Printf( _( "Track %s" ), MessageTextFromValue( units, width, true ) );
201 
202  int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
203  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
204  Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
205  }
206 
207  AppendSeparator();
208 
209  for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
210  {
212 
213  if( i == 0 )
214  msg = _( "Via netclass values" );
215  else
216  {
217  if( via.m_Drill > 0 )
218  msg.Printf( _("Via %s, drill %s" ),
219  MessageTextFromValue( units, via.m_Diameter, true ),
220  MessageTextFromValue( units, via.m_Drill, true ) );
221  else
222  msg.Printf( _( "Via %s" ), MessageTextFromValue( units, via.m_Diameter, true ) );
223  }
224 
225  int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
226  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
227  Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
228  }
229  }
230 
231  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
232  {
234  int id = aEvent.GetId();
235 
236  // On Windows, this handler can be called with an event ID not existing in any
237  // menuitem, so only set flags when we have an ID match.
238 
240  {
241  bds.UseCustomTrackViaSize( true );
242  bds.m_UseConnectedTrackWidth = false;
244  }
245  else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
246  {
247  bds.UseCustomTrackViaSize( false );
248  bds.m_UseConnectedTrackWidth = true;
249  }
251  {
252  bds.UseCustomTrackViaSize( false );
253  bds.m_UseConnectedTrackWidth = false;
254  bds.SetViaSizeIndex( 0 );
255  bds.SetTrackWidthIndex( 0 );
256  }
258  {
259  bds.UseCustomTrackViaSize( false );
260  bds.m_UseConnectedTrackWidth = false;
262  }
264  {
265  bds.UseCustomTrackViaSize( false );
266  bds.m_UseConnectedTrackWidth = false;
268  }
269 
270  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
271  }
272 
273 private:
275 };
276 
277 
279 {
280 public:
282  ACTION_MENU( true ),
283  m_frame( aFrame )
284  {
285  SetIcon( width_track_via_xpm );
286  SetTitle( _( "Select Differential Pair Dimensions" ) );
287  }
288 
289 protected:
290  ACTION_MENU* create() const override
291  {
292  return new DIFF_PAIR_MENU( m_frame );
293  }
294 
295  void update() override
296  {
297  EDA_UNITS_T units = m_frame.GetUserUnits();
299 
300  Clear();
301 
302  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
303  _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
305  !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
306 
307  Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
308  _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
310 
311  AppendSeparator();
312 
313  // Append the list of differential pair dimensions
314 
315  // Drop index 0 which is the current netclass dimensions (which are handled above)
316  for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
317  {
319  wxString msg;
320 
321  msg << _( "Width " ) << MessageTextFromValue( units, diffPair.m_Width, true );
322 
323  if( diffPair.m_Gap > 0 )
324  msg << _( ", gap " ) << MessageTextFromValue( units, diffPair.m_Gap, true );
325 
326  if( diffPair.m_ViaGap > 0 )
327  msg << _( ", via gap " ) << MessageTextFromValue( units, diffPair.m_ViaGap, true );
328 
329  int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
330  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
331  Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
332  }
333  }
334 
335  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
336  {
338  int id = aEvent.GetId();
339 
340  // On Windows, this handler can be called with an event ID not existing in any
341  // menuitem, so only set flags when we have an ID match.
342 
344  {
345  bds.UseCustomDiffPairDimensions( true );
346  TOOL_MANAGER* toolManager = m_frame.GetToolManager();
347  toolManager->RunAction( PCB_ACTIONS::routerDiffPairDialog, true );
348  }
350  {
351  bds.UseCustomDiffPairDimensions( false );
352  bds.SetDiffPairIndex( 0 );
353  }
355  {
356  bds.UseCustomDiffPairDimensions( false );
357  // remember that the menu doesn't contain index 0 (which is the netclass values)
359  }
360 
361  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
362  }
363 
364 private:
366 };
367 
368 
370 {
371 public:
373  ACTION_MENU( true ),
374  m_frame( aFrame ), m_mode( aMode ), m_trackViaMenu( aFrame ), m_diffPairMenu( aFrame ),
375  m_zoomMenu( &aFrame ), m_gridMenu( &aFrame )
376  {
377  SetTitle( _( "Interactive Router" ) );
378 
380 
381  AppendSeparator();
382 
385  Add( ACT_EndTrack );
387 
390 
391 // Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry.
398 
399  AppendSeparator();
400 
401  Add( &m_trackViaMenu );
402 
404  Add( &m_diffPairMenu );
405 
407 
408  AppendSeparator();
409 
410  Add( &m_zoomMenu );
411  Add( &m_gridMenu );
412  }
413 
414 private:
415  ACTION_MENU* create() const override
416  {
417  return new ROUTER_TOOL_MENU( m_frame, m_mode );
418  }
419 
426 };
427 
428 
430 {
432 }
433 
434 
436 {
438  return true;
439 }
440 
441 
443 {
444  if( aReason == RUN )
445  TOOL_BASE::Reset( aReason );
446 }
447 
448 
450 {
451 #ifdef DEBUG
452  if( aEvent.IsKeyPressed() )
453  {
454  switch( aEvent.KeyCode() )
455  {
456  case '0':
457  wxLogTrace( "PNS", "saving drag/route log...\n" );
458  m_router->DumpLog();
459  break;
460  }
461  }
462 #endif
463 }
464 
465 
467 {
468  int tl = getView()->GetTopLayer();
469 
470  if( m_startItem )
471  {
472  const LAYER_RANGE& ls = m_startItem->Layers();
473 
474  if( ls.Overlaps( tl ) )
475  return tl;
476  else
477  return ls.Start();
478  }
479 
480  return tl;
481 }
482 
483 
485 {
486  int al = frame()->GetActiveLayer();
487  int cl = m_router->GetCurrentLayer();
488 
489  if( cl != al )
490  {
491  m_router->SwitchLayer( al );
492  }
493 
494  OPT<int> newLayer = m_router->Sizes().PairedLayer( cl );
495 
496  if( !newLayer )
497  newLayer = m_router->Sizes().GetLayerTop();
498 
499  m_router->SwitchLayer( *newLayer );
500  frame()->SetActiveLayer( ToLAYER_ID( *newLayer ) );
501 }
502 
503 
504 static VIATYPE_T getViaTypeFromFlags( int aFlags )
505 {
506  switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
507  {
508  case VIA_ACTION_FLAGS::VIA: return VIA_THROUGH;
511  default:
512  wxASSERT_MSG( false, "Unhandled via type" );
513  return VIA_THROUGH;
514  }
515 }
516 
517 
519 {
520  const int actViaFlags = aEvent.Parameter<intptr_t>();
521 
522  VIATYPE_T viaType = getViaTypeFromFlags( actViaFlags );
523  const bool selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
524 
526 
527  const int layerCount = bds.GetCopperLayerCount();
528  int currentLayer = m_router->GetCurrentLayer();
531 
533 
534  // ask the user for a target layer
535  PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
536 
537  if( selectLayer )
538  {
539  wxPoint dlgPosition = wxGetMousePosition();
540 
541  targetLayer = frame()->SelectLayer( static_cast<PCB_LAYER_ID>( currentLayer ),
542  LSET::AllNonCuMask(), dlgPosition );
543 
544  // Reset the cursor to the position where the event occured
545  controls()->SetCursorPosition( aEvent.HasPosition() ? aEvent.Position() : dlgPosition );
546  }
547 
548  // fixme: P&S supports more than one fixed layer pair. Update the dialog?
549  sizes.ClearLayerPairs();
550 
551  if( !m_router->IsPlacingVia() )
552  {
553  // Cannot place microvias or blind vias if not allowed (obvious)
554  if( ( viaType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
555  {
556  DisplayError( frame(), _( "Blind/buried vias have to be enabled in Board Setup > Design Rules > Constraints." ) );
557  return false;
558  }
559 
560  if( ( viaType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
561  {
562  DisplayError( frame(), _( "Microvias have to be enabled in Board Setup > Design Rules > Constraints." ) );
563  return false;
564  }
565 
566  // Can only place through vias on 2-layer boards
567  if( ( viaType != VIA_THROUGH ) && ( layerCount <= 2 ) )
568  {
569  DisplayError( frame(), _( "Only through vias are allowed on 2 layer boards." ) );
570  return false;
571  }
572 
573  // Can only place microvias if we're on an outer layer, or directly adjacent to one
574  if( ( viaType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount - 2 ) )
575  {
576  DisplayError( frame(), _( "Microvias can be placed only between the outer layers " \
577  "(F.Cu/B.Cu) and the ones directly adjacent to them." ) );
578  return false;
579  }
580  }
581 
582  // Convert blind/buried via to a through hole one, if it goes through all layers
583  if( viaType == VIA_BLIND_BURIED && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
584  || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
585  {
586  viaType = VIA_THROUGH;
587  }
588 
589  switch( viaType )
590  {
591  case VIA_THROUGH:
592  sizes.SetViaDiameter( bds.GetCurrentViaSize() );
593  sizes.SetViaDrill( bds.GetCurrentViaDrill() );
594 
595  if( targetLayer != UNDEFINED_LAYER )
596  {
597  // go from the current layer to the chosen layer
598  sizes.AddLayerPair( currentLayer, targetLayer );
599  }
600  else
601  {
602  // use the default layer pair
603  sizes.AddLayerPair( pairTop, pairBottom );
604  }
605  break;
606 
607  case VIA_MICROVIA:
608  sizes.SetViaDiameter( bds.GetCurrentMicroViaSize() );
609  sizes.SetViaDrill( bds.GetCurrentMicroViaDrill() );
610 
611  wxASSERT_MSG( !selectLayer, "Unexpected select layer for microvia (microvia layers are implicit)" );
612 
613  if( currentLayer == F_Cu || currentLayer == In1_Cu )
614  {
615  // front-side microvia
616  sizes.AddLayerPair( F_Cu, In1_Cu );
617  }
618  else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
619  {
620  // back-side microvia
621  sizes.AddLayerPair( B_Cu, layerCount - 2 );
622  }
623  else
624  {
625  wxASSERT_MSG( false, "Invalid layer pair for microvia (must be on or adjacent to an outer layer)" );
626  }
627  break;
628 
629  case VIA_BLIND_BURIED:
630  sizes.SetViaDiameter( bds.GetCurrentViaSize() );
631  sizes.SetViaDrill( bds.GetCurrentViaDrill() );
632 
633  if( targetLayer != UNDEFINED_LAYER )
634  {
635  // go directly to the user specified layer
636  sizes.AddLayerPair( currentLayer, targetLayer );
637  }
638  else
639  {
640  if( currentLayer == pairTop || currentLayer == pairBottom )
641  {
642  // the current layer is on the defined layer pair,
643  // swap to the other side
644  sizes.AddLayerPair( pairTop, pairBottom );
645  }
646  else
647  {
648  // the current layer is not part of the current layer pair,
649  // so fallback and swap to the top layer of the pair by default
650  sizes.AddLayerPair( pairTop, currentLayer );
651  }
652  }
653  break;
654 
655  default:
656  wxASSERT( false );
657  break;
658  }
659 
660  sizes.SetViaType( viaType );
661 
662  m_router->UpdateSizes( sizes );
664 
665  if( m_router->RoutingInProgress() )
666  updateEndItem( aEvent );
667  else
668  updateStartItem( aEvent );
669 
670  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
671 
672  return 0;
673 }
674 
675 
677 {
678  int routingLayer = getStartLayer( m_startItem );
679 
680  if( !IsCopperLayer( routingLayer ) )
681  {
682  DisplayError( frame(), _( "Tracks on Copper layers only" ) );
683  return false;
684  }
685 
686  PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
687 
688  editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
689 
690  // Force layer visible
691  editFrame->GetLayerManager()->SetLayerVisible( routingLayer, true );
692 
693  // for some reason I don't understand, GetNetclass() may return null sometimes...
694  if( m_startItem && m_startItem->Net() >= 0 &&
696  {
697  highlightNet( true, m_startItem->Net() );
698  // Update track width and via size shown in main toolbar comboboxes
699  editFrame->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() );
700  }
701  else
703 
704  controls()->ForceCursorPosition( false );
705  controls()->SetAutoPan( true );
706 
707  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
708 
709  sizes.Init( board(), m_startItem );
710  sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
711  frame()->GetScreen()->m_Route_Layer_BOTTOM );
712  m_router->UpdateSizes( sizes );
713 
714  if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
715  {
717  highlightNet( false );
718  controls()->SetAutoPan( false );
719  return false;
720  }
721 
722  m_endItem = nullptr;
724 
725  frame()->UndoRedoBlock( true );
726 
727  return true;
728 }
729 
730 
732 {
734 
735  controls()->SetAutoPan( false );
736  controls()->ForceCursorPosition( false );
737  frame()->UndoRedoBlock( false );
738  highlightNet( false );
739 
740  return true;
741 }
742 
743 
745 {
746  if( !prepareInteractive() )
747  return;
748 
749  while( TOOL_EVENT* evt = Wait() )
750  {
751  frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
752 
753  // Don't crash if we missed an operation that cancelled routing.
754  wxCHECK2( m_router->RoutingInProgress(), break );
755 
756  handleCommonEvents( *evt );
757 
758  if( evt->IsMotion() )
759  {
760  m_router->SetOrthoMode( evt->Modifier( MD_CTRL ) );
761  updateEndItem( *evt );
763  }
764  else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
765  {
766  updateEndItem( *evt );
767  bool needLayerSwitch = m_router->IsPlacingVia();
768  bool forceFinish = evt->Modifier( MD_SHIFT );
769 
770 
771  if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) )
772  break;
773 
774  if( needLayerSwitch )
776 
777  // Synchronize the indicated layer
779  updateEndItem( *evt );
781  m_startItem = nullptr;
782  }
783  else if( evt->IsAction( &ACT_SwitchPosture ) )
784  {
786  updateEndItem( *evt );
787  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
788  }
789  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
790  {
791  m_router->SwitchLayer( frame()->GetActiveLayer() );
792  updateEndItem( *evt );
793  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
794  }
795  else if( evt->IsAction( &ACT_EndTrack ) )
796  {
797  bool still_routing = true;
798  while( still_routing )
799  still_routing = m_router->FixRoute( m_endSnapPoint, m_endItem );
800  break;
801  }
802  else if( evt->IsCancelInteractive() || evt->IsActivate()
803  || evt->IsUndoRedo()
804  || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
805  {
806  if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
807  m_cancelled = true;
808 
809  if( evt->IsActivate() && !evt->IsMoveTool() )
810  m_cancelled = true;
811 
812  break;
813  }
814  else if( evt->IsKeyPressed() )
815  {
816  // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
817  // event so we need to process the wxEVT_CHAR event that will follow as long as we
818  // pass the event.
819  evt->SetPassEvent();
820  }
821  }
822 
824 }
825 
826 
828 {
830  DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
831 
832  if( settingsDlg.ShowModal() == wxID_OK )
833  {
834  m_router->UpdateSizes( sizes );
835  m_savedSizes = sizes;
836 
838  bds.SetCustomDiffPairWidth( sizes.DiffPairWidth() );
839  bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
841  }
842 
843  return 0;
844 }
845 
846 
848 {
849  DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
850 
851  if( settingsDlg.ShowModal() == wxID_OK )
853 
854  return 0;
855 }
856 
857 
859 {
862 }
863 
864 
865 int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
866 {
868  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
869 
870  // Deselect all items
872 
873  std::string tool = aEvent.GetCommandStr().get();
874  frame->PushTool( tool );
875  Activate();
876 
877  m_router->SetMode( mode );
878 
879  VIEW_CONTROLS* ctls = getViewControls();
880  ctls->ShowCursor( true );
881  ctls->ForceCursorPosition( false );
882  m_cancelled = false;
884 
885  std::unique_ptr<ROUTER_TOOL_MENU> ctxMenu( new ROUTER_TOOL_MENU( *frame, mode ) );
886  SetContextMenu( ctxMenu.get() );
887 
888  // Prime the pump
889  if( aEvent.HasPosition() )
891 
892  // Main loop: keep receiving events
893  while( TOOL_EVENT* evt = Wait() )
894  {
895  frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
896 
897  if( evt->IsCancelInteractive() )
898  {
899  frame->PopTool( tool );
900  break;
901  }
902  else if( evt->IsActivate() )
903  {
904  if( evt->IsMoveTool() )
905  {
906  // leave ourselves on the stack so we come back after the move
907  break;
908  }
909  else
910  {
911  frame->PopTool( tool );
912  break;
913  }
914  }
915  else if( evt->Action() == TA_UNDO_REDO_PRE )
916  {
917  m_router->ClearWorld();
918  }
919  else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
920  {
921  m_router->SyncWorld();
922  }
923  else if( evt->IsMotion() )
924  {
925  updateStartItem( *evt );
926  }
927  else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
928  {
929  updateStartItem( *evt, true );
931  }
932  else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
933  {
934  updateStartItem( *evt, true );
936  }
937  else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
938  {
939  updateStartItem( *evt, true );
940  breakTrack( );
941  }
942  else if( evt->IsClick( BUT_LEFT )
943  || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
944  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
945  {
946  if( evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
947  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
948  {
949  mode = evt->Parameter<PNS::ROUTER_MODE>();
950  }
951 
952  updateStartItem( *evt );
953 
954  if( evt->HasPosition() )
955  {
956  if( evt->Modifier( MD_CTRL ) )
958  else
959  performRouting();
960  }
961  }
962  else if( evt->IsAction( &ACT_PlaceThroughVia ) )
963  {
965  }
966  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
967  {
969  updateStartItem( *evt );
970  }
971  else if( evt->IsKeyPressed() )
972  {
973  // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
974  // event so we need to process the wxEVT_CHAR event that will follow as long as we
975  // pass the event.
976  evt->SetPassEvent();
977  }
978 
979  if( m_cancelled )
980  {
981  frame->PopTool( tool );
982  break;
983  }
984  }
985 
986  SetContextMenu( nullptr );
987 
988  // Store routing settings till the next invocation
991 
992  return 0;
993 }
994 
995 
997 {
998  VIEW_CONTROLS* ctls = getViewControls();
999 
1000  if( m_startItem && m_startItem->IsLocked() )
1001  {
1002  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1003  wxOK | wxCANCEL | wxICON_WARNING );
1004  dlg.SetOKLabel( _( "Drag Anyway" ) );
1005  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1006 
1007  if( dlg.ShowModal() == wxID_CANCEL )
1008  return;
1009  }
1010 
1011  bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1012 
1013  if( !dragStarted )
1014  return;
1015 
1016  if( m_startItem && m_startItem->Net() >= 0 )
1017  highlightNet( true, m_startItem->Net() );
1018 
1019  ctls->SetAutoPan( true );
1021  frame()->UndoRedoBlock( true );
1022 
1023  while( TOOL_EVENT* evt = Wait() )
1024  {
1025  ctls->ForceCursorPosition( false );
1026 
1027  if( evt->IsMotion() )
1028  {
1029  updateEndItem( *evt );
1031  }
1032  else if( evt->IsClick( BUT_LEFT ) )
1033  {
1035  break;
1036  }
1037  else if( evt->IsCancelInteractive() || evt->IsActivate() || evt->IsUndoRedo() )
1038  {
1039  if( evt->IsCancelInteractive() && !m_startItem )
1040  m_cancelled = true;
1041 
1042  if( evt->IsActivate() && !evt->IsMoveTool() )
1043  m_cancelled = true;
1044 
1045  break;
1046  }
1047 
1048  handleCommonEvents( *evt );
1049  }
1050 
1051  if( m_router->RoutingInProgress() )
1052  m_router->StopRouting();
1053 
1054  m_startItem = nullptr;
1055 
1056  m_gridHelper->SetAuxAxes( false );
1057  frame()->UndoRedoBlock( false );
1058  ctls->SetAutoPan( false );
1059  ctls->ForceCursorPosition( false );
1060  highlightNet( false );
1061 }
1062 
1063 
1065 {
1066  /*
1067  * If the collection contains a trivial line corner (two connected segments)
1068  * or a non-fanout-via (a via with no more than two connected segments), then
1069  * trim the collection down to a single item (which one won't matter since
1070  * they're all connected).
1071  */
1072 
1073  // First make sure we've got something that *might* match.
1074  int vias = aCollector.CountType( PCB_VIA_T );
1075  int traces = aCollector.CountType( PCB_TRACE_T );
1076 
1077  if( vias > 1 || traces > 2 || vias + traces < 1 )
1078  return;
1079 
1080  // Fetch first TRACK (via or trace) as our reference
1081  TRACK* reference = nullptr;
1082 
1083  for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
1084  reference = dynamic_cast<TRACK*>( aCollector[i] );
1085 
1086  int refNet = reference->GetNetCode();
1087 
1088  wxPoint refPoint( aPt.x, aPt.y );
1089  STATUS_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
1090 
1091  if( flags & STARTPOINT )
1092  refPoint = reference->GetStart();
1093  else if( flags & ENDPOINT )
1094  refPoint = reference->GetEnd();
1095 
1096  // Check all items to ensure that any TRACKs are co-terminus with the reference and on
1097  // the same net.
1098  for( int i = 0; i < aCollector.GetCount(); i++ )
1099  {
1100  TRACK* neighbor = dynamic_cast<TRACK*>( aCollector[i] );
1101 
1102  if( neighbor && neighbor != reference )
1103  {
1104  if( neighbor->GetNetCode() != refNet )
1105  return;
1106 
1107  if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
1108  return;
1109  }
1110  }
1111 
1112  // Selection meets criteria; trim it to the reference item.
1113  aCollector.Empty();
1114  aCollector.Append( reference );
1115 }
1116 
1117 
1119 {
1121  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1122 
1123  if( selection.Size() == 1 )
1124  {
1125  const BOARD_CONNECTED_ITEM* item = static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
1126 
1127  if( item->Type() == PCB_TRACE_T || item->Type() == PCB_VIA_T )
1128  return true;
1129  }
1130 
1131  return false;
1132 }
1133 
1134 
1136 {
1137  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1138 
1139  if( selection.Empty() )
1141 
1142  if( selection.Size() != 1 )
1143  return 0;
1144 
1145  const BOARD_CONNECTED_ITEM* item = static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
1146 
1147  if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T )
1148  return 0;
1149 
1150  Activate();
1151 
1153  m_router->SyncWorld();
1155 
1156  if( m_startItem && m_startItem->IsLocked() )
1157  {
1158  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1159  wxOK | wxCANCEL | wxICON_WARNING );
1160  dlg.SetOKLabel( _( "Drag Anyway" ) );
1161  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1162 
1163  if( dlg.ShowModal() == wxID_CANCEL )
1164  return 0;
1165  }
1166 
1167  VECTOR2I p0 = controls()->GetCursorPosition( false );
1168  auto p = snapToItem( true, m_startItem, p0 );
1169  int dragMode = aEvent.Parameter<int64_t> ();
1170 
1171  bool dragStarted = m_router->StartDragging( p, m_startItem, dragMode );
1172 
1173  if( !dragStarted )
1174  return 0;
1175 
1176  m_gridHelper->SetAuxAxes( true, p );
1177  controls()->ShowCursor( true );
1178  controls()->ForceCursorPosition( false );
1179  controls()->SetAutoPan( true );
1180  frame()->UndoRedoBlock( true );
1181 
1182  while( TOOL_EVENT* evt = Wait() )
1183  {
1184  frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
1185 
1186  if( evt->IsCancelInteractive() )
1187  {
1188  break;
1189  }
1190  else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
1191  {
1192  updateEndItem( *evt );
1194  }
1195  else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
1196  {
1197  updateEndItem( *evt );
1199  break;
1200  }
1201  }
1202 
1203  if( m_router->RoutingInProgress() )
1204  m_router->StopRouting();
1205 
1206  m_gridHelper->SetAuxAxes( false );
1207  controls()->SetAutoPan( false );
1208  controls()->ForceCursorPosition( false );
1209  frame()->UndoRedoBlock( false );
1210 
1211  return 0;
1212 }
1213 
1214 
1216 {
1217  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1218 
1219  if( selection.Size() != 1 )
1220  return 0;
1221 
1222  const BOARD_CONNECTED_ITEM* item = static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
1223 
1224  if( item->Type() != PCB_TRACE_T )
1225  return 0;
1226 
1227  Activate();
1228 
1230  m_router->SyncWorld();
1232  m_startSnapPoint = snapToItem( true, m_startItem, controls()->GetCursorPosition() );
1233 
1234 
1235  if( m_startItem && m_startItem->IsLocked() )
1236  {
1237  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1238  wxOK | wxCANCEL | wxICON_WARNING );
1239  dlg.SetOKLabel( _( "Break Track" ) );
1240  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1241 
1242  if( dlg.ShowModal() == wxID_CANCEL )
1243  return 0;
1244  }
1245 
1246  frame()->UndoRedoBlock( true );
1247  breakTrack();
1248 
1249  if( m_router->RoutingInProgress() )
1250  m_router->StopRouting();
1251 
1252  frame()->UndoRedoBlock( false );
1253 
1254  return 0;
1255 }
1256 
1257 
1259 {
1261  DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
1262 
1263  if( sizeDlg.ShowModal() )
1264  {
1265  bds.UseCustomTrackViaSize( true );
1267  }
1268 
1269  return 0;
1270 }
1271 
1272 
1274 {
1275  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
1276  sizes.ImportCurrent( board()->GetDesignSettings() );
1277  m_router->UpdateSizes( sizes );
1278 
1279  // Changing the track width can affect the placement, so call the
1280  // move routine without changing the destination
1282 
1283  return 0;
1284 }
1285 
1286 
1288 {
1290 
1297 
1303 
1306 }
1307 
1308 
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:122
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
const wxString & FailureReason() const
Definition: pns_router.h:217
int GetCurrentMicroViaSize()
Function GetCurrentMicroViaSize.
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
Class ITEM.
Definition: pns_item.h:53
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon)
Function Add() Adds a wxWidgets-style entry to the menu.
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
BOARD_CONNECTED_ITEM * Parent() const
Definition: pns_item.h:145
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox
Definition: confirm.cpp:53
void SetTrackWidthIndex(unsigned aIndex)
Function SetTrackWidthIndex sets the current track width list index to aIndex.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
int GetNetCode() const
Function GetNetCode.
int MainLoop(const TOOL_EVENT &aEvent)
static TOOL_ACTION selectLayerPair
Definition: pcb_actions.h:135
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: class_module.h:58
Normal via
Definition: router_tool.cpp:63
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:64
Implementation of conversion functions that require both schematic and board internal units.
Class ACTION_MENU.
Definition: action_menu.h:43
This file is part of the common library.
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:194
std::vector< int > m_TrackWidthList
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
const wxPoint & GetStart() const
Definition: class_track.h:109
int GetCurrentMicroViaDrill()
Function GetCurrentMicroViaDrill.
VIEW_CONTROLS class definition.
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
VECTOR2I m_startSnapPoint
Definition: pns_tool_base.h:70
int InlineDrag(const TOOL_EVENT &aEvent)
Class 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.
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:144
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()
Function AllNonCuMask returns a mask holding all layer minus CU layers.
Definition: lset.cpp:699
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
SIZES_SETTINGS m_savedSizes
Stores sizes settings between router invocations.
Definition: pns_tool_base.h:67
void SyncWorld()
Definition: pns_router.cpp:90
bool IsPlacingVia() const
Definition: pns_router.cpp:498
Microvia
Definition: router_tool.cpp:67
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:109
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:68
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:285
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:143
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)
void UndoRedoBlock(bool aBlock=true)
Function UndoRedoBlock Enables/disable undo and redo operations.
void SetViaDrill(int aDrill)
void SetContextMenu(ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Function SetContextMenu()
SIZES_SETTINGS & Sizes()
Definition: pns_router.h:209
VIATYPE_T
Definition: class_track.h:60
bool SetCurrentNetClass(const wxString &aNetClassName)
Function SetCurrentNetClass Must be called after a netclass selection (or after a netclass parameter ...
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void SwitchLayer(int layer)
Definition: pns_router.cpp:435
int CountType(KICAD_T aType)
Function CountType counts the number of items matching aType.
Definition: collector.h:264
void breakTrack()
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
ROUTER_TOOL_MENU(PCB_EDIT_FRAME &aFrame, PNS::ROUTER_MODE aMode)
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
void SetOrthoMode(bool aEnable)
Definition: pns_router.cpp:507
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
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:448
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
void handleCommonEvents(const TOOL_EVENT &evt)
GRID_MENU m_gridMenu
This file contains miscellaneous commonly used macros and functions.
void ClearWorld()
Definition: pns_router.cpp:99
int Start() const
Definition: pns_layerset.h:83
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:132
wxString MessageTextFromValue(EDA_UNITS_T aUnits, int aValue, bool aUseMils)
Definition: base_units.cpp:125
PCB_BASE_EDIT_FRAME * frame() const
virtual PCB_LAYER_ID GetActiveLayer() const
Function GetActiveLayer returns the active layer.
virtual void updateStartItem(const TOOL_EVENT &aEvent, bool aIgnorePads=false)
void SetViaSizeIndex(unsigned aIndex)
Function SetViaSizeIndex sets the current via size list index to aIndex.
int onViaCommand(const TOOL_EVENT &aEvent)
Class TOOL_MANAGER.
Definition: tool_manager.h:50
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:113
virtual void Reset(RESET_REASON aReason)=0
Function Reset() Brings the tool to a known, initial state.
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))
Definition: grid_helper.cpp:93
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:193
#define _(s)
const PCBNEW_SELECTION & selection() const
void performRouting()
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
Definition: pns_router.cpp:528
static const TOOL_ACTION ACT_AutoEndRoute("pcbnew.InteractiveRouter.AutoEndRoute", AS_CONTEXT, 'F', "", _("Auto-finish Track"), _("Automagically finishes laying the current track."))
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:80
void update() override
Update menu state stub.
unsigned GetViaSizeIndex() const
Function GetViaSizeIndex.
int Net() const
Definition: pns_item.h:148
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)
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:851
void SetCustomDiffPairWidth(int aWidth)
Function SetCustomDiffPairWidth Sets custom track width for differential pairs (i....
void SetIcon(const BITMAP_OPAQUE *aIcon)
Function SetIcon() Assigns an icon for the entry.
Definition: action_menu.cpp:68
Class TOOL_EVENT.
Definition: tool_event.h:171
PNS::ROUTER_MODE m_mode
ITEM * m_startItem
Definition: pns_tool_base.h:68
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:373
OPT_TOOL_EVENT eventHandler(const wxMenuEvent &aEvent) override
Event handler stub.
unsigned GetTrackWidthIndex() const
Function GetTrackWidthIndex.
DIFF_PAIR_MENU(PCB_EDIT_FRAME &aFrame)
ZOOM_MENU m_zoomMenu
void Init(BOARD *aBoard, ITEM *aStartItem=NULL, int aNet=-1)
unsigned STATUS_FLAGS
Definition: base_struct.h:156
ROUTER * m_router
Definition: pns_tool_base.h:78
bool CanInlineDrag()
void Load(const TOOL_SETTINGS &where)
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition: pcb_screen.h:46
void switchLayerOnViaPlacement()
PCB_EDIT_FRAME & m_frame
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
PCB_LAYER_WIDGET * GetLayerManager()
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
ROUTING_SETTINGS m_savedSettings
Stores routing settings between router invocations.
Definition: pns_tool_base.h:66
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)
Function SetActiveLayer will change the currently active layer to aLayer.
void SetCustomDiffPairGap(int aGap)
Function SetCustomDiffPairGap Sets custom gap for differential pairs (i.e.
void ImportCurrent(BOARD_DESIGN_SETTINGS &aSettings)
void Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:230
TOOL_SETTINGS & GetSettings()
Definition: tool_base.cpp:78
int onTrackViaSizeChanged(const TOOL_EVENT &aEvent)
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:198
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:175
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.
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:119
static TOOL_ACTION inlineBreakTrack
Breaks track when router is not activated.
Definition: pcb_actions.h:141
ACTION_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes.
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:138
void StopRouting()
Definition: pns_router.cpp:398
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)
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
ACTION_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes.
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
ROUTER_MODE
Definition: pns_router.h:65
PCB_EDIT_FRAME & m_frame
int GetCurrentViaSize() const
Function GetCurrentViaSize.
void SetViaType(VIATYPE_T aViaType)
void Save(TOOL_SETTINGS &where) const
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:275
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:317
void SetTitle(const wxString &aTitle) override
Function SetTitle() Sets title for the menu.
Definition: action_menu.cpp:86
KIGFX::VIEW_CONTROLS * controls() const
void SetMode(ROUTER_MODE aMode)
Definition: pns_router.cpp:516
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,...
EDA_UNITS_T GetUserUnits() const
Return the user units currently in use.
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:178
VECTOR2I m_endSnapPoint
Definition: pns_tool_base.h:74
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
Class TOOL_BASE.
Definition: tool_base.h:67
Class TOOL_ACTION.
Definition: tool_action.h:46
size_t i
Definition: json11.cpp:649
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:126
#define ENDPOINT
ends. (Used to support dragging.)
Definition: base_struct.h:126
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:132
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
void Clear()
Function Clear() Removes all the entries from the menu (as well as its title).
TOOL_EVENT MakeEvent() const
Function MakeEvent() Returns the event associated with the action (i.e.
Definition: tool_action.h:107
int Size() const
Returns the number of selected parts.
Definition: selection.h:125
bool IsLocked() const
Definition: pns_item.h:235
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int InlineBreakTrack(const TOOL_EVENT &aEvent)
ITEM * FindItemByParent(const BOARD_CONNECTED_ITEM *aParent)
Definition: pns_node.cpp:1297
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
const wxPoint & GetEnd() const
Definition: class_track.h:106
std::vector< VIA_DIMENSION > m_ViasDimensionsList
boost::optional< T > OPT
Definition: optional.h:7
virtual void PopTool(const std::string &actionName)
int ShowModal() override
Definition: confirm.cpp:95
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void Activate()
Function Activate() Runs the tool.
Implementing DIALOG_TRACK_VIA_SIZE_BASE.
int SelectCopperLayerPair(const TOOL_EVENT &aEvent)
Definition: sel_layer.cpp:260
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)
void DumpLog()
Definition: pns_router.cpp:475
static VIATYPE_T getViaTypeFromFlags(int aFlags)
bool m_MicroViasAllowed
true to allow micro vias
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
Function SetLayerVisible sets aLayer visible or not.
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
void FlipPosture()
Definition: pns_router.cpp:426
DIFF_PAIR_MENU m_diffPairMenu
bool RoutingInProgress() const
Definition: pns_router.cpp:111
int KeyCode() const
Definition: tool_event.h:347
void SetViaDiameter(int aDiameter)
int getStartLayer(const PNS::ITEM *aItem)
TRACK_WIDTH_MENU m_trackViaMenu
NODE * GetWorld() const
Definition: pns_router.h:146
int GetCopperLayerCount() const
Function GetCopperLayerCount.
OPT< int > PairedLayer(int aLayerId)
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:205
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Function SetActiveLayer will change the currently active layer to aLayer and also update the PCB_LAYE...
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:190
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:813
VIA_ACTION_FLAGS
Flags used by via tool actions.
Definition: router_tool.cpp:58
EDA_UNITS_T
Definition: common.h:133
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:70
Class LAYER_RANGE.
Definition: pns_layerset.h:32
const LAYER_RANGE & Layers() const
Definition: pns_item.h:150
PCB_LAYER_ID m_Route_Layer_TOP
Definition: pcb_screen.h:45
void UseCustomTrackViaSize(bool aEnabled)
Function UseCustomTrackViaSize Enables/disables custom track/via size settings.
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:182
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: base_struct.h:210
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: base_struct.h:125
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:273
int GetCurrentLayer() const
Definition: pns_router.cpp:467
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:181