KiCad PCB EDA Suite
board_inspection_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <bitmaps.h>
25 #include <pcb_group.h>
26 #include <tool/tool_manager.h>
28 #include <tools/pcb_picker_tool.h>
29 #include <tools/edit_tool.h>
30 #include <pcb_painter.h>
32 #include <profile.h>
34 #include <drc/drc_engine.h>
37 #include <kicad_string.h>
38 #include "board_inspection_tool.h"
39 #include <pcbnew_settings.h>
41 #include <drc/drc_item.h>
42 #include <pad.h>
43 
44 void DIALOG_INSPECTION_REPORTER::OnErrorLinkClicked( wxHtmlLinkEvent& event )
45 {
46  if( event.GetLinkInfo().GetHref() == "boardsetup" )
47  m_frame->ShowBoardSetupDialog( _( "Rules" ) );
48  else if( event.GetLinkInfo().GetHref() == "drc" )
50 }
51 
52 
54  PCB_TOOL_BASE( "pcbnew.InspectionTool" ),
55  m_frame( nullptr )
56 {
57  m_probingSchToPcb = false;
58  m_dynamicData = nullptr;
59 }
60 
61 
63 {
64 public:
66  {
68  SetTitle( _( "Net Tools" ) );
69 
74  }
75 
76 private:
77  ACTION_MENU* create() const override
78  {
79  return new NET_CONTEXT_MENU();
80  }
81 };
82 
83 
85 {
87 
88  auto netSubMenu = std::make_shared<NET_CONTEXT_MENU>();
89  netSubMenu->SetTool( this );
90 
91  static KICAD_T connectedTypes[] = { PCB_TRACE_T, PCB_VIA_T, PCB_ARC_T, PCB_PAD_T,
92  PCB_ZONE_T, EOT };
93 
94  CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
95 
96  selectionTool->GetToolMenu().AddSubMenu( netSubMenu );
97 
98  menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ), 200 );
100 
101  return true;
102 }
103 
104 
106 {
107  m_frame = getEditFrame<PCB_EDIT_FRAME>();
108 }
109 
110 
112 {
114  dialog.ShowModal();
115  return 0;
116 }
117 
118 
120 {
121  // Null items have no description
122  if( !aItem )
123  return wxString();
124 
125  wxString s = aItem->GetSelectMenuText( m_frame->GetUserUnits() );
126 
127  if( aItem->IsConnected() )
128  {
129  BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem );
130  s += wxS( " " ) + wxString::Format( _( "[netclass %s]" ),
131  cItem->GetNetClass()->GetName() );
132  }
133 
134  return s;
135 };
136 
137 
139 {
141  wxString source;
142  ZONE_CONNECTION connection = aZone->GetPadConnection( aPad, &source );
143 
144  r->Report( "" );
145 
146  r->Report( wxString::Format( _( "Zone connection type: %s." ),
147  connectionEnum.ToString( aZone->GetPadConnection() ) ) );
148 
149  if( source != _( "zone" ) )
150  {
151  r->Report( wxString::Format( _( "Overridden by %s; connection type: %s." ),
152  source,
153  connectionEnum.ToString( connection ) ) );
154  }
155 
156  // Resolve complex connection types into simple types
157  if( connection == ZONE_CONNECTION::THT_THERMAL )
158  {
159  if( aPad->GetAttribute() == PAD_ATTRIB::PTH )
160  {
161  connection = ZONE_CONNECTION::THERMAL;
162  }
163  else
164  {
165  connection = ZONE_CONNECTION::FULL;
166  r->Report( wxString::Format( _( "Pad is not a PTH pad; connection will be: %s." ),
167  connectionEnum.ToString( ZONE_CONNECTION::FULL ) ) );
168  }
169  }
170 
171  r->Report( "" );
172 
173  // Process simple connection types
174  if( connection == ZONE_CONNECTION::THERMAL )
175  {
176  int gap = aZone->GetThermalReliefGap();
177 
178  r->Report( wxString::Format( _( "Zone thermal relief: %s." ),
179  StringFromValue( r->GetUnits(), gap, true ) ) );
180 
181  gap = aZone->GetThermalReliefGap( aPad, &source );
182 
183  if( source != _( "zone" ) )
184  {
185  r->Report( wxString::Format( _( "Overridden by %s; thermal relief: %s." ),
186  source,
187  StringFromValue( r->GetUnits(), gap, true ) ) );
188  }
189  }
190  else if( connection == ZONE_CONNECTION::NONE )
191  {
192  int clearance = aZone->GetLocalClearance();
193 
194  r->Report( wxString::Format( _( "Zone clearance: %s." ),
195  StringFromValue( r->GetUnits(), clearance, true ) ) );
196 
197  if( aZone->GetThermalReliefGap( aPad ) > clearance )
198  {
199  clearance = aZone->GetThermalReliefGap( aPad, &source );
200 
201  if( source != _( "zone" ) )
202  {
203  r->Report( wxString::Format( _( "Overridden by larger thermal relief from %s;"
204  "clearance: %s." ),
205  source,
206  StringFromValue( r->GetUnits(), clearance, true ) ) );
207  }
208  }
209  }
210  else
211  {
212  r->Report( wxString::Format( _( "Clearance: %s." ),
213  StringFromValue( r->GetUnits(), 0, true ) ) );
214  }
215 }
216 
217 
219  BOARD_ITEM* aA, BOARD_ITEM* aB, REPORTER* r )
220 {
221  r->Report( "" );
222 
224 
225  try
226  {
227  drcEngine.InitEngine( m_frame->GetDesignRulesPath() );
228  }
229  catch( PARSE_ERROR& )
230  {
231  r->Report( "" );
232  r->Report( _( "Report incomplete: could not compile custom design rules. " )
233  + "<a href='boardsetup'>" + _( "Show design rules." ) + "</a>" );
234  return;
235  }
236 
237  for( ZONE* zone : m_frame->GetBoard()->Zones() )
238  zone->CacheBoundingBox();
239 
241  {
242  for( ZONE* zone : footprint->Zones() )
243  zone->CacheBoundingBox();
244 
246  }
247 
248  auto constraint = drcEngine.EvalRules( aClearanceType, aA, aB, aLayer, r );
249  int clearance = constraint.m_Value.Min();
250 
251  wxString clearanceStr = StringFromValue( r->GetUnits(), clearance, true );
252 
253  r->Report( "" );
254  r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
255 }
256 
257 
258 void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem )
259 {
260  BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() );
261  BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() );
263 
264  if( !a || !b )
265  return;
266 
267  if( m_inspectClearanceDialog == nullptr )
268  {
269  m_inspectClearanceDialog = std::make_unique<DIALOG_INSPECTION_REPORTER>( m_frame );
270  m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) );
271 
272  m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW,
274  nullptr, this );
275  }
276 
278  r->SetUnits( m_frame->GetUserUnits() );
279  r->Clear();
280 
281  switch( aDRCItem->GetErrorCode() )
282  {
284  r->Report( "<h7>" + _( "Edge clearance resolution for:" ) + "</h7>" );
285 
286  r->Report( wxString::Format( "<ul><li>%s</li><li>%s</li></ul>",
288  EscapeHTML( getItemDescription( b ) ) ) );
289 
290  reportClearance( EDGE_CLEARANCE_CONSTRAINT, layer, a, b, r );
291  break;
292 
293  case DRCE_CLEARANCE:
294  if( a->Type() == PCB_TRACE_T || a->Type() == PCB_ARC_T )
295  {
296  layer = a->GetLayer();
297  }
298  else if( b->Type() == PCB_TRACE_T || b->Type() == PCB_ARC_T )
299  {
300  layer = b->GetLayer();
301  }
302  else if( a->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
303  {
304  PAD* pad = static_cast<PAD*>( a );
305 
306  if( pad->IsOnLayer( F_Cu ) )
307  layer = F_Cu;
308  else
309  layer = B_Cu;
310  }
311  else if( b->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
312  {
313  PAD* pad = static_cast<PAD*>( b );
314 
315  if( pad->IsOnLayer( F_Cu ) )
316  layer = F_Cu;
317  else
318  layer = B_Cu;
319  }
320 
321  r->Report( "<h7>" + _( "Clearance resolution for:" ) + "</h7>" );
322 
323  r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
324  _( "Layer" ),
325  EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
327  EscapeHTML( getItemDescription( b ) ) ) );
328 
329  reportClearance( CLEARANCE_CONSTRAINT, layer, a, b, r );
330  break;
331 
332  default:
333  return;
334  }
335 
336  r->Flush();
337 
338  m_inspectClearanceDialog->Raise();
339  m_inspectClearanceDialog->Show( true );
340 }
341 
342 
344 {
346  const PCB_SELECTION& selection = selTool->GetSelection();
348 
349  if( selection.Size() != 2 )
350  {
351  m_frame->ShowInfoBarError( _( "Select two items for a clearance resolution report." ) );
352  return 0;
353  }
354 
355  if( m_inspectClearanceDialog == nullptr )
356  {
357  m_inspectClearanceDialog = std::make_unique<DIALOG_INSPECTION_REPORTER>( m_frame );
358  m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) );
359 
360  m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW,
362  nullptr, this );
363  }
364 
366  r->SetUnits( m_frame->GetUserUnits() );
367  r->Clear();
368 
369  BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
370  BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
371 
372  auto hasHole =
373  []( BOARD_ITEM* aItem )
374  {
375  PAD* pad = dynamic_cast<PAD*>( aItem );
376  return pad && pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0;
377  };
378 
379  wxCHECK( a && b, 0 );
380 
381  if( a->Type() == PCB_GROUP_T )
382  {
383  PCB_GROUP* ag = static_cast<PCB_GROUP*>( a );
384 
385  if( ag->GetItems().empty() )
386  {
387  m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
388  return 0;
389  }
390 
391  a = *ag->GetItems().begin();
392  }
393 
394  if( b->Type() == PCB_GROUP_T )
395  {
396  PCB_GROUP* bg = static_cast<PCB_GROUP*>( b );
397 
398  if( bg->GetItems().empty() )
399  {
400  m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
401  return 0;
402  }
403 
404  b = *bg->GetItems().begin();
405  }
406 
407  // a and b could be null after group tests above.
408  wxCHECK( a && b, 0 );
409 
410  if( a->Type() == PCB_TRACE_T || a->Type() == PCB_ARC_T )
411  {
412  layer = a->GetLayer();
413  }
414  else if( b->Type() == PCB_TRACE_T || b->Type() == PCB_ARC_T )
415  {
416  layer = b->GetLayer();
417  }
418  else if( a->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
419  {
420  PAD* pad = static_cast<PAD*>( a );
421 
422  if( pad->IsOnLayer( F_Cu ) )
423  layer = F_Cu;
424  else
425  layer = B_Cu;
426  }
427  else if( b->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
428  {
429  PAD* pad = static_cast<PAD*>( b );
430 
431  if( pad->IsOnLayer( F_Cu ) )
432  layer = F_Cu;
433  else
434  layer = B_Cu;
435  }
436 
437  if( a->Type() != PCB_ZONE_T && b->Type() == PCB_ZONE_T )
438  std::swap( a, b );
439  else if( !a->IsConnected() && b->IsConnected() )
440  std::swap( a, b );
441 
442  if( layer == F_SilkS || layer == B_SilkS )
443  {
444  r->Report( "<h7>" + _( "Silkscreen clearance resolution for:" ) + "</h7>" );
445 
446  r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
447  _( "Layer" ),
448  EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
450  EscapeHTML( getItemDescription( b ) ) ) );
451 
452  reportClearance( SILK_CLEARANCE_CONSTRAINT, layer, a, b, r );
453  }
454  else if( !( a->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() )
455  {
456  if( hasHole( a ) )
457  {
458  r->Report( "<h7>" + _( "Hole clearance resolution for:" ) + "</h7>" );
459 
460  r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
461  _( "Layer" ),
462  EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
464  EscapeHTML( getItemDescription( b ) ) ) );
465 
466  reportClearance( HOLE_CLEARANCE_CONSTRAINT, layer, a, b, r );
467  }
468  else
469  {
470  r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
471  a->GetSelectMenuText( r->GetUnits() ),
472  m_frame->GetBoard()->GetLayerName( layer ) ) );
473  }
474  }
475  else if( !( b->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() )
476  {
477  if( hasHole( b ) )
478  {
479  r->Report( "<h7>" + _( "Hole clearance resolution for:" ) + "</h7>" );
480 
481  r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
482  _( "Layer" ),
483  EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
485  EscapeHTML( getItemDescription( a ) ) ) );
486 
487  reportClearance( HOLE_CLEARANCE_CONSTRAINT, layer, b, a, r );
488  }
489  else
490  {
491  r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
492  b->GetSelectMenuText( r->GetUnits() ),
493  m_frame->GetBoard()->GetLayerName( layer ) ) );
494  }
495  }
496  else if( a->GetLayer() == Edge_Cuts || a->GetLayer() == Margin
497  || b->GetLayer() == Edge_Cuts || b->GetLayer() == Margin )
498  {
499  r->Report( "<h7>" + _( "Edge clearance resolution for:" ) + "</h7>" );
500 
501  r->Report( wxString::Format( "<ul><li>%s</li><li>%s</li></ul>",
503  EscapeHTML( getItemDescription( b ) ) ) );
504 
505  reportClearance( EDGE_CLEARANCE_CONSTRAINT, layer, a, b, r );
506  }
507  else
508  {
509  r->Report( "<h7>" + _( "Clearance resolution for:" ) + "</h7>" );
510 
511  r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
512  _( "Layer" ),
513  EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
515  EscapeHTML( getItemDescription( b ) ) ) );
516 
517  BOARD_CONNECTED_ITEM* ac = a->IsConnected() ?
518  static_cast<BOARD_CONNECTED_ITEM*>( a ) : nullptr;
519  BOARD_CONNECTED_ITEM* bc = b->IsConnected() ?
520  static_cast<BOARD_CONNECTED_ITEM*>( b ) : nullptr;
521 
522  if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() )
523  {
524  // Same nets....
525 
526  if( ac->Type() == PCB_ZONE_T && bc->Type() == PCB_PAD_T )
527  {
528  reportZoneConnection( static_cast<ZONE*>( ac ), static_cast<PAD*>( bc ), r );
529  }
530  else
531  {
532  r->Report( "" );
533  r->Report( _( "Items belong to the same net. Clearance is 0." ) );
534  }
535  }
536  else
537  {
538  // Different nets (or one or both unconnected)....
539  reportClearance( CLEARANCE_CONSTRAINT, layer, a, b, r );
540  }
541  }
542 
543  r->Flush();
544 
545  m_inspectClearanceDialog->Raise();
546  m_inspectClearanceDialog->Show( true );
547  return 0;
548 }
549 
550 
552 {
554  const PCB_SELECTION& selection = selTool->GetSelection();
555 
556  if( selection.Size() != 1 )
557  {
558  m_frame->ShowInfoBarError( _( "Select an item for a constraints resolution report." ) );
559  return 0;
560  }
561 
562  if( m_inspectConstraintsDialog == nullptr )
563  {
564  m_inspectConstraintsDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame );
565  m_inspectConstraintsDialog->SetTitle( _( "Constraints Report" ) );
566 
568  wxEVT_CLOSE_WINDOW,
570  nullptr, this );
571  }
572 
573  m_inspectConstraintsDialog->DeleteAllPages();
574 
575  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
577  bool courtyardError = false;
578  bool compileError = false;
579 
580  try
581  {
582  drcEngine.InitEngine( m_frame->GetDesignRulesPath() );
583  }
584  catch( PARSE_ERROR& )
585  {
586  compileError = true;
587  }
588 
589  for( ZONE* zone : m_frame->GetBoard()->Zones() )
590  zone->CacheBoundingBox();
591 
593  {
594  for( ZONE* zone : footprint->Zones() )
595  zone->CacheBoundingBox();
596 
598 
599  if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
600  courtyardError = true;
601  }
602 
603  WX_HTML_REPORT_BOX* r = nullptr;
604 
605  if( item->Type() == PCB_TRACE_T )
606  {
607  r = m_inspectConstraintsDialog->AddPage( _( "Track Width" ) );
608 
609  r->Report( "<h7>" + _( "Track width resolution for:" ) + "</h7>" );
610  r->Report( "<ul><li>" + EscapeHTML( getItemDescription( item ) ) + "</li></ul>" );
611  r->Report( "" );
612 
613  if( compileError )
614  {
615  r->Report( "" );
616  r->Report( _( "Report incomplete: could not compile custom design rules. " )
617  + "<a href='boardsetup'>" + _( "Show design rules." ) + "</a>" );
618  }
619  else
620  {
621  auto constraint = drcEngine.EvalRules( TRACK_WIDTH_CONSTRAINT, item, nullptr,
622  item->GetLayer(), r );
623 
624  wxString min = _( "undefined" );
625  wxString max = _( "undefined" );
626 
627  if( constraint.m_Value.HasMin() )
628  min = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
629 
630  if( constraint.m_Value.HasMax() )
631  max = StringFromValue( r->GetUnits(), constraint.m_Value.Max(), true );
632 
633  r->Report( "" );
634  r->Report( wxString::Format( _( "Width constraints: min %s max %s." ),
635  min,
636  max ) );
637  }
638 
639  r->Flush();
640  }
641 
642  if( item->Type() == PCB_VIA_T )
643  {
644  r = m_inspectConstraintsDialog->AddPage( _( "Via Diameter" ) );
645 
646  r->Report( "<h7>" + _( "Via diameter resolution for:" ) + "</h7>" );
647  r->Report( "<ul><li>" + EscapeHTML( getItemDescription( item ) ) + "</li></ul>" );
648  r->Report( "" );
649 
650  if( compileError )
651  {
652  r->Report( "" );
653  r->Report( _( "Report incomplete: could not compile custom design rules. " )
654  + "<a href='boardsetup'>" + _( "Show design rules." ) + "</a>" );
655  }
656  else
657  {
658  // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
659  auto constraint = drcEngine.EvalRules( VIA_DIAMETER_CONSTRAINT, item, nullptr,
660  UNDEFINED_LAYER, r );
661 
662  wxString min = _( "undefined" );
663  wxString max = _( "undefined" );
664 
665  if( constraint.m_Value.HasMin() )
666  min = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
667 
668  if( constraint.m_Value.HasMax() )
669  max = StringFromValue( r->GetUnits(), constraint.m_Value.Max(), true );
670 
671  r->Report( "" );
672  r->Report( wxString::Format( _( "Diameter constraints: min %s max %s." ),
673  min,
674  max ) );
675  }
676 
677  r->Flush();
678 
679  r = m_inspectConstraintsDialog->AddPage( _( "Via Annular Width" ) );
680 
681  r->Report( "<h7>" + _( "Via annular width resolution for:" ) + "</h7>" );
682  r->Report( "<ul><li>" + EscapeHTML( getItemDescription( item ) ) + "</li></ul>" );
683  r->Report( "" );
684 
685  if( compileError )
686  {
687  r->Report( "" );
688  r->Report( _( "Report incomplete: could not compile custom design rules. " )
689  + "<a href='boardsetup'>" + _( "Show design rules." ) + "</a>" );
690  }
691  else
692  {
693  // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
694  auto constraint = drcEngine.EvalRules( ANNULAR_WIDTH_CONSTRAINT, item, nullptr,
695  UNDEFINED_LAYER, r );
696 
697  wxString min = _( "undefined" );
698  wxString max = _( "undefined" );
699 
700  if( constraint.m_Value.HasMin() )
701  min = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
702 
703  if( constraint.m_Value.HasMax() )
704  max = StringFromValue( r->GetUnits(), constraint.m_Value.Max(), true );
705 
706  r->Report( "" );
707  r->Report( wxString::Format( _( "Annular width constraints: min %s max %s." ),
708  min,
709  max ) );
710  }
711 
712  r->Flush();
713  }
714 
715  if( ( item->Type() == PCB_PAD_T && static_cast<PAD*>( item )->GetDrillSize().x > 0 )
716  || item->Type() == PCB_VIA_T )
717  {
718  r = m_inspectConstraintsDialog->AddPage( _( "Hole Size" ) );
719 
720  r->Report( "<h7>" + _( "Hole diameter resolution for:" ) + "</h7>" );
721  r->Report( "<ul><li>" + EscapeHTML( getItemDescription( item ) ) + "</li></ul>" );
722  r->Report( "" );
723 
724  if( compileError )
725  {
726  r->Report( "" );
727  r->Report( _( "Report incomplete: could not compile custom design rules. " )
728  + "<a href='boardsetup'>" + _( "Show design rules." ) + "</a>" );
729  }
730  else
731  {
732  // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
733  auto constraint = drcEngine.EvalRules( HOLE_SIZE_CONSTRAINT, item, nullptr,
734  UNDEFINED_LAYER, r );
735 
736  wxString min = _( "undefined" );
737 
738  if( constraint.m_Value.HasMin() )
739  min = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
740 
741  r->Report( "" );
742  r->Report( wxString::Format( _( "Hole constraint: min %s." ), min ) );
743  }
744 
745  r->Flush();
746  }
747 
748  r = m_inspectConstraintsDialog->AddPage( _( "Keepouts" ) );
749 
750  r->Report( "<h7>" + _( "Keepout resolution for:" ) + "</h7>" );
751  r->Report( "<ul><li>" + EscapeHTML( getItemDescription( item ) ) + "</li></ul>" );
752  r->Report( "" );
753 
754  if( compileError )
755  {
756  r->Report( "" );
757  r->Report( _( "Report incomplete: could not compile custom design rules. " )
758  + "<a href='boardsetup'>" + _( "Show design rules." ) + "</a>" );
759  }
760  else
761  {
762  if( courtyardError )
763  {
764  r->Report( "" );
765  r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
766  + " <a href='drc'>" + _( "Run DRC for a full analysis." ) + "</a>" );
767  }
768 
769  auto constraint = drcEngine.EvalRules( DISALLOW_CONSTRAINT, item, nullptr, item->GetLayer(),
770  r );
771 
772  r->Report( "" );
773 
774  if( constraint.m_DisallowFlags )
775  r->Report( _( "Item <b>disallowed</b> at current location." ) );
776  else
777  r->Report( _( "Item allowed at current location." ) );
778  }
779 
780  r->Flush();
781 
782  m_inspectConstraintsDialog->FinishInitialization();
784  m_inspectConstraintsDialog->Show( true );
785  return 0;
786 }
787 
788 
790 {
791  // Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
792  if( m_probingSchToPcb )
793  return 0;
794 
796  const PCB_SELECTION& selection = selTool->GetSelection();
797 
798  if( selection.Size() == 1 )
799  m_frame->SendMessageToEESCHEMA( static_cast<BOARD_ITEM*>( selection.Front() ) );
800  else
801  m_frame->SendMessageToEESCHEMA( nullptr );
802 
803  // Update 3D viewer highlighting
804  m_frame->Update3DView( false, frame()->GetDisplayOptions().m_Live3DRefresh );
805 
806  return 0;
807 }
808 
809 
811 {
812  BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
813 
814  m_probingSchToPcb = true; // recursion guard
815  {
817 
818  if( item )
819  m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) item );
820  }
821  m_probingSchToPcb = false;
822 
823  bool request3DviewRedraw = frame()->GetDisplayOptions().m_Live3DRefresh;
824 
825  if( item && item->Type() != PCB_FOOTPRINT_T )
826  request3DviewRedraw = false;
827 
828  // Update 3D viewer highlighting
829  if( request3DviewRedraw )
830  m_frame->Update3DView( false, true );
831 
832  return 0;
833 }
834 
835 
836  bool BOARD_INSPECTION_TOOL::highlightNet( const VECTOR2D& aPosition, bool aUseSelection )
837 {
838  BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
841 
842  int net = -1;
843  bool enableHighlight = false;
844 
845  if( aUseSelection )
846  {
847  const PCB_SELECTION& selection = selectionTool->GetSelection();
848  std::set<int> netcodes;
849 
850  for( auto item : selection )
851  {
852  if( auto ci = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
853  netcodes.insert( ci->GetNetCode() );
854  }
855 
856  enableHighlight = !netcodes.empty();
857 
858  if( enableHighlight && netcodes.size() > 1 )
859  {
860  // If we are doing a multi-highlight, cross-probing back and other stuff is not
861  // yet supported
862  settings->SetHighlight( netcodes );
864 
865  for( int multiNet : netcodes )
866  board->SetHighLightNet( multiNet, true );
867 
868  board->HighLightON();
870  m_currentlyHighlighted = netcodes;
871  return true;
872  }
873  else if( enableHighlight )
874  {
875  net = *netcodes.begin();
876  }
877  }
878 
879  // If we didn't get a net to highlight from the selection, use the cursor
880  if( net < 0 )
881  {
883  GENERAL_COLLECTOR collector;
884 
885  PCB_LAYER_ID activeLayer = static_cast<PCB_LAYER_ID>( view()->GetTopLayer() );
886  guide.SetPreferredLayer( activeLayer );
887 
888  // Find a connected item for which we are going to highlight a net
889  collector.Collect( board, GENERAL_COLLECTOR::PadsOrTracks, (wxPoint) aPosition, guide );
890 
891  if( collector.GetCount() == 0 )
892  collector.Collect( board, GENERAL_COLLECTOR::Zones, (wxPoint) aPosition, guide );
893 
894  // Apply the active selection filter, except we want to allow picking locked items for
895  // highlighting even if the user has disabled them for selection
896  SELECTION_FILTER_OPTIONS& filter = selectionTool->GetFilter();
897 
898  bool saved = filter.lockedItems;
899  filter.lockedItems = true;
900 
901  selectionTool->FilterCollectedItems( collector );
902 
903  filter.lockedItems = saved;
904 
905  // Clear the previous highlight
906  m_frame->SendMessageToEESCHEMA( nullptr );
907 
908  bool highContrast = settings->GetHighContrast();
909  PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
910 
911  for( int i = collector.GetCount() - 1; i >= 0; i-- )
912  {
913  LSET itemLayers = collector[i]->GetLayerSet();
914 
915  if( ( itemLayers & LSET::AllCuMask() ).none() ||
916  ( highContrast && !itemLayers.Contains( contrastLayer ) ) )
917  {
918  collector.Remove( i );
919  continue;
920  }
921  }
922 
923  enableHighlight = ( collector.GetCount() > 0 );
924 
925  // Obtain net code for the clicked item
926  if( enableHighlight )
927  {
928  BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
929 
930  if( targetItem->Type() == PCB_PAD_T )
931  m_frame->SendMessageToEESCHEMA( targetItem );
932 
933  net = targetItem->GetNetCode();
934  }
935  }
936 
937  auto& netcodes = settings->GetHighlightNetCodes();
938 
939  // Toggle highlight when the same net was picked
940  if( net > 0 && netcodes.count( net ) )
941  enableHighlight = !settings->IsHighlightEnabled();
942 
943  if( enableHighlight != settings->IsHighlightEnabled() || !netcodes.count( net ) )
944  {
945  if( !netcodes.empty() )
946  m_lastHighlighted = netcodes;
947 
948  settings->SetHighlight( enableHighlight, net );
950  }
951 
952  // Store the highlighted netcode in the current board (for dialogs for instance)
953  if( enableHighlight && net >= 0 )
954  {
955  m_currentlyHighlighted = netcodes;
956  board->SetHighLightNet( net );
957  board->HighLightON();
958 
959  NETINFO_ITEM* netinfo = board->FindNet( net );
960 
961  if( netinfo )
962  {
963  MSG_PANEL_ITEMS items;
964  netinfo->GetMsgPanelInfo( m_frame, items );
965  m_frame->SetMsgPanel( items );
967  }
968  }
969  else
970  {
971  m_currentlyHighlighted.clear();
975  }
976 
977  return true;
978 }
979 
980 
982 {
983  int netcode = aEvent.Parameter<intptr_t>();
985  const std::set<int>& highlighted = settings->GetHighlightNetCodes();
986 
987  if( netcode > 0 )
988  {
989  m_lastHighlighted = highlighted;
990  settings->SetHighlight( true, netcode );
992  m_currentlyHighlighted.clear();
993  m_currentlyHighlighted.insert( netcode );
994  }
995  else if( aEvent.IsAction( &PCB_ACTIONS::highlightNetSelection ) )
996  {
997  // Highlight selection (cursor position will be ignored)
998  highlightNet( getViewControls()->GetMousePosition(), true );
999  }
1000  else if( aEvent.IsAction( &PCB_ACTIONS::toggleLastNetHighlight ) )
1001  {
1002  std::set<int> temp = highlighted;
1003  settings->SetHighlight( m_lastHighlighted );
1006  m_lastHighlighted = temp;
1007  }
1008  else if( aEvent.IsAction( &PCB_ACTIONS::toggleNetHighlight ) )
1009  {
1010  bool turnOn = highlighted.empty() && !m_currentlyHighlighted.empty();
1011  settings->SetHighlight( m_currentlyHighlighted, turnOn );
1013  }
1014  else // Highlight the net belonging to the item under the cursor
1015  {
1016  highlightNet( getViewControls()->GetMousePosition(), false );
1017  }
1018 
1019  return 0;
1020 }
1021 
1022 
1024 {
1025  BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1027 
1028  m_currentlyHighlighted.clear();
1029  m_lastHighlighted.clear();
1030 
1032  settings->SetHighlight( false );
1036  return 0;
1037 }
1038 
1039 #if 0
1041 {
1042  std::string tool = aEvent.GetCommandStr().get();
1044 
1045  // Deactivate other tools; particularly important if another PICKER is currently running
1046  Activate();
1047 
1048  // If the keyboard hotkey was triggered and we are already in the highlight tool, behave
1049  // the same as a left-click. Otherwise highlight the net of the selected item(s), or if
1050  // there is no selection, then behave like a ctrl-left-click.
1052  {
1053  bool use_selection = m_frame->IsCurrentTool( PCB_ACTIONS::highlightNetTool );
1054  highlightNet( getViewControls()->GetMousePosition(), use_selection );
1055  }
1056 
1057  picker->SetClickHandler(
1058  [this] ( const VECTOR2D& pt ) -> bool
1059  {
1060  highlightNet( pt, false );
1061  return true;
1062  } );
1063 
1064  picker->SetLayerSet( LSET::AllCuMask() );
1065  picker->SetSnapping( false );
1066 
1067  m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );
1068 
1069  return 0;
1070 }
1071 #endif
1072 
1074 {
1075  std::string tool = aEvent.GetCommandStr().get();
1077  BOARD* board = getModel<BOARD>();
1078 
1079  // Deactivate other tools; particularly important if another PICKER is currently running
1080  Activate();
1081 
1082  picker->SetClickHandler(
1083  [this, board]( const VECTOR2D& pt ) -> bool
1084  {
1085  const PCB_DISPLAY_OPTIONS& opt = displayOptions();
1087 
1090  PCB_SELECTION& selection = selectionTool->GetSelection();
1091 
1092  if( selection.Empty() )
1093  {
1096  selection = selectionTool->GetSelection();
1097  }
1098 
1099  if( selection.Empty() )
1100  {
1101  // Clear the previous local ratsnest if we click off all items
1102  for( FOOTPRINT* fp : board->Footprints() )
1103  {
1104  for( PAD* pad : fp->Pads() )
1105  pad->SetLocalRatsnestVisible( opt.m_ShowGlobalRatsnest );
1106  }
1107  }
1108  else
1109  {
1110  for( EDA_ITEM* item : selection )
1111  {
1112  if( PAD* pad = dyn_cast<PAD*>( item) )
1113  {
1114  pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
1115  }
1116  else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
1117  {
1118  if( !fp->Pads().empty() )
1119  {
1120  bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
1121 
1122  for( PAD* childPad : fp->Pads() )
1123  childPad->SetLocalRatsnestVisible( enable );
1124  }
1125  }
1126  }
1127  }
1128 
1130 
1131  return true;
1132  } );
1133 
1134  picker->SetFinalizeHandler(
1135  [this, board]( int aCondition )
1136  {
1137  const PCB_DISPLAY_OPTIONS& opt = displayOptions();
1138 
1139  if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
1140  {
1141  for( FOOTPRINT* fp : board->Footprints() )
1142  {
1143  for( PAD* pad : fp->Pads() )
1144  pad->SetLocalRatsnestVisible( opt.m_ShowGlobalRatsnest );
1145  }
1146  }
1147  } );
1148 
1149  m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );
1150 
1151  return 0;
1152 }
1153 
1154 
1156 {
1157  VECTOR2I delta;
1158 
1159  // If we have passed the simple move vector, we can update without recalculation
1160  if( aEvent.Parameter<VECTOR2I*>() )
1161  {
1162  delta = *aEvent.Parameter<VECTOR2I*>();
1163  delete aEvent.Parameter<VECTOR2I*>();
1164  }
1165  else
1166  {
1167  // We can delete the existing map to force a recalculation
1168  delete m_dynamicData;
1169  m_dynamicData = nullptr;
1170  }
1171 
1172  auto selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1173  auto& selection = selectionTool->GetSelection();
1174  auto connectivity = getModel<BOARD>()->GetConnectivity();
1175 
1176  if( selection.Empty() )
1177  {
1178  connectivity->ClearDynamicRatsnest();
1179  delete m_dynamicData;
1180  m_dynamicData = nullptr;
1181  }
1182  else
1183  {
1184  calculateSelectionRatsnest( delta );
1185  }
1186 
1187  return 0;
1188 }
1189 
1190 
1192 {
1193  getModel<BOARD>()->GetConnectivity()->ClearDynamicRatsnest();
1194  delete m_dynamicData;
1195  m_dynamicData = nullptr;
1196 
1197  return 0;
1198 }
1199 
1200 
1202 {
1204  SELECTION& selection = selectionTool->GetSelection();
1205  std::shared_ptr<CONNECTIVITY_DATA> connectivity = board()->GetConnectivity();
1206  std::vector<BOARD_ITEM*> items;
1207  std::deque<EDA_ITEM*> queued_items( selection.begin(), selection.end() );
1208 
1209  for( std::size_t i = 0; i < queued_items.size(); ++i )
1210  {
1211  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( queued_items[i] );
1212 
1213  if( item->Type() == PCB_FOOTPRINT_T )
1214  {
1215  for( PAD* pad : static_cast<FOOTPRINT*>( item )->Pads() )
1216  {
1217  if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1218  items.push_back( pad );
1219  }
1220  }
1221  else if( item->Type() == PCB_GROUP_T )
1222  {
1223  PCB_GROUP *group = static_cast<PCB_GROUP*>( item );
1224  group->RunOnDescendants( [ &queued_items ]( BOARD_ITEM *aItem )
1225  {
1226  queued_items.push_back( aItem );
1227  } );
1228  }
1229  else if( BOARD_CONNECTED_ITEM* boardItem = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
1230  {
1231  if( boardItem->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1232  items.push_back( boardItem );
1233  }
1234  }
1235 
1236  if( items.empty() || std::none_of( items.begin(), items.end(),
1237  []( const BOARD_ITEM* aItem )
1238  {
1239  return( aItem->Type() == PCB_TRACE_T
1240  || aItem->Type() == PCB_PAD_T
1241  || aItem->Type() == PCB_ARC_T
1242  || aItem->Type() == PCB_ZONE_T
1243  || aItem->Type() == PCB_FOOTPRINT_T
1244  || aItem->Type() == PCB_VIA_T );
1245  } ) )
1246  {
1247  return;
1248  }
1249 
1250  if( !m_dynamicData )
1251  {
1252  m_dynamicData = new CONNECTIVITY_DATA( items, true );
1253  connectivity->BlockRatsnestItems( items );
1254  }
1255  else
1256  {
1257  m_dynamicData->Move( aDelta );
1258  }
1259 
1260  connectivity->ComputeDynamicRatsnest( items, m_dynamicData );
1261 }
1262 
1263 
1265 {
1266  if( m_listNetsDialog == nullptr )
1267  {
1269  std::make_unique<DIALOG_NET_INSPECTOR>( m_frame, m_listNetsDialogSettings );
1270 
1271  m_listNetsDialog->Connect( wxEVT_CLOSE_WINDOW,
1272  wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr,
1273  this );
1274 
1275  m_listNetsDialog->Connect( wxEVT_BUTTON,
1276  wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr,
1277  this );
1278  }
1279 
1280  m_listNetsDialog->Raise();
1281  m_listNetsDialog->Show( true );
1282  return 0;
1283 }
1284 
1285 
1287 {
1289 
1290  m_listNetsDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1291  wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
1292 
1293  m_listNetsDialog->Disconnect( wxEVT_BUTTON,
1294  wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
1295 
1296  m_listNetsDialog->Destroy();
1297  m_listNetsDialog.release();
1298 }
1299 
1300 
1302 {
1303  m_inspectClearanceDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1305  nullptr, this );
1306 
1307  m_inspectClearanceDialog->Destroy();
1308  m_inspectClearanceDialog.release();
1309 }
1310 
1311 
1313 {
1314  m_inspectConstraintsDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1316  nullptr, this );
1317 
1318  m_inspectConstraintsDialog->Destroy();
1319  m_inspectConstraintsDialog.release();
1320 }
1321 
1322 
1324 {
1325  doHideNet( aEvent.Parameter<intptr_t>(), true );
1326  return 0;
1327 }
1328 
1329 
1331 {
1332  doHideNet( aEvent.Parameter<intptr_t>(), false );
1333  return 0;
1334 }
1335 
1336 
1337 void BOARD_INSPECTION_TOOL::doHideNet( int aNetCode, bool aHide )
1338 {
1339  KIGFX::PCB_RENDER_SETTINGS* rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>(
1341 
1343  SELECTION& selection = selectionTool->GetSelection();
1344 
1345  if( aNetCode <= 0 && !selection.Empty() )
1346  {
1347  for( EDA_ITEM* item : selection )
1348  {
1349  if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1350  {
1351  if( bci->GetNetCode() > 0 )
1352  doHideNet( bci->GetNetCode(), aHide );
1353  }
1354  }
1355 
1356  return;
1357  }
1358 
1359  if( aHide )
1360  rs->GetHiddenNets().insert( aNetCode );
1361  else
1362  rs->GetHiddenNets().erase( aNetCode );
1363 
1365  m_frame->GetCanvas()->Refresh();
1366 
1367  m_frame->GetAppearancePanel()->OnNetVisibilityChanged( aNetCode, !aHide );
1368 }
1369 
1370 
1372 {
1376 
1378  PCB_ACTIONS::localRatsnestTool.MakeEvent() );
1380  PCB_ACTIONS::hideDynamicRatsnest.MakeEvent() );
1382  PCB_ACTIONS::updateLocalRatsnest.MakeEvent() );
1383 
1388 
1395 
1398 }
void SetUnits(EDA_UNITS aUnits)
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
void BuildPolyCourtyards(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:1945
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:867
void reportClearance(DRC_CONSTRAINT_T aClearanceType, PCB_LAYER_ID aLayer, BOARD_ITEM *aA, BOARD_ITEM *aB, REPORTER *r)
int HideDynamicRatsnest(const TOOL_EVENT &aEvent)
Show local ratsnest of a component.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:187
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1343
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:41
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:80
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:283
bool IsCurrentTool(const TOOL_ACTION &aAction) const
static const TOOL_EVENT SelectedEvent
Definition: actions.h:199
wxString getItemDescription(BOARD_ITEM *aItem)
void SendCrossProbeNetName(const wxString &aNetName)
Send a net name to Eeschema for highlighting.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:360
ZONES & Zones()
Definition: board.h:239
BOARD * board() const
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:200
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2042
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:48
void Clear()
Delete the stored messages.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
A slimmed down version of WX_HTML_REPORT_PANEL.
static TOOL_ACTION hideNet
Definition: pcb_actions.h:455
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
virtual EDA_UNITS GetUnits() const
Definition: reporter.h:120
static TOOL_ACTION highlightItem
Definition: pcb_actions.h:454
const wxString & GetName() const
Definition: netclass.h:65
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
void Collect(BOARD_ITEM *aItem, const KICAD_T aScanList[], const wxPoint &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:571
int LocalRatsnestTool(const TOOL_EVENT &aEvent)
static TOOL_ACTION boardStatistics
Definition: pcb_actions.h:441
int InspectClearance(const TOOL_EVENT &aEvent)
static SELECTION_CONDITION OnlyTypes(const KICAD_T aTypes[])
Create a functor that tests if the selected items are only of given types.
int ClearHighlight(const TOOL_EVENT &aEvent)
Launch a tool to pick the item whose net is going to be highlighted.
virtual NETCLASS * GetNetClass() const
Return the NETCLASS for this item.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
void Flush()
Build the HTML messages page.
bool Contains(PCB_LAYER_ID aLayer)
See if the layer set contains a PCB layer.
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
ITER end()
Definition: selection.h:64
int CrossProbePcbToSch(const TOOL_EVENT &aEvent)
Highlight net belonging to the item under the cursor.
Smd pad, appears on the solder paste layer (default)
void InspectDRCError(const std::shared_ptr< RC_ITEM > &aDRCItem)
Show the clearance resolution for two selected items.
static ENUM_MAP< T > & Instance()
Definition: property.h:510
TOOL_MENU & GetToolMenu()
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
class PAD, a pad in a footprint
Definition: typeinfo.h:89
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:102
static const KICAD_T PadsOrTracks[]
A scan list for PADs, TRACKs, or VIAs.
Definition: collectors.h:288
static TOOL_ACTION localRatsnestTool
Definition: pcb_actions.h:459
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
bool IsConnected() const override
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
static TOOL_ACTION toggleLastNetHighlight
Definition: pcb_actions.h:451
APPEARANCE_CONTROLS * GetAppearancePanel()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:68
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
EDA_ITEM * GetModel() const
Definition: tool_manager.h:290
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:115
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
Plated through hole pad.
static TOOL_ACTION toggleNetHighlight
Definition: pcb_actions.h:452
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:88
static TOOL_ACTION inspectConstraints
Definition: pcb_actions.h:446
void SetLayerSet(LSET aLayerSet)
Set the tool's snap layer set.
static TOOL_ACTION pickerTool
Definition: actions.h:155
std::set< int > m_currentlyHighlighted
PCB_BASE_EDIT_FRAME * frame() const
int GetThermalReliefGap() const
Definition: zone.h:190
virtual PCB_LAYER_ID GetActiveLayer() const
DRC_CONSTRAINT_T
Definition: drc_rule.h:41
PCB specific render settings.
Definition: pcb_painter.h:64
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
PCB_SELECTION & GetSelection()
Return the set of currently selected items.
int InspectConstraints(const TOOL_EVENT &aEvent)
FP_ZONES & Zones()
Definition: footprint.h:165
ITER begin()
Definition: selection.h:63
std::set< int > m_lastHighlighted
Container for display options like enable/disable some optional drawings.
PCB_LAYER_ID
A quick note on layer IDs:
void SetPreferredLayer(PCB_LAYER_ID aLayer)
Definition: collectors.h:471
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
LSET is a set of PCB_LAYER_IDs.
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2020
pads are covered by copper
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString)
int HighlightNet(const TOOL_EVENT &aEvent)
Clear all board highlights.
const PCB_SELECTION & selection() const
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
std::unique_ptr< DIALOG_CONSTRAINTS_REPORTER > m_inspectConstraintsDialog
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:572
void onInspectClearanceDialogClosed(wxCommandEvent &aEvent)
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: zone.cpp:494
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:427
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
FOOTPRINTS & Footprints()
Definition: board.h:233
Generic, UI-independent tool event.
Definition: tool_event.h:152
FOOTPRINT * footprint() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:344
KIGFX::PCB_VIEW * view() const
static const KICAD_T Zones[]
A scan list for zones outlines only.
Definition: collectors.h:272
const wxString & GetNetname() const
Definition: netinfo.h:119
Items that may change while the view stays the same (noncached)
Definition: definitions.h:50
#define _(s)
int HighlightItem(const TOOL_EVENT &aEvent)
Update ratsnest for selected items.
static const TOOL_EVENT ClearedEvent
Selected item had a property changed (except movement)
Definition: actions.h:201
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:105
This file contains data structures that are saved in the project file or project local settings file ...
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2029
int ShowNet(const TOOL_EVENT &aEvent)
static TOOL_ACTION hideDynamicRatsnest
Definition: pcb_actions.h:460
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
bool highlightNet(const VECTOR2D &aPosition, bool aUseSelection)
Look for a BOARD_CONNECTED_ITEM in a given spot and if one is found - it enables highlight for its ne...
static void PadFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *sTool)
A selection filter which prunes the selection to contain only items of type PCB_PAD_T.
Definition: edit_tool.cpp:2188
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:97
Thermal relief only for THT pads.
static TOOL_ACTION inspectClearance
Definition: pcb_actions.h:445
const PCB_DISPLAY_OPTIONS & displayOptions() const
Generic tool for picking an item.
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:155
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
std::unique_ptr< DIALOG_NET_INSPECTOR > m_listNetsDialog
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:449
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:71
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void reportZoneConnection(ZONE *aZone, PAD *aPad, REPORTER *r)
int ListNets(const TOOL_EVENT &aEvent)
Hide the ratsnest for a given net.
void OnNetVisibilityChanged(int aNetCode, bool aVisibility)
Notifies the panel when a net has been hidden or shown via the external tool.
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:455
Use thermal relief for pads.
EDA_UNITS GetUnits() const override
int HighlightNetTool(const TOOL_EVENT &aEvent)
Perform the appropriate action in response to an Eeschema cross-probe.
void SendMessageToEESCHEMA(BOARD_ITEM *objectToSync)
Send a message to the schematic editor so that it may move its cursor to a symbol with the same refer...
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Handle the data for a net.
Definition: netinfo.h:64
static TOOL_ACTION showNet
Definition: pcb_actions.h:456
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:118
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:87
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:450
DIALOG_NET_INSPECTOR::SETTINGS m_listNetsDialogSettings
static TOOL_ACTION highlightNetSelection
Definition: pcb_actions.h:453
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:52
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
PAD_ATTRIB GetAttribute() const
Definition: pad.h:368
static TOOL_ACTION listNets
Definition: pcb_actions.h:344
bool Init() override
Init() is called once upon a registration of the tool.
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
Dialog to show common board info.
virtual wxString GetSelectMenuText(EDA_UNITS aUnits) const
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: eda_item.cpp:109
bool m_Live3DRefresh
If true, 3D viewer will redraw on every modification operation.
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:52
void onListNetsDialogClosed(wxCommandEvent &aEvent)
void doHideNet(int aNetCode, bool aHide)
Bind handlers to corresponding TOOL_ACTIONs.
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:62
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
int Size() const
Returns the number of selected parts.
Definition: selection.h:103
The selection tool: currently supports:
static TOOL_ACTION runDRC
Definition: pcb_actions.h:345
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
CONNECTIVITY_DATA * m_dynamicData
Pads are not covered.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:97
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
int HideNet(const TOOL_EVENT &aEvent)
Show the ratsnest for a given net.
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:204
void Activate()
Run the tool.
int UpdateSelectionRatsnest(const TOOL_EVENT &aEvent)
Hide ratsnest for selected items. Called when there are no items selected.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:134
SELECTION_FILTER_OPTIONS & GetFilter()
Set up handlers for various events.
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
void SetSnapping(bool aSnap)
Definition: picker_tool.h:64
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:461
static void FootprintFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *sTool)
A selection filter which prunes the selection to contain only items of type #PCB_MODULE_T.
Definition: edit_tool.cpp:2201
BOARD * GetBoard() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:377
ZONE_CONNECTION GetPadConnection(PAD *aPad, wxString *aSource=nullptr) const
Definition: zone.cpp:774
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Return the information about the NETINFO_ITEM in aList to display in the message panel.
Definition: pad.h:57
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:773
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
Definition: string.cpp:442
void FilterCollectedItems(GENERAL_COLLECTOR &aCollector)
#define MALFORMED_COURTYARDS
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
std::unique_ptr< DIALOG_INSPECTION_REPORTER > m_inspectClearanceDialog
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
void Move(const VECTOR2I &aDelta)
Moves the connectivity list anchors.
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:56
void calculateSelectionRatsnest(const VECTOR2I &aDelta)
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void onInspectConstraintsDialogClosed(wxCommandEvent &aEvent)
int ShowStatisticsDialog(const TOOL_EVENT &aEvent)
Show dialog with board statistics.
void InitEngine(const wxFileName &aRulePath)
Initializes the DRC engine.
Definition: drc_engine.cpp:628
void OnErrorLinkClicked(wxHtmlLinkEvent &event) override
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:176
EDA_ITEM * Front() const
Definition: selection.h:144
const wxString & ToString(T value) const
Definition: property.h:529
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113