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 "class_module.h"
28 #include "class_pad.h"
29 
30 #include <pcb_edit_frame.h>
31 #include <id.h>
32 #include <macros.h>
33 #include <pcbnew_id.h>
34 #include <view/view_controls.h>
35 #include <pcb_layer_widget.h>
36 #include <pcb_painter.h>
40 #include <base_units.h>
41 #include <confirm.h>
42 #include <bitmaps.h>
43 #include <collectors.h>
44 #include <tool/action_menu.h>
45 #include <tool/tool_manager.h>
46 #include <tool/grid_menu.h>
47 #include <tool/zoom_menu.h>
48 #include <tools/pcb_actions.h>
49 #include <tools/selection_tool.h>
50 #include <tools/grid_helper.h>
51 
52 #include "router_tool.h"
53 #include "pns_segment.h"
54 #include "pns_router.h"
55 #include "pns_itemset.h"
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 Rounding" ),
152  _( "Switch Rounding" ),
153  _( "Switches the corner type of the currently routed track." ) );
154 
155 #undef _
156 #define _(s) wxGetTranslation((s))
157 
158 
160  TOOL_BASE( "pcbnew.InteractiveRouter" )
161 {
162 }
163 
164 
166 {
167 public:
169  ACTION_MENU( true ),
170  m_frame( aFrame )
171  {
173  SetTitle( _( "Select Track/Via Width" ) );
174  }
175 
176 protected:
177  ACTION_MENU* create() const override
178  {
179  return new TRACK_WIDTH_MENU( m_frame );
180  }
181 
182  void update() override
183  {
184  EDA_UNITS units = m_frame.GetUserUnits();
186  bool useIndex = !bds.m_UseConnectedTrackWidth &&
187  !bds.UseCustomTrackViaSize();
188  wxString msg;
189 
190  Clear();
191 
192  Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use Starting Track Width" ),
193  _( "Route using the width of the starting track." ), wxITEM_CHECK );
196 
197  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use Net Class Values" ),
198  _( "Use track and via sizes from the net class" ), wxITEM_CHECK );
200  useIndex && bds.GetTrackWidthIndex() == 0 && bds.GetViaSizeIndex() == 0 );
201 
202  Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Use Custom Values..." ),
203  _( "Specify custom track and via sizes" ), wxITEM_CHECK );
205 
206  AppendSeparator();
207 
208  // Append the list of tracks & via sizes
209  for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
210  {
211  int width = bds.m_TrackWidthList[i];
212 
213  if( i == 0 )
214  msg = _( "Track netclass width" );
215  else
216  msg.Printf( _( "Track %s" ), MessageTextFromValue( units, width, true ) );
217 
218  int menuIdx = ID_POPUP_PCB_SELECT_WIDTH1 + i;
219  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
220  Check( menuIdx, useIndex && bds.GetTrackWidthIndex() == i );
221  }
222 
223  AppendSeparator();
224 
225  for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
226  {
227  VIA_DIMENSION via = bds.m_ViasDimensionsList[i];
228 
229  if( i == 0 )
230  msg = _( "Via netclass values" );
231  else
232  {
233  if( via.m_Drill > 0 )
234  msg.Printf( _("Via %s, drill %s" ),
235  MessageTextFromValue( units, via.m_Diameter, true ),
236  MessageTextFromValue( units, via.m_Drill, true ) );
237  else
238  msg.Printf( _( "Via %s" ), MessageTextFromValue( units, via.m_Diameter, true ) );
239  }
240 
241  int menuIdx = ID_POPUP_PCB_SELECT_VIASIZE1 + i;
242  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
243  Check( menuIdx, useIndex && bds.GetViaSizeIndex() == i );
244  }
245  }
246 
247  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
248  {
250  int id = aEvent.GetId();
251 
252  // On Windows, this handler can be called with an event ID not existing in any
253  // menuitem, so only set flags when we have an ID match.
254 
256  {
257  bds.UseCustomTrackViaSize( true );
258  bds.m_UseConnectedTrackWidth = false;
260  }
261  else if( id == ID_POPUP_PCB_SELECT_AUTO_WIDTH )
262  {
263  bds.UseCustomTrackViaSize( false );
264  bds.m_UseConnectedTrackWidth = true;
265  }
267  {
268  bds.UseCustomTrackViaSize( false );
269  bds.m_UseConnectedTrackWidth = false;
270  bds.SetViaSizeIndex( 0 );
271  bds.SetTrackWidthIndex( 0 );
272  }
274  {
275  bds.UseCustomTrackViaSize( false );
276  bds.m_UseConnectedTrackWidth = false;
278  }
280  {
281  bds.UseCustomTrackViaSize( false );
282  bds.m_UseConnectedTrackWidth = false;
284  }
285 
286  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
287  }
288 
289 private:
291 };
292 
293 
295 {
296 public:
298  ACTION_MENU( true ),
299  m_frame( aFrame )
300  {
302  SetTitle( _( "Select Differential Pair Dimensions" ) );
303  }
304 
305 protected:
306  ACTION_MENU* create() const override
307  {
308  return new DIFF_PAIR_MENU( m_frame );
309  }
310 
311  void update() override
312  {
313  EDA_UNITS units = m_frame.GetUserUnits();
315 
316  Clear();
317 
318  Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_DIFFPAIR, _( "Use Net Class Values" ),
319  _( "Use differential pair dimensions from the net class" ), wxITEM_CHECK );
321  !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == 0 );
322 
323  Append( ID_POPUP_PCB_SELECT_CUSTOM_DIFFPAIR, _( "Use Custom Values..." ),
324  _( "Specify custom differential pair dimensions" ), wxITEM_CHECK );
326 
327  AppendSeparator();
328 
329  // Append the list of differential pair dimensions
330 
331  // Drop index 0 which is the current netclass dimensions (which are handled above)
332  for( unsigned i = 1; i < bds.m_DiffPairDimensionsList.size(); ++i )
333  {
335  wxString msg;
336 
337  msg << _( "Width " ) << MessageTextFromValue( units, diffPair.m_Width, true );
338 
339  if( diffPair.m_Gap > 0 )
340  msg << _( ", gap " ) << MessageTextFromValue( units, diffPair.m_Gap, true );
341 
342  if( diffPair.m_ViaGap > 0 )
343  msg << _( ", via gap " ) << MessageTextFromValue( units, diffPair.m_ViaGap, true );
344 
345  int menuIdx = ID_POPUP_PCB_SELECT_DIFFPAIR1 + i - 1;
346  Append( menuIdx, msg, wxEmptyString, wxITEM_CHECK );
347  Check( menuIdx, !bds.UseCustomDiffPairDimensions() && bds.GetDiffPairIndex() == i );
348  }
349  }
350 
351  OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override
352  {
354  int id = aEvent.GetId();
355 
356  // On Windows, this handler can be called with an event ID not existing in any
357  // menuitem, so only set flags when we have an ID match.
358 
360  {
361  bds.UseCustomDiffPairDimensions( true );
362  TOOL_MANAGER* toolManager = m_frame.GetToolManager();
363  toolManager->RunAction( PCB_ACTIONS::routerDiffPairDialog, true );
364  }
366  {
367  bds.UseCustomDiffPairDimensions( false );
368  bds.SetDiffPairIndex( 0 );
369  }
371  {
372  bds.UseCustomDiffPairDimensions( false );
373  // remember that the menu doesn't contain index 0 (which is the netclass values)
375  }
376 
377  return OPT_TOOL_EVENT( PCB_ACTIONS::trackViaSizeChanged.MakeEvent() );
378  }
379 
380 private:
382 };
383 
384 
386 {
387 public:
389  ACTION_MENU( true ),
390  m_frame( aFrame ), m_mode( aMode ), m_trackViaMenu( aFrame ), m_diffPairMenu( aFrame ),
391  m_zoomMenu( &aFrame ), m_gridMenu( &aFrame )
392  {
393  SetTitle( _( "Interactive Router" ) );
394 
396 
397  AppendSeparator();
398 
401  Add( ACT_EndTrack );
404 
407 
408 // Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry.
416 
417  AppendSeparator();
418 
419  Add( &m_trackViaMenu );
420 
422  Add( &m_diffPairMenu );
423 
425 
426  AppendSeparator();
427 
428  Add( &m_zoomMenu );
429  Add( &m_gridMenu );
430  }
431 
432 private:
433  ACTION_MENU* create() const override
434  {
435  return new ROUTER_TOOL_MENU( m_frame, m_mode );
436  }
437 
444 };
445 
446 
448 {
449 }
450 
451 
453 {
454  return true;
455 }
456 
457 
459 {
460  if( aReason == RUN )
461  TOOL_BASE::Reset( aReason );
462 }
463 
464 
466 {
467 #ifdef DEBUG
468  if( aEvent.IsKeyPressed() )
469  {
470  switch( aEvent.KeyCode() )
471  {
472  case '0':
473  wxLogTrace( "PNS", "saving drag/route log...\n" );
474  m_router->DumpLog();
475  break;
476  }
477  }
478 #endif
479 }
480 
481 
483 {
484  int tl = getView()->GetTopLayer();
485 
486  if( m_startItem )
487  {
488  const LAYER_RANGE& ls = m_startItem->Layers();
489 
490  if( ls.Overlaps( tl ) )
491  return tl;
492  else
493  return ls.Start();
494  }
495 
496  return tl;
497 }
498 
499 
501 {
502  int al = frame()->GetActiveLayer();
503  int cl = m_router->GetCurrentLayer();
504 
505  if( cl != al )
506  {
507  m_router->SwitchLayer( al );
508  }
509 
510  OPT<int> newLayer = m_router->Sizes().PairedLayer( cl );
511 
512  if( !newLayer )
513  newLayer = m_router->Sizes().GetLayerTop();
514 
515  m_router->SwitchLayer( *newLayer );
516  frame()->SetActiveLayer( ToLAYER_ID( *newLayer ) );
517 }
518 
519 
520 static VIATYPE getViaTypeFromFlags( int aFlags )
521 {
522  switch( aFlags & VIA_ACTION_FLAGS::VIA_MASK )
523  {
525  return VIATYPE::THROUGH;
527  return VIATYPE::BLIND_BURIED;
529  return VIATYPE::MICROVIA;
530  default:
531  wxASSERT_MSG( false, "Unhandled via type" );
532  return VIATYPE::THROUGH;
533  }
534 }
535 
536 
538 {
539  const int actViaFlags = aEvent.Parameter<intptr_t>();
540 
541  VIATYPE viaType = getViaTypeFromFlags( actViaFlags );
542  const bool selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER;
543 
545 
546  const int layerCount = bds.GetCopperLayerCount();
547  int currentLayer = m_router->GetCurrentLayer();
550 
552 
553  // ask the user for a target layer
554  PCB_LAYER_ID targetLayer = UNDEFINED_LAYER;
555 
556  if( selectLayer )
557  {
558  wxPoint dlgPosition = wxGetMousePosition();
559 
560  targetLayer = frame()->SelectLayer(
561  static_cast<PCB_LAYER_ID>( currentLayer ), LSET::AllNonCuMask(), dlgPosition );
562 
563  // Reset the cursor to the position where the event occured
564  controls()->SetCursorPosition( aEvent.HasPosition() ? aEvent.Position() : dlgPosition );
565  }
566 
567  // fixme: P&S supports more than one fixed layer pair. Update the dialog?
568  sizes.ClearLayerPairs();
569 
570  if( !m_router->IsPlacingVia() )
571  {
572  // Cannot place microvias or blind vias if not allowed (obvious)
573  if( ( viaType == VIATYPE::BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
574  {
575  DisplayError( frame(),
576  _( "Blind/buried vias have to be enabled in Board Setup > Design Rules > Constraints." ) );
577  return false;
578  }
579 
580  if( ( viaType == VIATYPE::MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
581  {
582  DisplayError( frame(),
583  _( "Microvias have to be enabled in Board Setup > Design Rules > Constraints." ) );
584  return false;
585  }
586 
587  // Can only place through vias on 2-layer boards
588  if( ( viaType != VIATYPE::THROUGH ) && ( layerCount <= 2 ) )
589  {
590  DisplayError( frame(), _( "Only through vias are allowed on 2 layer boards." ) );
591  return false;
592  }
593 
594  // Can only place microvias if we're on an outer layer, or directly adjacent to one
595  if( ( viaType == VIATYPE::MICROVIA ) && ( currentLayer > In1_Cu )
596  && ( currentLayer < layerCount - 2 ) )
597  {
598  DisplayError( frame(), _( "Microvias can be placed only between the outer layers "
599  "(F.Cu/B.Cu) and the ones directly adjacent to them." ) );
600  return false;
601  }
602  }
603 
604  // Convert blind/buried via to a through hole one, if it goes through all layers
605  if( viaType == VIATYPE::BLIND_BURIED
606  && ( ( targetLayer == B_Cu && currentLayer == F_Cu )
607  || ( targetLayer == F_Cu && currentLayer == B_Cu ) ) )
608  {
609  viaType = VIATYPE::THROUGH;
610  }
611 
612  switch( viaType )
613  {
614  case VIATYPE::THROUGH:
615  sizes.SetViaDiameter( bds.GetCurrentViaSize() );
616  sizes.SetViaDrill( bds.GetCurrentViaDrill() );
617 
618  if( targetLayer != UNDEFINED_LAYER )
619  {
620  // go from the current layer to the chosen layer
621  sizes.AddLayerPair( currentLayer, targetLayer );
622  }
623  else
624  {
625  // use the default layer pair
626  sizes.AddLayerPair( pairTop, pairBottom );
627  }
628  break;
629 
630  case VIATYPE::MICROVIA:
631  sizes.SetViaDiameter( bds.GetCurrentMicroViaSize() );
632  sizes.SetViaDrill( bds.GetCurrentMicroViaDrill() );
633 
634  wxASSERT_MSG( !selectLayer,
635  "Unexpected select layer for microvia (microvia layers are implicit)" );
636 
637  if( currentLayer == F_Cu || currentLayer == In1_Cu )
638  {
639  // front-side microvia
640  sizes.AddLayerPair( F_Cu, In1_Cu );
641  }
642  else if( currentLayer == B_Cu || currentLayer == layerCount - 2 )
643  {
644  // back-side microvia
645  sizes.AddLayerPair( B_Cu, layerCount - 2 );
646  }
647  else
648  {
649  wxASSERT_MSG( false,
650  "Invalid layer pair for microvia (must be on or adjacent to an outer layer)" );
651  }
652  break;
653 
655  sizes.SetViaDiameter( bds.GetCurrentViaSize() );
656  sizes.SetViaDrill( bds.GetCurrentViaDrill() );
657 
658  if( targetLayer != UNDEFINED_LAYER )
659  {
660  // go directly to the user specified layer
661  sizes.AddLayerPair( currentLayer, targetLayer );
662  }
663  else
664  {
665  if( currentLayer == pairTop || currentLayer == pairBottom )
666  {
667  // the current layer is on the defined layer pair,
668  // swap to the other side
669  sizes.AddLayerPair( pairTop, pairBottom );
670  }
671  else
672  {
673  // the current layer is not part of the current layer pair,
674  // so fallback and swap to the top layer of the pair by default
675  sizes.AddLayerPair( pairTop, currentLayer );
676  }
677  }
678  break;
679 
680  default:
681  wxASSERT( false );
682  break;
683  }
684 
685  sizes.SetViaType( viaType );
686 
687  m_router->UpdateSizes( sizes );
689 
690  if( m_router->RoutingInProgress() )
691  updateEndItem( aEvent );
692  else
693  updateStartItem( aEvent );
694 
695  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
696 
697  return 0;
698 }
699 
700 
702 {
703  int routingLayer = getStartLayer( m_startItem );
704 
705  if( !IsCopperLayer( routingLayer ) )
706  {
707  DisplayError( frame(), _( "Tracks on Copper layers only" ) );
708  return false;
709  }
710 
711  PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
712 
713  editFrame->SetActiveLayer( ToLAYER_ID( routingLayer ) );
714 
715  // Force layer visible
716  editFrame->GetLayerManager()->SetLayerVisible( routingLayer, true );
717 
718  // for some reason I don't understand, GetNetclass() may return null sometimes...
719  if( m_startItem && m_startItem->Net() >= 0 &&
721  {
722  highlightNet( true, m_startItem->Net() );
723  // Update track width and via size shown in main toolbar comboboxes
724  editFrame->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() );
725  }
726  else
728 
729  controls()->ForceCursorPosition( false );
730  controls()->SetAutoPan( true );
731 
732  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
733 
734  sizes.Init( board(), m_startItem );
735  sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
736  frame()->GetScreen()->m_Route_Layer_BOTTOM );
737  m_router->UpdateSizes( sizes );
738 
739  if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
740  {
742  highlightNet( false );
743  controls()->SetAutoPan( false );
744  return false;
745  }
746 
747  m_endItem = nullptr;
749 
750  frame()->UndoRedoBlock( true );
751 
752  return true;
753 }
754 
755 
757 {
759 
760  controls()->SetAutoPan( false );
761  controls()->ForceCursorPosition( false );
762  frame()->UndoRedoBlock( false );
763  highlightNet( false );
764 
765  return true;
766 }
767 
768 
770 {
771  if( !prepareInteractive() )
772  return;
773 
774  while( TOOL_EVENT* evt = Wait() )
775  {
776  frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
777 
778  // Don't crash if we missed an operation that cancelled routing.
779  wxCHECK2( m_router->RoutingInProgress(), break );
780 
781  handleCommonEvents( *evt );
782 
783  if( evt->IsMotion() )
784  {
785  m_router->SetOrthoMode( evt->Modifier( MD_CTRL ) );
786  updateEndItem( *evt );
788  }
789  else if( evt->IsAction( &ACT_UndoLastSegment ) )
790  {
792  updateEndItem( *evt );
794  }
795  else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
796  {
797  updateEndItem( *evt );
798  bool needLayerSwitch = m_router->IsPlacingVia();
799  bool forceFinish = evt->Modifier( MD_SHIFT );
800 
801 
802  if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) )
803  {
804  break;
805  }
806 
807  if( needLayerSwitch )
809 
810  // Synchronize the indicated layer
812  updateEndItem( *evt );
814  m_startItem = nullptr;
815  }
816  else if( evt->IsAction( &ACT_SwitchRounding ) )
817  {
819  updateEndItem( *evt );
820  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
821  }
822  else if( evt->IsAction( &ACT_SwitchPosture ) )
823  {
825  updateEndItem( *evt );
826  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
827  }
828  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
829  {
830  m_router->SwitchLayer( frame()->GetActiveLayer() );
831  updateEndItem( *evt );
832  m_router->Move( m_endSnapPoint, m_endItem ); // refresh
833  }
834  else if( evt->IsAction( &ACT_EndTrack ) )
835  {
836  bool still_routing = true;
837 
838  while( still_routing )
839  still_routing = m_router->FixRoute( m_endSnapPoint, m_endItem );
840 
841  break;
842  }
843  else if( evt->IsCancelInteractive() || evt->IsActivate()
844  || evt->IsUndoRedo()
845  || evt->IsAction( &PCB_ACTIONS::routerInlineDrag ) )
846  {
847  if( evt->IsCancelInteractive() && !m_router->RoutingInProgress() )
848  m_cancelled = true;
849 
850  if( evt->IsActivate() && !evt->IsMoveTool() )
851  m_cancelled = true;
852 
853  break;
854  }
855  else if( evt->IsKeyPressed() )
856  {
857  // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
858  // event so we need to process the wxEVT_CHAR event that will follow as long as we
859  // pass the event.
860  evt->SetPassEvent();
861  }
862  }
863 
866 
868 }
869 
870 
872 {
874  DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes );
875 
876  if( settingsDlg.ShowModal() == wxID_OK )
877  {
878  m_router->UpdateSizes( sizes );
879  m_savedSizes = sizes;
880 
882  bds.SetCustomDiffPairWidth( sizes.DiffPairWidth() );
883  bds.SetCustomDiffPairGap( sizes.DiffPairGap() );
885  }
886 
887  return 0;
888 }
889 
890 
892 {
893  DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
894 
895  settingsDlg.ShowModal();
896 
897  return 0;
898 }
899 
900 
902 {
905 }
906 
907 
908 int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
909 {
911  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
912 
913  // Deselect all items
915 
916  std::string tool = aEvent.GetCommandStr().get();
917  frame->PushTool( tool );
918  Activate();
919 
920  m_router->SetMode( mode );
921 
922  VIEW_CONTROLS* ctls = getViewControls();
923  ctls->ShowCursor( true );
924  ctls->ForceCursorPosition( false );
925  m_cancelled = false;
927 
928  std::unique_ptr<ROUTER_TOOL_MENU> ctxMenu( new ROUTER_TOOL_MENU( *frame, mode ) );
929  SetContextMenu( ctxMenu.get() );
930 
931  // Prime the pump
932  if( aEvent.HasPosition() )
934 
935  // Main loop: keep receiving events
936  while( TOOL_EVENT* evt = Wait() )
937  {
938  frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
939 
940  if( evt->IsCancelInteractive() )
941  {
942  frame->PopTool( tool );
943  break;
944  }
945  else if( evt->IsActivate() )
946  {
947  if( evt->IsMoveTool() )
948  {
949  // leave ourselves on the stack so we come back after the move
950  break;
951  }
952  else
953  {
954  frame->PopTool( tool );
955  break;
956  }
957  }
958  else if( evt->Action() == TA_UNDO_REDO_PRE )
959  {
960  m_router->ClearWorld();
961  }
962  else if( evt->Action() == TA_UNDO_REDO_POST || evt->Action() == TA_MODEL_CHANGE )
963  {
964  m_router->SyncWorld();
965  }
966  else if( evt->IsMotion() )
967  {
968  updateStartItem( *evt );
969  }
970  else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) )
971  {
972  updateStartItem( *evt, true );
974  }
975  else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) )
976  {
977  updateStartItem( *evt, true );
979  }
980  else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) )
981  {
982  updateStartItem( *evt, true );
983  breakTrack( );
984  }
985  else if( evt->IsClick( BUT_LEFT )
986  || evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
987  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
988  {
989  if( evt->IsAction( &PCB_ACTIONS::routeSingleTrack )
990  || evt->IsAction( &PCB_ACTIONS::routeDiffPair ) )
991  {
992  mode = evt->Parameter<PNS::ROUTER_MODE>();
993  }
994 
995  updateStartItem( *evt );
996 
997  if( evt->HasPosition() )
998  {
999  if( evt->Modifier( MD_CTRL ) )
1001  else
1002  performRouting();
1003  }
1004  }
1005  else if( evt->IsAction( &ACT_PlaceThroughVia ) )
1006  {
1008  }
1009  else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
1010  {
1012  updateStartItem( *evt );
1013  }
1014  else if( evt->IsKeyPressed() )
1015  {
1016  // wxWidgets fails to correctly translate shifted keycodes on the wxEVT_CHAR_HOOK
1017  // event so we need to process the wxEVT_CHAR event that will follow as long as we
1018  // pass the event.
1019  evt->SetPassEvent();
1020  }
1021 
1022  if( m_cancelled )
1023  {
1024  frame->PopTool( tool );
1025  break;
1026  }
1027  }
1028 
1029  SetContextMenu( nullptr );
1030 
1031  // Store routing settings till the next invocation
1033 
1034  return 0;
1035 }
1036 
1037 
1039 {
1040  VIEW_CONTROLS* ctls = getViewControls();
1041 
1042  if( m_startItem && m_startItem->IsLocked() )
1043  {
1044  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1045  wxOK | wxCANCEL | wxICON_WARNING );
1046  dlg.SetOKLabel( _( "Drag Anyway" ) );
1047  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1048 
1049  if( dlg.ShowModal() == wxID_CANCEL )
1050  return;
1051  }
1052 
1053  bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode );
1054 
1055  if( !dragStarted )
1056  return;
1057 
1058  if( m_startItem && m_startItem->Net() >= 0 )
1059  highlightNet( true, m_startItem->Net() );
1060 
1061  ctls->SetAutoPan( true );
1063  frame()->UndoRedoBlock( true );
1064 
1065  while( TOOL_EVENT* evt = Wait() )
1066  {
1067  ctls->ForceCursorPosition( false );
1068 
1069  if( evt->IsMotion() )
1070  {
1071  updateEndItem( *evt );
1073  }
1074  else if( evt->IsClick( BUT_LEFT ) )
1075  {
1077  break;
1078  }
1079  else if( evt->IsCancelInteractive() || evt->IsActivate() || evt->IsUndoRedo() )
1080  {
1081  if( evt->IsCancelInteractive() && !m_startItem )
1082  m_cancelled = true;
1083 
1084  if( evt->IsActivate() && !evt->IsMoveTool() )
1085  m_cancelled = true;
1086 
1087  break;
1088  }
1089 
1090  handleCommonEvents( *evt );
1091  }
1092 
1093  if( m_router->RoutingInProgress() )
1094  m_router->StopRouting();
1095 
1096  m_startItem = nullptr;
1097 
1098  m_gridHelper->SetAuxAxes( false );
1099  frame()->UndoRedoBlock( false );
1100  ctls->SetAutoPan( false );
1101  ctls->ForceCursorPosition( false );
1102  highlightNet( false );
1103 }
1104 
1105 
1107 {
1108  /*
1109  * If the collection contains a trivial line corner (two connected segments)
1110  * or a non-fanout-via (a via with no more than two connected segments), then
1111  * trim the collection down to a single item (which one won't matter since
1112  * they're all connected).
1113  */
1114 
1115  // First make sure we've got something that *might* match.
1116  int vias = aCollector.CountType( PCB_VIA_T );
1117  int traces = aCollector.CountType( PCB_TRACE_T );
1118  int arcs = aCollector.CountType( PCB_ARC_T );
1119 
1120  if( arcs > 0 || vias > 1 || traces > 2 || vias + traces < 1 )
1121  return;
1122 
1123  // Fetch first TRACK (via or trace) as our reference
1124  TRACK* reference = nullptr;
1125 
1126  for( int i = 0; !reference && i < aCollector.GetCount(); i++ )
1127  reference = dynamic_cast<TRACK*>( aCollector[i] );
1128 
1129  int refNet = reference->GetNetCode();
1130 
1131  wxPoint refPoint( aPt.x, aPt.y );
1132  STATUS_FLAGS flags = reference->IsPointOnEnds( refPoint, -1 );
1133 
1134  if( flags & STARTPOINT )
1135  refPoint = reference->GetStart();
1136  else if( flags & ENDPOINT )
1137  refPoint = reference->GetEnd();
1138 
1139  // Check all items to ensure that any TRACKs are co-terminus with the reference and on
1140  // the same net.
1141  for( int i = 0; i < aCollector.GetCount(); i++ )
1142  {
1143  TRACK* neighbor = dynamic_cast<TRACK*>( aCollector[i] );
1144 
1145  if( neighbor && neighbor != reference )
1146  {
1147  if( neighbor->GetNetCode() != refNet )
1148  return;
1149 
1150  if( neighbor->GetStart() != refPoint && neighbor->GetEnd() != refPoint )
1151  return;
1152  }
1153  }
1154 
1155  // Selection meets criteria; trim it to the reference item.
1156  aCollector.Empty();
1157  aCollector.Append( reference );
1158 }
1159 
1160 
1162 {
1164  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1165 
1166  if( selection.Size() == 1 )
1167  {
1168  const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
1169 
1170  if( item->Type() == PCB_TRACE_T || item->Type() == PCB_VIA_T || item->Type() == PCB_MODULE_T )
1171  return true;
1172  }
1173 
1174  return false;
1175 }
1176 
1177 
1179 {
1180  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1181 
1182  if( selection.Empty() )
1184 
1185  if( selection.Size() != 1 )
1186  return 0;
1187 
1188  const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
1189 
1190  if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T && item->Type() != PCB_MODULE_T )
1191  return 0;
1192 
1193  Activate();
1194 
1196  m_router->SyncWorld();
1197  m_startItem = nullptr;
1198 
1199  PNS::ITEM* startItem = nullptr;
1200  PNS::ITEM_SET itemsToDrag;
1201 
1202  if( item->Type() == PCB_MODULE_T )
1203  {
1204  const auto mod = static_cast<const MODULE*>(item);
1205  for ( const auto p : mod->Pads() )
1206  {
1207  auto solid = m_router->GetWorld()->FindItemByParent( p );
1208 
1209  if( solid )
1210  itemsToDrag.Add( solid );
1211  }
1212  }
1213  else
1214  {
1215  startItem = m_router->GetWorld()->FindItemByParent( static_cast<const BOARD_CONNECTED_ITEM*>( item ) );
1216 
1217  if( startItem)
1218  itemsToDrag.Add( startItem );
1219  }
1220 
1221  if( startItem && startItem->IsLocked() )
1222  {
1223  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1224  wxOK | wxCANCEL | wxICON_WARNING );
1225  dlg.SetOKLabel( _( "Drag Anyway" ) );
1226  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1227 
1228  if( dlg.ShowModal() == wxID_CANCEL )
1229  return 0;
1230  }
1231 
1232  VECTOR2I p0 = controls()->GetCursorPosition( false );
1233  VECTOR2I p = p0;
1234 
1235  if( startItem )
1236  p = snapToItem( true, startItem, p0 );
1237 
1238  int dragMode = aEvent.Parameter<int64_t> ();
1239 
1240  bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
1241 
1242  if( !dragStarted )
1243  return 0;
1244 
1245  m_gridHelper->SetAuxAxes( true, p );
1246  controls()->ShowCursor( true );
1247  controls()->ForceCursorPosition( false );
1248  controls()->SetAutoPan( true );
1249  frame()->UndoRedoBlock( true );
1250 
1251  while( TOOL_EVENT* evt = Wait() )
1252  {
1253  frame()->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
1254 
1255  if( evt->IsCancelInteractive() )
1256  {
1257  break;
1258  }
1259  else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
1260  {
1261  updateEndItem( *evt );
1263  }
1264  else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
1265  {
1266  updateEndItem( *evt );
1268  break;
1269  }
1270  }
1271 
1272  if( m_router->RoutingInProgress() )
1273  m_router->StopRouting();
1274 
1275  m_gridHelper->SetAuxAxes( false );
1276  controls()->SetAutoPan( false );
1277  controls()->ForceCursorPosition( false );
1278  frame()->UndoRedoBlock( false );
1279 
1280  return 0;
1281 }
1282 
1283 
1285 {
1286  const auto& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
1287 
1288  if( selection.Size() != 1 )
1289  return 0;
1290 
1291  const BOARD_CONNECTED_ITEM* item = static_cast<const BOARD_CONNECTED_ITEM*>( selection.Front() );
1292 
1293  if( item->Type() != PCB_TRACE_T )
1294  return 0;
1295 
1296  Activate();
1297 
1299  m_router->SyncWorld();
1301  m_startSnapPoint = snapToItem( true, m_startItem, controls()->GetCursorPosition() );
1302 
1303 
1304  if( m_startItem && m_startItem->IsLocked() )
1305  {
1306  KIDIALOG dlg( frame(), _( "The selected item is locked." ), _( "Confirmation" ),
1307  wxOK | wxCANCEL | wxICON_WARNING );
1308  dlg.SetOKLabel( _( "Break Track" ) );
1309  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1310 
1311  if( dlg.ShowModal() == wxID_CANCEL )
1312  return 0;
1313  }
1314 
1315  frame()->UndoRedoBlock( true );
1316  breakTrack();
1317 
1318  if( m_router->RoutingInProgress() )
1319  m_router->StopRouting();
1320 
1321  frame()->UndoRedoBlock( false );
1322 
1323  return 0;
1324 }
1325 
1326 
1328 {
1330  DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds );
1331 
1332  if( sizeDlg.ShowModal() )
1333  {
1334  bds.UseCustomTrackViaSize( true );
1336  }
1337 
1338  return 0;
1339 }
1340 
1341 
1343 {
1344  PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
1345  sizes.ImportCurrent( board()->GetDesignSettings() );
1346  m_router->UpdateSizes( sizes );
1347 
1348  // Changing the track width can affect the placement, so call the
1349  // move routine without changing the destination
1351 
1352  return 0;
1353 }
1354 
1355 
1357 {
1359 
1366 
1372 
1375 }
1376 
1377 
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:109
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
const wxString & FailureReason() const
Definition: pns_router.h:226
int GetCurrentMicroViaSize()
Function GetCurrentMicroViaSize.
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
EDA_UNITS
Definition: common.h:184
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
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:146
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:75
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:131
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
Implementation of conversion functions that require both schematic and board internal units.
ACTION_MENU.
Definition: action_menu.h:43
This file is part of the common library.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
static TOOL_ACTION routerDiffPairDialog
Definition: pcb_actions.h:196
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:111
int GetCurrentMicroViaDrill()
Function GetCurrentMicroViaDrill.
VIEW_CONTROLS class definition.
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
VECTOR2I m_startSnapPoint
Definition: pns_tool_base.h:69
int InlineDrag(const TOOL_EVENT &aEvent)
void CommitRouting()
Definition: pns_router.cpp:422
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:80
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
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:709
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
SIZES_SETTINGS m_savedSizes
Stores sizes settings between router invocations.
Definition: pns_tool_base.h:66
void SyncWorld()
Definition: pns_router.cpp:96
bool IsPlacingVia() const
Definition: pns_router.cpp:531
void ToggleRounded()
Definition: pns_router.cpp:540
Microvia
Definition: router_tool.cpp:71
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:139
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
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:287
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
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:218
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:468
int CountType(KICAD_T aType)
Function CountType counts the number of items matching aType.
Definition: collector.h:216
void breakTrack()
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
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:546
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:481
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]
GRID_MENU m_gridMenu
This file contains miscellaneous commonly used macros and functions.
void ClearWorld()
Definition: pns_router.cpp:105
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:119
PCB_BASE_EDIT_FRAME * frame() const
void UndoLastSegment()
Definition: pns_router.cpp:413
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)
static VIATYPE getViaTypeFromFlags(int aFlags)
TOOL_MANAGER.
Definition: tool_manager.h:50
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:100
virtual void Reset(RESET_REASON aReason)=0
Function Reset() Brings the tool to a known, initial state.
class MODULE, a footprint
Definition: typeinfo.h:89
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:195
#define _(s)
const PCBNEW_SELECTION & selection() const
void performRouting()
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
Definition: pns_router.cpp:567
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 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:149
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
TOOL_EVENT.
Definition: tool_event.h:171
VIATYPE
Definition: class_track.h:62
PNS::ROUTER_MODE m_mode
ITEM * m_startItem
Definition: pns_tool_base.h:67
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:391
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:159
ROUTER * m_router
Definition: pns_tool_base.h:77
bool CanInlineDrag()
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: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
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)
const BITMAP_OPAQUE via_buried_xpm[1]
Definition: via_buried.cpp:55
void Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:246
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:200
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:191
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.
void SetViaType(VIATYPE aViaType)
Pad object description.
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: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:431
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.
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aUseMils, EDA_DATA_TYPE aType)
Definition: base_units.cpp:127
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:67
PCB_EDIT_FRAME & m_frame
int GetCurrentViaSize() const
Function GetCurrentViaSize.
static const TOOL_ACTION ACT_SwitchRounding("pcbnew.InteractiveRouter.SwitchRounding", AS_CONTEXT, 0, LEGACY_HK_NAME("Switch Rounding"), _("Switch Rounding"), _("Switches the corner type of the currently routed track."))
static TOOL_ACTION layerChanged
Definition: pcb_actions.h:277
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:332
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:555
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,...
static TOOL_ACTION routeSingleTrack
Activation of the Push and Shove router.
Definition: pcb_actions.h:178
VECTOR2I m_endSnapPoint
Definition: pns_tool_base.h:73
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
TOOL_BASE.
Definition: tool_base.h:66
TOOL_ACTION.
Definition: tool_action.h:46
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:131
#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:133
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:126
bool IsLocked() const
Definition: pns_item.h:236
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:1443
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:78
const wxPoint & GetEnd() const
Definition: class_track.h:108
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:261
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:508
Module description (excepted pads)
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:459
DIFF_PAIR_MENU m_diffPairMenu
const BITMAP_OPAQUE change_entry_orient_xpm[1]
bool RoutingInProgress() const
Definition: pns_router.cpp:117
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:152
int GetCopperLayerCount() const
Function GetCopperLayerCount.
OPT< int > PairedLayer(int aLayerId)
const BITMAP_OPAQUE width_track_xpm[1]
Definition: width_track.cpp:39
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:206
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 PCB_LAYE...
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:199
const BITMAP_OPAQUE checked_ok_xpm[1]
Definition: checked_ok.cpp:51
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:823
VIA_ACTION_FLAGS
Flags used by via tool actions.
Definition: router_tool.cpp:62
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
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:151
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:183
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:212
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:275
int GetCurrentLayer() const
Definition: pns_router.cpp:500
static TOOL_ACTION routeDiffPair
Activation of the Push and Shove router (differential pair mode)
Definition: pcb_actions.h:181