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-2022 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>
29#include <tools/edit_tool.h>
30#include <pcb_painter.h>
32#include <drc/drc_engine.h>
36#include <string_utils.h>
38#include <pcbnew_settings.h>
41#include <drc/drc_item.h>
42#include <pad.h>
43
44
46 PCB_TOOL_BASE( "pcbnew.InspectionTool" ),
47 m_frame( nullptr )
48{
49 m_dynamicData = nullptr;
50}
51
52
54{
55public:
57 {
59 SetTitle( _( "Net Inspection Tools" ) );
60
63 AppendSeparator();
66 }
67
68private:
69 ACTION_MENU* create() const override
70 {
71 return new NET_CONTEXT_MENU();
72 }
73};
74
75
77{
79
80 std::shared_ptr<NET_CONTEXT_MENU> netSubMenu = std::make_shared<NET_CONTEXT_MENU>();
81 netSubMenu->SetTool( this );
82
83 static std::vector<KICAD_T> connectedTypes = { PCB_TRACE_T,
87 PCB_ZONE_T };
88
89 CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu();
90
91 selectionTool->GetToolMenu().RegisterSubMenu( netSubMenu );
92
93 menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ), 100 );
94
95 return true;
96}
97
98
100{
101 m_frame = getEditFrame<PCB_EDIT_FRAME>();
102}
103
104
106{
108 dialog.ShowModal();
109 return 0;
110}
111
112
113DRC_ENGINE BOARD_INSPECTION_TOOL::makeDRCEngine( bool* aCompileError, bool* aCourtyardError )
114{
116
117 try
118 {
120 }
121 catch( PARSE_ERROR& )
122 {
123 if( aCompileError )
124 *aCompileError = true;
125 }
126
127 for( ZONE* zone : m_frame->GetBoard()->Zones() )
128 zone->CacheBoundingBox();
129
131 {
132 for( ZONE* zone : footprint->Zones() )
133 zone->CacheBoundingBox();
134
136
137 if( aCourtyardError && ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
138 *aCourtyardError = true;
139 }
140
141 return engine;
142}
143
144
145bool isNPTHPad( BOARD_ITEM* aItem )
146{
147 return aItem->Type() == PCB_PAD_T
148 && static_cast<PAD*>( aItem )->GetAttribute() == PAD_ATTRIB::NPTH;
149}
150
151
153{
154 // Null items have no description
155 if( !aItem )
156 return wxString();
157
158 wxString msg = aItem->GetItemDescription( m_frame );
159
160 if( aItem->IsConnected() && !isNPTHPad( aItem ) )
161 {
162 BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem );
163
164 msg += wxS( " " ) + wxString::Format( _( "[netclass %s]" ),
165 cItem->GetEffectiveNetClass()->GetName() );
166 }
167
168 return msg;
169};
170
171
173{
174 r->Report( "" );
175 r->Report( _( "Report incomplete: could not compile custom design rules. " )
176 + wxT( "<a href='boardsetup'>" ) + _( "Show design rules." ) + wxT( "</a>" ) );
177}
178
179
180void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, REPORTER* r )
181{
182 r->Report( wxT( "<h7>" ) + EscapeHTML( aTitle ) + wxT( "</h7>" ) );
183 r->Report( wxT( "<ul><li>" ) + EscapeHTML( getItemDescription( a ) ) + wxT( "</li></ul>" ) );
184}
185
186
187void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, BOARD_ITEM* b,
188 REPORTER* r )
189{
190 r->Report( wxT( "<h7>" ) + EscapeHTML( aTitle ) + wxT( "</h7>" ) );
191 r->Report( wxT( "<ul><li>" ) + EscapeHTML( getItemDescription( a ) ) + wxT( "</li>" )
192 + wxT( "<li>" ) + EscapeHTML( getItemDescription( b ) ) + wxT( "</li></ul>" ) );
193}
194
195
196void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, BOARD_ITEM* b,
197 PCB_LAYER_ID aLayer, REPORTER* r )
198{
199 wxString layerStr = _( "Layer" ) + wxS( " " ) + m_frame->GetBoard()->GetLayerName( aLayer );
200
201 r->Report( wxT( "<h7>" ) + EscapeHTML( aTitle ) + wxT( "</h7>" ) );
202 r->Report( wxT( "<ul><li>" ) + EscapeHTML( layerStr ) + wxT( "</li>" )
203 + wxT( "<li>" ) + EscapeHTML( getItemDescription( a ) ) + wxT( "</li>" )
204 + wxT( "<li>" ) + EscapeHTML( getItemDescription( b ) ) + wxT( "</li></ul>" ) );
205}
206
207
208wxString reportMin( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
209{
210 if( aConstraint.m_Value.HasMin() )
211 return aFrame->StringFromValue( aConstraint.m_Value.Min(), true );
212 else
213 return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
214}
215
216
217wxString reportOpt( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
218{
219 if( aConstraint.m_Value.HasOpt() )
220 return aFrame->StringFromValue( aConstraint.m_Value.Opt(), true );
221 else
222 return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
223}
224
225
226wxString reportMax( PCB_BASE_FRAME* aFrame, DRC_CONSTRAINT& aConstraint )
227{
228 if( aConstraint.m_Value.HasMax() )
229 return aFrame->StringFromValue( aConstraint.m_Value.Max(), true );
230 else
231 return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
232}
233
234
235void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem )
236{
237 BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() );
238 BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() );
239 BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
240 BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
242
243 if( m_inspectClearanceDialog == nullptr )
244 {
245 m_inspectClearanceDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame );
246 m_inspectClearanceDialog->SetTitle( _( "Violation Report" ) );
247
248 m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW,
250 nullptr, this );
251 }
252
253 WX_HTML_REPORT_BOX* r = nullptr;
254 bool compileError = false;
255 DRC_ENGINE drcEngine = makeDRCEngine( &compileError );
256 DRC_CONSTRAINT constraint;
257 int clearance = 0;
258 wxString clearanceStr;
259
260 switch( aDRCItem->GetErrorCode() )
261 {
263 {
264 for( KIID id : aDRCItem->GetIDs() )
265 {
266 bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( m_frame->GetBoard()->GetItem( id ) );
267
268 if( ac && bc && ac->GetNetCode() != bc->GetNetCode() )
269 break;
270 }
271
272 r = m_inspectClearanceDialog->AddPage( _( "Uncoupled Length" ) );
273 reportHeader( _( "Diff pair uncoupled length resolution for:" ), ac, bc, r );
274
275 if( compileError )
277
278 constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r );
279
280 r->Report( "" );
281 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
282 reportMax( m_frame, constraint ) ) );
283 break;
284 }
285
286 case DRCE_TEXT_HEIGHT:
287 r = m_inspectClearanceDialog->AddPage( _( "Text Height" ) );
288 reportHeader( _( "Text height resolution for:" ), a, r );
289
290 if( compileError )
292
293 constraint = drcEngine.EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r );
294
295 r->Report( "" );
296 r->Report( wxString::Format( _( "Resolved height constraints: min %s; max %s." ),
297 reportMin( m_frame, constraint ),
298 reportMax( m_frame, constraint ) ) );
299 break;
300
302 r = m_inspectClearanceDialog->AddPage( _( "Text Thickness" ) );
303 reportHeader( _( "Text thickness resolution for:" ), a, r );
304
305 if( compileError )
307
308 constraint = drcEngine.EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r );
309
310 r->Report( "" );
311 r->Report( wxString::Format( _( "Resolved thickness constraints: min %s; max %s." ),
312 reportMin( m_frame, constraint ),
313 reportMax( m_frame, constraint ) ) );
314 break;
315
316 case DRCE_TRACK_WIDTH:
317 r = m_inspectClearanceDialog->AddPage( _( "Track Width" ) );
318 reportHeader( _( "Track width resolution for:" ), a, r );
319
320 if( compileError )
322
323 constraint = drcEngine.EvalRules( TRACK_WIDTH_CONSTRAINT, a, b, layer, r );
324
325 r->Report( "" );
326 r->Report( wxString::Format( _( "Resolved width constraints: min %s; max %s." ),
327 reportMin( m_frame, constraint ),
328 reportMax( m_frame, constraint ) ) );
329 break;
330
332 r = m_inspectClearanceDialog->AddPage( _( "Connection Width" ) );
333 reportHeader( _( "Connection width resolution for:" ), a, b, r );
334
335 if( compileError )
337
338 constraint = drcEngine.EvalRules( CONNECTION_WIDTH_CONSTRAINT, a, b, layer, r );
339
340 r->Report( "" );
341 r->Report( wxString::Format( _( "Resolved min connection width constraint: %s." ),
342 reportMin( m_frame, constraint ) ) );
343 break;
344
346 r = m_inspectClearanceDialog->AddPage( _( "Via Diameter" ) );
347 reportHeader( _( "Via diameter resolution for:" ), a, r );
348
349 if( compileError )
351
352 constraint = drcEngine.EvalRules( VIA_DIAMETER_CONSTRAINT, a, b, layer, r );
353
354 r->Report( "" );
355 r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
356 reportMin( m_frame, constraint ),
357 reportMax( m_frame, constraint ) ) );
358 break;
359
361 r = m_inspectClearanceDialog->AddPage( _( "Via Annulus" ) );
362 reportHeader( _( "Via annular width resolution for:" ), a, r );
363
364 if( compileError )
366
367 constraint = drcEngine.EvalRules( ANNULAR_WIDTH_CONSTRAINT, a, b, layer, r );
368
369 r->Report( "" );
370 r->Report( wxString::Format( _( "Resolved annular width constraints: min %s; max %s." ),
371 reportMin( m_frame, constraint ),
372 reportMax( m_frame, constraint ) ) );
373 break;
374
377 r = m_inspectClearanceDialog->AddPage( _( "Hole Size" ) );
378 reportHeader( _( "Hole diameter resolution for:" ), a, r );
379
380 if( compileError )
382
383 constraint = drcEngine.EvalRules( HOLE_SIZE_CONSTRAINT, a, b, layer, r );
384
385 r->Report( "" );
386 r->Report( wxString::Format( _( "Resolved diameter constraints: min %s; max %s." ),
387 reportMin( m_frame, constraint ),
388 reportMax( m_frame, constraint ) ) );
389 break;
390
392 r = m_inspectClearanceDialog->AddPage( _( "Hole Clearance" ) );
393 reportHeader( _( "Hole clearance resolution for:" ), a, b, r );
394
395 if( compileError )
397
398 if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
399 {
400 r->Report( "" );
401 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
402 }
403 else
404 {
405 constraint = drcEngine.EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
406 clearance = constraint.m_Value.Min();
407 clearanceStr = m_frame->StringFromValue( clearance, true );
408
409 r->Report( "" );
410 r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
411 }
412
413 r->Report( "" );
414 r->Report( "" );
415 r->Report( "" );
416 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
417
418 constraint = drcEngine.EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
419 clearance = constraint.m_Value.Min();
420 clearanceStr = m_frame->StringFromValue( clearance, true );
421
423 {
424 r->Report( "" );
425 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
426 }
427 else
428 {
429 r->Report( "" );
430 r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
431 }
432
433 break;
434
436 r = m_inspectClearanceDialog->AddPage( _( "Hole to Hole" ) );
437 reportHeader( _( "Hole to hole clearance resolution for:" ), a, b, r );
438
439 if( compileError )
441
442 constraint = drcEngine.EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
443 clearance = constraint.m_Value.Min();
444 clearanceStr = m_frame->StringFromValue( clearance, true );
445
446 r->Report( "" );
447 r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
448 break;
449
451 r = m_inspectClearanceDialog->AddPage( _( "Edge Clearance" ) );
452 reportHeader( _( "Edge clearance resolution for:" ), a, b, r );
453
454 if( compileError )
456
457 constraint = drcEngine.EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
458 clearance = constraint.m_Value.Min();
459 clearanceStr = m_frame->StringFromValue( clearance, true );
460
461 r->Report( "" );
462 r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
463 break;
464
465 case DRCE_CLEARANCE:
466 if( a->Type() == PCB_TRACE_T || a->Type() == PCB_ARC_T )
467 {
468 layer = a->GetLayer();
469 }
470 else if( b->Type() == PCB_TRACE_T || b->Type() == PCB_ARC_T )
471 {
472 layer = b->GetLayer();
473 }
474 else if( a->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
475 {
476 PAD* pad = static_cast<PAD*>( a );
477
478 if( pad->IsOnLayer( F_Cu ) )
479 layer = F_Cu;
480 else
481 layer = B_Cu;
482 }
483 else if( b->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB::SMD )
484 {
485 PAD* pad = static_cast<PAD*>( b );
486
487 if( pad->IsOnLayer( F_Cu ) )
488 layer = F_Cu;
489 else
490 layer = B_Cu;
491 }
492
493 r = m_inspectClearanceDialog->AddPage( _( "Clearance" ) );
494 reportHeader( _( "Clearance resolution for:" ), a, b, layer, r );
495
496 if( compileError )
498
499 if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
500 {
501 r->Report( "" );
502 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
503 }
504 else
505 {
506 constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, a, layer, r );
507 clearance = constraint.m_Value.Min();
508 clearanceStr = m_frame->StringFromValue( clearance, true );
509
510 r->Report( "" );
511 r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
512 }
513
514 r->Report( "" );
515 r->Report( "" );
516 r->Report( "" );
517 reportHeader( _( "Physical clearance resolution for:" ), a, b, layer, r );
518
519 constraint = drcEngine.EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
520 clearance = constraint.m_Value.Min();
521 clearanceStr = m_frame->StringFromValue( clearance, true );
522
524 {
525 r->Report( "" );
526 r->Report( _( "No 'physical_clearance' constraints defined." ) );
527 }
528 else
529 {
530 r->Report( "" );
531 r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
532 }
533
534 break;
535
536 default:
537 return;
538 }
539
540 r->Flush();
541
543 m_inspectClearanceDialog->Show( true );
544}
545
546
548{
550 const PCB_SELECTION& selection = selTool->GetSelection();
551
552 if( selection.Size() != 2 )
553 {
554 m_frame->ShowInfoBarError( _( "Select two items for a clearance resolution report." ) );
555 return 0;
556 }
557
558 BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
559 BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
560
561 wxCHECK( a && b, 0 );
562
563 if( a->Type() == PCB_GROUP_T )
564 {
565 PCB_GROUP* ag = static_cast<PCB_GROUP*>( a );
566
567 if( ag->GetItems().empty() )
568 {
569 m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
570 return 0;
571 }
572
573 a = *ag->GetItems().begin();
574 }
575
576 if( b->Type() == PCB_GROUP_T )
577 {
578 PCB_GROUP* bg = static_cast<PCB_GROUP*>( b );
579
580 if( bg->GetItems().empty() )
581 {
582 m_frame->ShowInfoBarError( _( "Cannot generate clearance report on empty group." ) );
583 return 0;
584 }
585
586 b = *bg->GetItems().begin();
587 }
588
589 // a and b could be null after group tests above.
590 wxCHECK( a && b, 0 );
591
592 if( m_inspectClearanceDialog == nullptr )
593 {
594 m_inspectClearanceDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame );
595 m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) );
596
597 m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW,
599 nullptr, this );
600 }
601
602 m_inspectClearanceDialog->DeleteAllPages();
603
604 if( a->Type() != PCB_ZONE_T && b->Type() == PCB_ZONE_T )
605 std::swap( a, b );
606 else if( !a->IsConnected() && b->IsConnected() )
607 std::swap( a, b );
608
609 WX_HTML_REPORT_BOX* r = nullptr;
611 LSET layerIntersection = a->GetLayerSet() & b->GetLayerSet();
612 LSET copperIntersection = layerIntersection & LSET::AllCuMask();
613 BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
614 BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
615 ZONE* zone = dynamic_cast<ZONE*>( a );
616 PAD* pad = dynamic_cast<PAD*>( b );
617 FOOTPRINT* aFP = dynamic_cast<FOOTPRINT*>( a );
618 FOOTPRINT* bFP = dynamic_cast<FOOTPRINT*>( b );
619
620 bool compileError = false;
621 DRC_ENGINE drcEngine = makeDRCEngine( &compileError );
622 DRC_CONSTRAINT constraint;
623 int clearance = 0;
624
625 if( copperIntersection.any() && zone && pad && zone->GetNetCode() == pad->GetNetCode() )
626 {
628
629 if( zone->IsOnLayer( active ) )
630 layer = active;
631 else if( zone->GetLayerSet().count() > 0 )
632 layer = zone->GetLayerSet().Seq().front();
633
634 r = m_inspectClearanceDialog->AddPage( _( "Zone" ) );
635 reportHeader( _( "Zone connection resolution for:" ), a, b, layer, r );
636
637 constraint = drcEngine.EvalZoneConnection( pad, zone, layer, r );
638
640 {
641 r->Report( "" );
642 r->Report( "" );
643 reportHeader( _( "Thermal relief gap resolution for:" ), a, b, layer, r );
644
645 constraint = drcEngine.EvalRules( THERMAL_RELIEF_GAP_CONSTRAINT, pad, zone, layer, r );
646 int gap = constraint.m_Value.Min();
647
648 if( compileError )
650
651 r->Report( "" );
652 r->Report( wxString::Format( _( "Resolved thermal relief gap: %s." ),
653 m_frame->StringFromValue( gap, true ) ) );
654
655 r->Report( "" );
656 r->Report( "" );
657 reportHeader( _( "Spoke width resolution for:" ), a, b, layer, r );
658
659 constraint = drcEngine.EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad, zone, layer, r );
660 int width = constraint.m_Value.Opt();
661
662 if( compileError )
664
665 r->Report( "" );
666 r->Report( wxString::Format( _( "Resolved thermal relief spoke width: %s." ),
667 m_frame->StringFromValue( width, true ) ) );
668
669 r->Report( "" );
670 r->Report( "" );
671 reportHeader( _( "Spoke count resolution for:" ), a, b, layer, r );
672
673 constraint = drcEngine.EvalRules( MIN_RESOLVED_SPOKES_CONSTRAINT, pad, zone, layer, r );
674 int minSpokes = constraint.m_Value.Min();
675
676 if( compileError )
678
679 r->Report( "" );
680 r->Report( wxString::Format( _( "Resolved min thermal relief spoke count: %d." ),
681 minSpokes ) );
682
683 std::shared_ptr<CONNECTIVITY_DATA> connectivity = pad->GetBoard()->GetConnectivity();
684 }
685 else if( constraint.m_ZoneConnection == ZONE_CONNECTION::NONE )
686 {
687 r->Report( "" );
688 r->Report( "" );
689 reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
690
691 clearance = zone->GetLocalClearance();
692 r->Report( "" );
693 r->Report( wxString::Format( _( "Zone clearance: %s." ),
694 m_frame->StringFromValue( clearance, true ) ) );
695
696 constraint = drcEngine.EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, pad, zone, layer, r );
697
698 if( constraint.m_Value.Min() > clearance )
699 {
700 clearance = constraint.m_Value.Min();
701
702 r->Report( "" );
703 r->Report( wxString::Format( _( "Overridden by larger physical clearance from %s;"
704 "clearance: %s." ),
705 EscapeHTML( constraint.GetName() ),
706 m_frame->StringFromValue( clearance, true ) ) );
707 }
708
709 if( !pad->FlashLayer( layer ) )
710 {
711 constraint = drcEngine.EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, pad, zone,
712 layer, r );
713
714 if( constraint.m_Value.Min() > clearance )
715 {
716 clearance = constraint.m_Value.Min();
717
718 r->Report( "" );
719 r->Report( wxString::Format( _( "Overridden by larger physical hole clearance from %s;"
720 "clearance: %s." ),
721 EscapeHTML( constraint.GetName() ),
722 m_frame->StringFromValue( clearance, true ) ) );
723 }
724 }
725
726 if( compileError )
728
729 r->Report( "" );
730 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
731 m_frame->StringFromValue( clearance, true ) ) );
732 }
733 else
734 {
735 r->Report( "" );
736 r->Report( "" );
737 reportHeader( _( "Zone clearance resolution for:" ), a, b, layer, r );
738
739 if( compileError )
741
742 // Report a 0 clearance for solid connections
743 r->Report( "" );
744 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
745 m_frame->StringFromValue( 0, true ) ) );
746 }
747
748 r->Flush();
749 }
750 else if( copperIntersection.any() && !aFP && !bFP )
751 {
752 PCB_LAYER_ID layer = active;
753
754 if( !copperIntersection.test( layer ) )
755 layer = copperIntersection.Seq().front();
756
757 r = m_inspectClearanceDialog->AddPage( m_frame->GetBoard()->GetLayerName( layer ) );
758 reportHeader( _( "Clearance resolution for:" ), a, b, layer, r );
759
760 if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() )
761 {
762 // Same nets....
763 r->Report( _( "Items belong to the same net. Clearance is 0." ) );
764 }
765 else
766 {
767 // Different nets (or one or both unconnected)....
768 constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, b, layer, r );
769 clearance = constraint.m_Value.Min();
770
771 if( compileError )
773
774 r->Report( "" );
775
776 if( clearance < 0 )
777 {
778 r->Report( wxString::Format( _( "Resolved clearance: %s; clearance will not be tested." ),
779 m_frame->StringFromValue( clearance, true ) ) );
780 }
781 else
782 {
783 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
784 m_frame->StringFromValue( clearance, true ) ) );
785 }
786 }
787
788 r->Flush();
789 }
790
791 if( ac && bc )
792 {
793 NETINFO_ITEM* refNet = ac->GetNet();
794 wxString coupledNet;
795 wxString dummy;
796
797 if( DRC_ENGINE::MatchDpSuffix( refNet->GetNetname(), coupledNet, dummy )
798 && bc->GetNetname() == coupledNet )
799 {
800 r = m_inspectClearanceDialog->AddPage( _( "Diff Pair" ) );
801 reportHeader( _( "Diff pair gap resolution for:" ), ac, bc, active, r );
802
803 constraint = drcEngine.EvalRules( DIFF_PAIR_GAP_CONSTRAINT, ac, bc, active, r );
804
805 r->Report( "" );
806 r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ),
807 reportMin( m_frame, constraint ),
808 reportOpt( m_frame, constraint ),
809 reportMax( m_frame, constraint ) ) );
810
811 r->Report( "" );
812 r->Report( "" );
813 r->Report( "" );
814 reportHeader( _( "Diff pair max uncoupled length resolution for:" ), ac, bc, active, r );
815
817 {
818 r->Report( "" );
819 r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
820 }
821 else
822 {
823 constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, ac, bc,
824 active, r );
825
826 r->Report( "" );
827 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
828 reportMax( m_frame, constraint ) ) );
829 }
830 r->Flush();
831 }
832 }
833
834 auto isOnCorrespondingLayer=
835 [&]( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, wxString* aWarning )
836 {
837 if( aItem->IsOnLayer( aLayer ) )
838 return true;
839
840 PCB_LAYER_ID correspondingMask = IsFrontLayer( aLayer ) ? F_Mask : B_Mask;
841 PCB_LAYER_ID correspondingCopper = IsFrontLayer( aLayer ) ? F_Cu : B_Cu;
842
843 if( aItem->IsOnLayer( aLayer ) )
844 return true;
845
846 if( aItem->IsOnLayer( correspondingMask ) )
847 return true;
848
849 if( aItem->IsTented() && aItem->IsOnLayer( correspondingCopper ) )
850 {
851 *aWarning = wxString::Format( _( "Note: %s is tented; clearance will only be "
852 "applied to holes." ),
853 getItemDescription( aItem ) );
854 return true;
855 }
856
857 return false;
858 };
859
860 for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
861 {
862 wxString warning;
863
864 if( ( a->IsOnLayer( layer ) && isOnCorrespondingLayer( b, layer, &warning ) )
865 || ( b->IsOnLayer( layer ) && isOnCorrespondingLayer( a, layer, &warning ) ) )
866 {
867 r = m_inspectClearanceDialog->AddPage( m_frame->GetBoard()->GetLayerName( layer ) );
868 reportHeader( _( "Silkscreen clearance resolution for:" ), a, b, layer, r );
869
870 constraint = drcEngine.EvalRules( SILK_CLEARANCE_CONSTRAINT, a, b, layer, r );
871 clearance = constraint.m_Value.Min();
872
873 if( compileError )
875
876 r->Report( "" );
877
878 if( !warning.IsEmpty() )
879 r->Report( warning );
880
881 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
882 m_frame->StringFromValue( clearance, true ) ) );
883
884 r->Flush();
885 }
886 }
887
888 for( PCB_LAYER_ID layer : { F_CrtYd, B_CrtYd } )
889 {
890 bool aCourtyard = aFP && !aFP->GetCourtyard( layer ).IsEmpty();
891 bool bCourtyard = bFP && !bFP->GetCourtyard( layer ).IsEmpty();
892
893 if( aCourtyard && bCourtyard )
894 {
895 r = m_inspectClearanceDialog->AddPage( m_frame->GetBoard()->GetLayerName( layer ) );
896 reportHeader( _( "Courtyard clearance resolution for:" ), a, b, layer, r );
897
898 constraint = drcEngine.EvalRules( COURTYARD_CLEARANCE_CONSTRAINT, a, b, layer, r );
899 clearance = constraint.m_Value.Min();
900
901 if( compileError )
903
904 r->Report( "" );
905 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
906 m_frame->StringFromValue( clearance, true ) ) );
907
908 r->Flush();
909 }
910 }
911
912 if( a->HasHole() || b->HasHole() )
913 {
915 bool pageAdded = false;
916
917 if( a->HasHole() && b->IsOnLayer( active ) && IsCopperLayer( active ) )
918 layer = active;
919 else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
920 layer = active;
921 else if( a->HasHole() && b->IsOnCopperLayer() )
922 layer = b->GetLayer();
923 else if( b->HasHole() && b->IsOnCopperLayer() )
924 layer = a->GetLayer();
925
926 if( layer >= 0 )
927 {
928 if( !pageAdded )
929 {
930 r = m_inspectClearanceDialog->AddPage( _( "Hole" ) );
931 pageAdded = true;
932 }
933 else
934 {
935 r->Report( "" );
936 r->Report( "" );
937 r->Report( "" );
938 }
939
940 reportHeader( _( "Hole clearance resolution for:" ), a, b, layer, r );
941
942 constraint = drcEngine.EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
943 clearance = constraint.m_Value.Min();
944
945 if( compileError )
947
948 r->Report( "" );
949 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
950 m_frame->StringFromValue( clearance, true ) ) );
951
952 r->Flush();
953 }
954
955 if( a->HasHole() && b->HasHole() )
956 {
957 if( !pageAdded )
958 {
959 r = m_inspectClearanceDialog->AddPage( _( "Hole" ) );
960 pageAdded = true;
961 }
962 else
963 {
964 r->Report( "" );
965 r->Report( "" );
966 r->Report( "" );
967 }
968
969 reportHeader( _( "Hole to hole clearance resolution for:" ), a, b, r );
970
971 constraint = drcEngine.EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
972 clearance = constraint.m_Value.Min();
973
974 if( compileError )
976
977 r->Report( "" );
978 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
979 m_frame->StringFromValue( clearance, true ) ) );
980
981 r->Flush();
982 }
983 }
984
985 for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
986 {
988
989 if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
990 {
991 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
992 layer = active;
993 else if( IsCopperLayer( b->GetLayer() ) )
994 layer = b->GetLayer();
995 }
996 else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
997 {
998 if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
999 layer = active;
1000 else if( IsCopperLayer( a->GetLayer() ) )
1001 layer = a->GetLayer();
1002 }
1003
1004 if( layer >= 0 )
1005 {
1006 wxString layerName = m_frame->GetBoard()->GetLayerName( edgeLayer );
1007 r = m_inspectClearanceDialog->AddPage( layerName + wxS( " " ) + _( "Clearance" ) );
1008 reportHeader( _( "Edge clearance resolution for:" ), a, b, layer, r );
1009
1010 constraint = drcEngine.EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1011 clearance = constraint.m_Value.Min();
1012
1013 if( compileError )
1014 reportCompileError( r );
1015
1016 r->Report( "" );
1017 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
1018 m_frame->StringFromValue( clearance, true ) ) );
1019
1020 r->Flush();
1021 }
1022 }
1023
1024 r = m_inspectClearanceDialog->AddPage( _( "Physical Clearances" ) );
1025
1026 auto reportPhysicalClearance =
1027 [&]( PCB_LAYER_ID aLayer )
1028 {
1029 reportHeader( _( "Physical clearance resolution for:" ), a, b, aLayer, r );
1030
1031 constraint = drcEngine.EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, aLayer, r );
1032 clearance = constraint.m_Value.Min();
1033
1034 if( compileError )
1035 {
1036 reportCompileError( r );
1037 }
1039 {
1040 r->Report( "" );
1041 r->Report( _( "No 'physical_clearance' constraints defined." ) );
1042 }
1043 else
1044 {
1045 r->Report( "" );
1046 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
1047 m_frame->StringFromValue( clearance, true ) ) );
1048 }
1049
1050 r->Report( "" );
1051 r->Report( "" );
1052 r->Report( "" );
1053 };
1054
1055 if( layerIntersection.any() )
1056 {
1057 PCB_LAYER_ID layer = active;
1058
1059 if( !layerIntersection.test( layer ) )
1060 layer = layerIntersection.Seq().front();
1061
1062 reportPhysicalClearance( layer );
1063 }
1064
1065 if( aFP && b->IsOnLayer( Edge_Cuts ) )
1066 {
1067 if( !aFP->GetCourtyard( F_CrtYd ).IsEmpty() )
1068 reportPhysicalClearance( F_CrtYd );
1069
1070 if( !aFP->GetCourtyard( B_CrtYd ).IsEmpty() )
1071 reportPhysicalClearance( B_CrtYd );
1072 }
1073 else if( bFP && a->IsOnLayer( Edge_Cuts ) )
1074 {
1075 if( !bFP->GetCourtyard( F_CrtYd ).IsEmpty() )
1076 reportPhysicalClearance( F_CrtYd );
1077
1078 if( !bFP->GetCourtyard( B_CrtYd ).IsEmpty() )
1079 reportPhysicalClearance( B_CrtYd );
1080 }
1081
1082 if( a->HasHole() || b->HasHole() )
1083 {
1084 PCB_LAYER_ID layer;
1085
1086 if( a->HasHole() && b->IsOnLayer( active ) )
1087 layer = active;
1088 else if( b->HasHole() && a->IsOnLayer( active ) )
1089 layer = active;
1090 else if( a->HasHole() )
1091 layer = b->GetLayer();
1092 else
1093 layer = a->GetLayer();
1094
1095 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
1096
1097 constraint = drcEngine.EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1098 clearance = constraint.m_Value.Min();
1099
1100 if( compileError )
1101 {
1102 reportCompileError( r );
1103 }
1105 {
1106 r->Report( "" );
1107 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
1108 }
1109 else
1110 {
1111 r->Report( "" );
1112 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
1113 m_frame->StringFromValue( clearance, true ) ) );
1114 }
1115 }
1116
1117 r->Flush();
1118
1119 m_inspectClearanceDialog->Raise();
1120 m_inspectClearanceDialog->Show( true );
1121 return 0;
1122}
1123
1124
1126{
1127#define EVAL_RULES( constraint, a, b, layer, r ) drcEngine.EvalRules( constraint, a, b, layer, r )
1128
1130 const PCB_SELECTION& selection = selTool->GetSelection();
1131
1132 if( selection.Size() != 1 )
1133 {
1134 m_frame->ShowInfoBarError( _( "Select an item for a constraints resolution report." ) );
1135 return 0;
1136 }
1137
1138 if( m_inspectConstraintsDialog == nullptr )
1139 {
1140 m_inspectConstraintsDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame );
1141 m_inspectConstraintsDialog->SetTitle( _( "Constraints Report" ) );
1142
1143 m_inspectConstraintsDialog->Connect( wxEVT_CLOSE_WINDOW,
1145 nullptr, this );
1146 }
1147
1148 m_inspectConstraintsDialog->DeleteAllPages();
1149
1150 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
1151 bool compileError = false;
1152 bool courtyardError = false;
1153 DRC_ENGINE drcEngine = makeDRCEngine( &compileError, &courtyardError );
1154 DRC_CONSTRAINT constraint;
1155
1156 WX_HTML_REPORT_BOX* r = nullptr;
1157
1158 if( item->Type() == PCB_TRACE_T )
1159 {
1160 r = m_inspectConstraintsDialog->AddPage( _( "Track Width" ) );
1161 reportHeader( _( "Track width resolution for:" ), item, r );
1162
1163 constraint = EVAL_RULES( TRACK_WIDTH_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1164
1165 if( compileError )
1166 reportCompileError( r );
1167
1168 r->Report( "" );
1169 r->Report( wxString::Format( _( "Width constraints: min %s; opt %s; max %s." ),
1170 reportMin( m_frame, constraint ),
1171 reportOpt( m_frame, constraint ),
1172 reportMax( m_frame, constraint ) ) );
1173
1174 r->Flush();
1175 }
1176
1177 if( item->Type() == PCB_VIA_T )
1178 {
1179 r = m_inspectConstraintsDialog->AddPage( _( "Via Diameter" ) );
1180 reportHeader( _( "Via diameter resolution for:" ), item, r );
1181
1182 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1183 constraint = EVAL_RULES( VIA_DIAMETER_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1184
1185 if( compileError )
1186 reportCompileError( r );
1187
1188 r->Report( "" );
1189 r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
1190 reportMin( m_frame, constraint ),
1191 reportOpt( m_frame, constraint ),
1192 reportMax( m_frame, constraint ) ) );
1193
1194 r->Flush();
1195
1196 r = m_inspectConstraintsDialog->AddPage( _( "Via Annular Width" ) );
1197 reportHeader( _( "Via annular width resolution for:" ), item, r );
1198
1199 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1200 constraint = EVAL_RULES( ANNULAR_WIDTH_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1201
1202 if( compileError )
1203 reportCompileError( r );
1204
1205 r->Report( "" );
1206 r->Report( wxString::Format( _( "Annular width constraints: min %s; opt %s; max %s." ),
1207 reportMin( m_frame, constraint ),
1208 reportOpt( m_frame, constraint ),
1209 reportMax( m_frame, constraint ) ) );
1210
1211 r->Flush();
1212 }
1213
1214 if( ( item->Type() == PCB_PAD_T && static_cast<PAD*>( item )->GetDrillSize().x > 0 )
1215 || item->Type() == PCB_VIA_T )
1216 {
1217 r = m_inspectConstraintsDialog->AddPage( _( "Hole Size" ) );
1218 reportHeader( _( "Hole diameter resolution for:" ), item, r );
1219
1220 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1221 constraint = EVAL_RULES( HOLE_SIZE_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1222
1223 if( compileError )
1224 reportCompileError( r );
1225
1226 r->Report( "" );
1227 r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
1228 reportMin( m_frame, constraint ),
1229 reportOpt( m_frame, constraint ),
1230 reportMax( m_frame, constraint ) ) );
1231
1232 r->Flush();
1233 }
1234
1235 if( item->Type() == PCB_TEXT_T
1236 || item->Type() == PCB_TEXTBOX_T
1237 || item->Type() == PCB_FP_TEXT_T )
1238 {
1239 r = m_inspectConstraintsDialog->AddPage( _( "Text Size" ) );
1240 reportHeader( _( "Text height resolution for:" ), item, r );
1241
1242 constraint = EVAL_RULES( TEXT_HEIGHT_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1243
1244 if( compileError )
1245 reportCompileError( r );
1246
1247 r->Report( "" );
1248 r->Report( wxString::Format( _( "Text height constraints: min %s; opt %s; max %s." ),
1249 reportMin( m_frame, constraint ),
1250 reportOpt( m_frame, constraint ),
1251 reportMax( m_frame, constraint ) ) );
1252
1253 r->Report( "" );
1254 r->Report( "" );
1255 r->Report( "" );
1256 reportHeader( _( "Text thickness resolution for:" ), item, r );
1257
1258 constraint = EVAL_RULES( TEXT_THICKNESS_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1259
1260 if( compileError )
1261 reportCompileError( r );
1262
1263 r->Report( "" );
1264 r->Report( wxString::Format( _( "Text thickness constraints: min %s; opt %s; max %s." ),
1265 reportMin( m_frame, constraint ),
1266 reportOpt( m_frame, constraint ),
1267 reportMax( m_frame, constraint ) ) );
1268
1269 r->Flush();
1270 }
1271
1272 r = m_inspectConstraintsDialog->AddPage( _( "Keepouts" ) );
1273 reportHeader( _( "Keepout resolution for:" ), item, r );
1274
1275 constraint = EVAL_RULES( DISALLOW_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1276
1277 if( compileError )
1278 reportCompileError( r );
1279
1280 if( courtyardError )
1281 {
1282 r->Report( "" );
1283 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1284 + wxT( " <a href='drc'>" ) + _( "Run DRC for a full analysis." ) + wxT( "</a>" ) );
1285 }
1286
1287 r->Report( "" );
1288
1289 if( constraint.m_DisallowFlags )
1290 r->Report( _( "Item <b>disallowed</b> at current location." ) );
1291 else
1292 r->Report( _( "Item allowed at current location." ) );
1293
1294 r->Flush();
1295
1296 r = m_inspectConstraintsDialog->AddPage( _( "Assertions" ) );
1297 reportHeader( _( "Assertions for:" ), item, r );
1298
1299 if( compileError )
1300 reportCompileError( r );
1301
1302 if( courtyardError )
1303 {
1304 r->Report( "" );
1305 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1306 + wxT( " <a href='drc'>" ) + _( "Run DRC for a full analysis." ) + wxT( "</a>" ) );
1307 }
1308
1309 drcEngine.ProcessAssertions( item, []( const DRC_CONSTRAINT* c ){}, r );
1310 r->Flush();
1311
1312 m_inspectConstraintsDialog->FinishInitialization();
1314 m_inspectConstraintsDialog->Show( true );
1315 return 0;
1316}
1317
1318
1320{
1321 BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
1322
1323 m_frame->m_probingSchToPcb = true; // recursion guard
1324 {
1326
1327 if( item )
1328 m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) item );
1329 }
1330 m_frame->m_probingSchToPcb = false;
1331
1332 bool request3DviewRedraw = frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh;
1333
1334 if( item && item->Type() != PCB_FOOTPRINT_T )
1335 request3DviewRedraw = false;
1336
1337 // Update 3D viewer highlighting
1338 if( request3DviewRedraw )
1339 m_frame->Update3DView( false, true );
1340
1341 return 0;
1342}
1343
1344
1345 bool BOARD_INSPECTION_TOOL::highlightNet( const VECTOR2D& aPosition, bool aUseSelection )
1346{
1347 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1350
1351 int net = -1;
1352 bool enableHighlight = false;
1353
1354 if( aUseSelection )
1355 {
1356 const PCB_SELECTION& selection = selectionTool->GetSelection();
1357 std::set<int> netcodes;
1358
1359 for( EDA_ITEM* item : selection )
1360 {
1361 if( BOARD_CONNECTED_ITEM* ci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1362 netcodes.insert( ci->GetNetCode() );
1363 }
1364
1365 enableHighlight = !netcodes.empty();
1366
1367 if( enableHighlight && netcodes.size() > 1 )
1368 {
1369 // If we are doing a multi-highlight, cross-probing back and other stuff is not
1370 // yet supported
1371 settings->SetHighlight( netcodes );
1373
1374 for( int multiNet : netcodes )
1375 board->SetHighLightNet( multiNet, true );
1376
1377 board->HighLightON();
1379 m_currentlyHighlighted = netcodes;
1380 return true;
1381 }
1382 else if( enableHighlight )
1383 {
1384 net = *netcodes.begin();
1385 }
1386 }
1387
1388 // If we didn't get a net to highlight from the selection, use the cursor
1389 if( net < 0 )
1390 {
1392 guide.SetIgnoreZoneFills( false );
1393
1394 PCB_LAYER_ID activeLayer = static_cast<PCB_LAYER_ID>( view()->GetTopLayer() );
1395 guide.SetPreferredLayer( activeLayer );
1396
1397 GENERAL_COLLECTOR collector;
1398 collector.Collect( board, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T }, aPosition,
1399 guide );
1400
1401 if( collector.GetCount() == 0 )
1402 collector.Collect( board, { PCB_ZONE_T, PCB_FP_ZONE_T }, aPosition, guide );
1403
1404 // Apply the active selection filter, except we want to allow picking locked items for
1405 // highlighting even if the user has disabled them for selection
1406 SELECTION_FILTER_OPTIONS& filter = selectionTool->GetFilter();
1407
1408 bool saved = filter.lockedItems;
1409 filter.lockedItems = true;
1410
1411 selectionTool->FilterCollectedItems( collector, true );
1412
1413 filter.lockedItems = saved;
1414
1415 // Clear the previous highlight
1416 //m_frame->SendMessageToEESCHEMA( nullptr );
1417
1418 bool highContrast = settings->GetHighContrast();
1419 PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
1420
1421 for( int i = collector.GetCount() - 1; i >= 0; i-- )
1422 {
1423 LSET itemLayers = collector[i]->GetLayerSet();
1424
1425 if( ( itemLayers & LSET::AllCuMask() ).none() ||
1426 ( highContrast && !itemLayers.Contains( contrastLayer ) ) )
1427 {
1428 collector.Remove( i );
1429 continue;
1430 }
1431 }
1432
1433 enableHighlight = ( collector.GetCount() > 0 );
1434
1435 // Obtain net code for the clicked item
1436 if( enableHighlight )
1437 {
1438 BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
1439
1440 if( targetItem->Type() == PCB_PAD_T )
1441 m_frame->SendCrossProbeItem( targetItem );
1442
1443 net = targetItem->GetNetCode();
1444 }
1445 }
1446
1447 const std::set<int>& netcodes = settings->GetHighlightNetCodes();
1448
1449 // Toggle highlight when the same net was picked
1450 if( netcodes.count( net ) )
1451 enableHighlight = !settings->IsHighlightEnabled();
1452
1453 if( enableHighlight != settings->IsHighlightEnabled() || !netcodes.count( net ) )
1454 {
1455 if( !netcodes.empty() )
1456 m_lastHighlighted = netcodes;
1457
1458 settings->SetHighlight( enableHighlight, net );
1459 m_toolMgr->GetView()->UpdateAllLayersColor();
1460 }
1461
1462 // Store the highlighted netcode in the current board (for dialogs for instance)
1463 if( enableHighlight && net >= 0 )
1464 {
1465 m_currentlyHighlighted = netcodes;
1466 board->SetHighLightNet( net );
1467 board->HighLightON();
1468
1469 NETINFO_ITEM* netinfo = board->FindNet( net );
1470
1471 if( netinfo )
1472 {
1473 std::vector<MSG_PANEL_ITEM> items;
1474 netinfo->GetMsgPanelInfo( m_frame, items );
1475 m_frame->SetMsgPanel( items );
1476 m_frame->SendCrossProbeNetName( netinfo->GetNetname() );
1477 }
1478 }
1479 else
1480 {
1481 m_currentlyHighlighted.clear();
1482 board->ResetNetHighLight();
1483 m_frame->SetMsgPanel( board );
1484 m_frame->SendCrossProbeNetName( "" );
1485 }
1486
1487 return true;
1488}
1489
1490
1492{
1493 int netcode = aEvent.Parameter<intptr_t>();
1495 const std::set<int>& highlighted = settings->GetHighlightNetCodes();
1496
1497 if( netcode > 0 )
1498 {
1499 m_lastHighlighted = highlighted;
1500 settings->SetHighlight( true, netcode );
1502 m_currentlyHighlighted.clear();
1503 m_currentlyHighlighted.insert( netcode );
1504 }
1505 else if( aEvent.IsAction( &PCB_ACTIONS::highlightNetSelection ) )
1506 {
1507 // Highlight selection (cursor position will be ignored)
1508 highlightNet( getViewControls()->GetMousePosition(), true );
1509 }
1510 else if( aEvent.IsAction( &PCB_ACTIONS::toggleLastNetHighlight ) )
1511 {
1512 std::set<int> temp = highlighted;
1513 settings->SetHighlight( m_lastHighlighted );
1516 m_lastHighlighted = temp;
1517 }
1518 else if( aEvent.IsAction( &PCB_ACTIONS::toggleNetHighlight ) )
1519 {
1520 bool turnOn = highlighted.empty() && !m_currentlyHighlighted.empty();
1521 settings->SetHighlight( m_currentlyHighlighted, turnOn );
1523 }
1524 else // Highlight the net belonging to the item under the cursor
1525 {
1526 highlightNet( getViewControls()->GetMousePosition(), false );
1527 }
1528
1529 return 0;
1530}
1531
1532
1534{
1535 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1537
1538 m_currentlyHighlighted.clear();
1539 m_lastHighlighted.clear();
1540
1542 settings->SetHighlight( false );
1546 return 0;
1547}
1548
1549
1551{
1553 BOARD* board = getModel<BOARD>();
1554
1555 // Deactivate other tools; particularly important if another PICKER is currently running
1556 Activate();
1557
1558 picker->SetCursor( KICURSOR::BULLSEYE );
1559
1560 picker->SetClickHandler(
1561 [this, board]( const VECTOR2D& pt ) -> bool
1562 {
1564
1567 PCB_SELECTION& selection = selectionTool->GetSelection();
1568
1569 if( selection.Empty() )
1570 {
1573 selection = selectionTool->GetSelection();
1574 }
1575
1576 if( selection.Empty() )
1577 {
1578 // Clear the previous local ratsnest if we click off all items
1579 for( FOOTPRINT* fp : board->Footprints() )
1580 {
1581 for( PAD* pad : fp->Pads() )
1582 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1583 }
1584 }
1585 else
1586 {
1587 for( EDA_ITEM* item : selection )
1588 {
1589 if( PAD* pad = dyn_cast<PAD*>( item) )
1590 {
1591 pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
1592 }
1593 else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
1594 {
1595 if( !fp->Pads().empty() )
1596 {
1597 bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
1598
1599 for( PAD* childPad : fp->Pads() )
1600 childPad->SetLocalRatsnestVisible( enable );
1601 }
1602 }
1603 }
1604 }
1605
1607
1608 return true;
1609 } );
1610
1611 picker->SetFinalizeHandler(
1612 [this, board]( int aCondition )
1613 {
1614 if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
1615 {
1616 for( FOOTPRINT* fp : board->Footprints() )
1617 {
1618 for( PAD* pad : fp->Pads() )
1619 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1620 }
1621 }
1622 } );
1623
1625
1626 return 0;
1627}
1628
1629
1631{
1633
1634 // If we have passed the simple move vector, we can update without recalculation
1635 if( aEvent.Parameter<VECTOR2I*>() )
1636 {
1637 delta = *aEvent.Parameter<VECTOR2I*>();
1638 delete aEvent.Parameter<VECTOR2I*>();
1639 }
1640 else
1641 {
1642 // We can delete the existing map to force a recalculation
1643 delete m_dynamicData;
1644 m_dynamicData = nullptr;
1645 }
1646
1647 auto selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1648 auto& selection = selectionTool->GetSelection();
1649 auto connectivity = getModel<BOARD>()->GetConnectivity();
1650
1651 if( selection.Empty() )
1652 {
1653 connectivity->ClearLocalRatsnest();
1654 delete m_dynamicData;
1655 m_dynamicData = nullptr;
1656 }
1657 else
1658 {
1660 }
1661
1662 return 0;
1663}
1664
1665
1667{
1668 getModel<BOARD>()->GetConnectivity()->ClearLocalRatsnest();
1669 delete m_dynamicData;
1670 m_dynamicData = nullptr;
1671
1672 return 0;
1673}
1674
1675
1677{
1679 SELECTION& selection = selectionTool->GetSelection();
1680 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board()->GetConnectivity();
1681 std::vector<BOARD_ITEM*> items;
1682 std::deque<EDA_ITEM*> queued_items( selection.begin(), selection.end() );
1683
1684 for( std::size_t i = 0; i < queued_items.size(); ++i )
1685 {
1686 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( queued_items[i] );
1687
1688 if( item->Type() == PCB_FOOTPRINT_T )
1689 {
1690 for( PAD* pad : static_cast<FOOTPRINT*>( item )->Pads() )
1691 {
1692 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1693 items.push_back( pad );
1694 }
1695 }
1696 else if( item->Type() == PCB_GROUP_T )
1697 {
1698 PCB_GROUP *group = static_cast<PCB_GROUP*>( item );
1699 group->RunOnDescendants( [ &queued_items ]( BOARD_ITEM *aItem )
1700 {
1701 queued_items.push_back( aItem );
1702 } );
1703 }
1704 else if( BOARD_CONNECTED_ITEM* boardItem = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
1705 {
1706 if( boardItem->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1707 items.push_back( boardItem );
1708 }
1709 }
1710
1711 if( items.empty() || std::none_of( items.begin(), items.end(),
1712 []( const BOARD_ITEM* aItem )
1713 {
1714 return( aItem->Type() == PCB_TRACE_T
1715 || aItem->Type() == PCB_PAD_T
1716 || aItem->Type() == PCB_ARC_T
1717 || aItem->Type() == PCB_ZONE_T
1718 || aItem->Type() == PCB_FOOTPRINT_T
1719 || aItem->Type() == PCB_VIA_T );
1720 } ) )
1721 {
1722 return;
1723 }
1724
1725 if( !m_dynamicData )
1726 {
1727 m_dynamicData = new CONNECTIVITY_DATA( items, true );
1728 connectivity->BlockRatsnestItems( items );
1729 }
1730 else
1731 {
1732 m_dynamicData->Move( aDelta );
1733 }
1734
1735 connectivity->ComputeLocalRatsnest( items, m_dynamicData );
1736}
1737
1738
1740{
1741 if( m_listNetsDialog == nullptr )
1742 {
1744 std::make_unique<DIALOG_NET_INSPECTOR>( m_frame, m_listNetsDialogSettings );
1745
1746 m_listNetsDialog->Connect( wxEVT_CLOSE_WINDOW,
1747 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr,
1748 this );
1749
1750 m_listNetsDialog->Connect( wxEVT_BUTTON,
1751 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr,
1752 this );
1753 }
1754
1755 m_listNetsDialog->Raise();
1756 m_listNetsDialog->Show( true );
1757 return 0;
1758}
1759
1760
1762{
1764
1765 m_listNetsDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1766 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
1767
1768 m_listNetsDialog->Disconnect( wxEVT_BUTTON,
1769 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
1770
1771 m_listNetsDialog->Destroy();
1772 m_listNetsDialog.release();
1773}
1774
1775
1777{
1778 m_inspectClearanceDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1780 nullptr, this );
1781
1782 m_inspectClearanceDialog->Destroy();
1783 m_inspectClearanceDialog.release();
1784}
1785
1786
1788{
1789 m_inspectConstraintsDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1791 nullptr, this );
1792
1793 m_inspectConstraintsDialog->Destroy();
1795}
1796
1797
1799{
1800 doHideRatsnestNet( aEvent.Parameter<intptr_t>(), true );
1801 return 0;
1802}
1803
1804
1806{
1807 doHideRatsnestNet( aEvent.Parameter<intptr_t>(), false );
1808 return 0;
1809}
1810
1811
1812void BOARD_INSPECTION_TOOL::doHideRatsnestNet( int aNetCode, bool aHide )
1813{
1816
1818 SELECTION& selection = selectionTool->GetSelection();
1819
1820 if( aNetCode <= 0 && !selection.Empty() )
1821 {
1822 for( EDA_ITEM* item : selection )
1823 {
1824 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1825 {
1826 if( bci->GetNetCode() > 0 )
1827 doHideRatsnestNet( bci->GetNetCode(), aHide );
1828 }
1829 }
1830
1831 return;
1832 }
1833
1834 if( aHide )
1835 rs->GetHiddenNets().insert( aNetCode );
1836 else
1837 rs->GetHiddenNets().erase( aNetCode );
1838
1841
1842 m_frame->GetAppearancePanel()->OnNetVisibilityChanged( aNetCode, !aHide );
1843}
1844
1845
1847{
1851
1856
1863
1866}
@ show_ratsnest
#define EVAL_RULES(constraint, a, b, layer, r)
wxString reportMax(PCB_BASE_FRAME *aFrame, DRC_CONSTRAINT &aConstraint)
bool isNPTHPad(BOARD_ITEM *aItem)
wxString reportMin(PCB_BASE_FRAME *aFrame, DRC_CONSTRAINT &aConstraint)
wxString reportOpt(PCB_BASE_FRAME *aFrame, DRC_CONSTRAINT &aConstraint)
static TOOL_ACTION pickerTool
Definition: actions.h:159
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:87
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
void OnNetVisibilityChanged(int aNetCode, bool aVisibility)
Notifies the panel when a net has been hidden or shown via the external tool.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void InspectDRCError(const std::shared_ptr< RC_ITEM > &aDRCItem)
Show the clearance resolution for two selected items.
int HighlightNet(const TOOL_EVENT &aEvent)
Clear all board highlights.
void calculateSelectionRatsnest(const VECTOR2I &aDelta)
< Recalculate dynamic ratsnest for the current selection.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int ShowBoardStatistics(const TOOL_EVENT &aEvent)
Show dialog with board statistics.
DIALOG_NET_INSPECTOR::SETTINGS m_listNetsDialogSettings
std::unique_ptr< DIALOG_CONSTRAINTS_REPORTER > m_inspectConstraintsDialog
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...
int ListNets(const TOOL_EVENT &aEvent)
Hide the ratsnest for a given net.
std::unique_ptr< DIALOG_NET_INSPECTOR > m_listNetsDialog
int LocalRatsnestTool(const TOOL_EVENT &aEvent)
std::set< int > m_lastHighlighted
bool Init() override
Init() is called once upon a registration of the tool.
int ShowNetInRatsnest(const TOOL_EVENT &aEvent)
void reportCompileError(REPORTER *r)
int ClearHighlight(const TOOL_EVENT &aEvent)
Perform the appropriate action in response to an Eeschema cross-probe.
int HideNetInRatsnest(const TOOL_EVENT &aEvent)
Show the ratsnest for a given net.
void onListNetsDialogClosed(wxCommandEvent &aEvent)
int InspectConstraints(const TOOL_EVENT &aEvent)
void doHideRatsnestNet(int aNetCode, bool aHide)
Bind handlers to corresponding TOOL_ACTIONs.
wxString getItemDescription(BOARD_ITEM *aItem)
void onInspectConstraintsDialogClosed(wxCommandEvent &aEvent)
CONNECTIVITY_DATA * m_dynamicData
void reportHeader(const wxString &aTitle, BOARD_ITEM *a, REPORTER *r)
DRC_ENGINE makeDRCEngine(bool *aCompileError, bool *aCourtyardError=nullptr)
void onInspectClearanceDialogClosed(wxCommandEvent &aEvent)
int InspectClearance(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
std::unique_ptr< DIALOG_CONSTRAINTS_REPORTER > m_inspectClearanceDialog
std::set< int > m_currentlyHighlighted
int UpdateLocalRatsnest(const TOOL_EVENT &aEvent)
Hide ratsnest for selected items. Called when there are no items selected.
int HideLocalRatsnest(const TOOL_EVENT &aEvent)
Show local ratsnest of a component.
int HighlightItem(const TOOL_EVENT &aEvent)
Update ratsnest for selected items.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:127
virtual bool IsTented() const
Definition: board_item.h:145
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:197
virtual bool IsOnLayer(PCB_LAYER_ID aLayer, bool aIncludeCourtyards=false) const
Test to see if this object is on the given layer.
Definition: board_item.h:257
virtual bool IsOnCopperLayer() const
Definition: board_item.h:135
virtual bool HasHole() const
Definition: board_item.h:140
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
ZONES & Zones()
Definition: board.h:317
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2092
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1019
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2083
FOOTPRINTS & Footprints()
Definition: board.h:311
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:474
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2105
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:430
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
void Move(const VECTOR2I &aDelta)
Moves the connectivity list anchors.
Dialog to show common board info.
wxString GetName() const
Definition: drc_rule.h:149
int m_DisallowFlags
Definition: drc_rule.h:173
ZONE_CONNECTION m_ZoneConnection
Definition: drc_rule.h:174
MINOPTMAX< int > m_Value
Definition: drc_rule.h:172
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:83
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
void ProcessAssertions(const BOARD_ITEM *a, std::function< void(const DRC_CONSTRAINT *)> aFailureHandler, REPORTER *aReporter=nullptr)
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
Definition: drc_engine.cpp:669
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
Definition: drc_engine.cpp:514
DRC_CONSTRAINT EvalZoneConnection(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
Definition: drc_engine.cpp:612
static int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
Check if the given net is a diff pair, returning its polarity and complement if so.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
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...
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const
Return a user-visible description string of this item.
Definition: eda_item.cpp:108
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:142
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:2362
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:2375
PADS & Pads()
Definition: footprint.h:170
void BuildCourtyardCaches(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:2245
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
Definition: footprint.cpp:2233
FP_ZONES & Zones()
Definition: footprint.h:176
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:326
void SetIgnoreZoneFills(bool ignore)
Definition: collectors.h:480
void SetPreferredLayer(PCB_LAYER_ID aLayer)
Definition: collectors.h:391
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:204
void Collect(BOARD_ITEM *aItem, const std::vector< KICAD_T > &aScanList, const VECTOR2I &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:596
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:72
std::set< int > & GetHiddenNets()
Definition: pcb_painter.h:118
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > & GetHighlightNetCodes() const
Return the netcode of currently highlighted net.
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
bool GetHighContrast() const
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:761
virtual int GetTopLayer() const
Definition: view.cpp:816
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:617
Definition: kiid.h:48
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
bool Contains(PCB_LAYER_ID aLayer)
See if the layer set contains a PCB layer.
Definition: layer_ids.h:602
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
T Min() const
Definition: minoptmax.h:33
bool HasMax() const
Definition: minoptmax.h:38
bool HasMin() const
Definition: minoptmax.h:37
T Max() const
Definition: minoptmax.h:34
T Opt() const
Definition: minoptmax.h:35
bool HasOpt() const
Definition: minoptmax.h:39
const wxString GetName() const
Definition: netclass.h:65
Handle the data for a net.
Definition: netinfo.h:67
const wxString & GetNetname() const
Definition: netinfo.h:125
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.
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
Definition: pad.h:60
const VECTOR2I & GetDrillSize() const
Definition: pad.h:268
PAD_ATTRIB GetAttribute() const
Definition: pad.h:401
DISPLAY_OPTIONS m_Display
static TOOL_ACTION highlightItem
Definition: pcb_actions.h:501
static TOOL_ACTION listNets
Definition: pcb_actions.h:383
static TOOL_ACTION toggleNetHighlight
Definition: pcb_actions.h:499
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:56
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:497
static TOOL_ACTION hideNetInRatsnest
Definition: pcb_actions.h:504
static TOOL_ACTION hideLocalRatsnest
Definition: pcb_actions.h:507
static TOOL_ACTION showNetInRatsnest
Definition: pcb_actions.h:505
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION toggleLastNetHighlight
Definition: pcb_actions.h:498
static TOOL_ACTION inspectConstraints
Definition: pcb_actions.h:493
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:496
static TOOL_ACTION inspectClearance
Definition: pcb_actions.h:492
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:508
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:62
static TOOL_ACTION highlightNetSelection
Definition: pcb_actions.h:500
static TOOL_ACTION boardStatistics
Definition: pcb_actions.h:488
static TOOL_ACTION localRatsnestTool
Definition: pcb_actions.h:506
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
APPEARANCE_CONTROLS * GetAppearancePanel()
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCBNEW_SETTINGS * GetPcbNewSettings() const
virtual PCB_LAYER_ID GetActiveLayer() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
void SendCrossProbeItem(BOARD_ITEM *aSyncItem)
Send a message to the schematic editor so that it may move its cursor to an item with the same refere...
void SendCrossProbeNetName(const wxString &aNetName)
Send a net name to Eeschema for highlighting.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:68
Generic tool for picking an item.
The selection tool: currently supports:
void FilterCollectedItems(GENERAL_COLLECTOR &aCollector, bool aMultiSelect)
Apply the SELECTION_FITLER_OPTIONS to the collector.
SELECTION_FILTER_OPTIONS & GetFilter()
Set up handlers for various events.
PCB_SELECTION & GetSelection()
KIGFX::PCB_VIEW * view() const
PCB_BASE_EDIT_FRAME * frame() const
BOARD * board() const
PCBNEW_SETTINGS::DISPLAY_OPTIONS & displayOptions() const
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:71
void SetCursor(KICURSOR aCursor)
Definition: picker_tool.h:62
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:102
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:75
ITER end()
Definition: selection.h:74
ITER begin()
Definition: selection.h:73
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:109
bool IsEmpty() const
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:156
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:442
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:81
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).
TOOL_MENU & GetToolMenu()
void Activate()
Run the tool.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
EDA_ITEM * GetModel() const
Definition: tool_manager.h:292
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:285
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void RegisterSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:50
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Converts aValue in internal units into a united string.
A slimmed down version of WX_HTML_REPORT_PANEL.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
void Flush()
Build the HTML messages page.
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
virtual bool IsOnLayer(PCB_LAYER_ID, bool aIncludeCourtyards=false) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:323
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: zone.cpp:476
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:122
@ DRCE_HOLE_CLEARANCE
Definition: drc_item.h:53
@ DRCE_VIA_DIAMETER
Definition: drc_item.h:58
@ DRCE_TRACK_WIDTH
Definition: drc_item.h:54
@ DRCE_DRILL_OUT_OF_RANGE
Definition: drc_item.h:57
@ DRCE_EDGE_CLEARANCE
Definition: drc_item.h:45
@ DRCE_CLEARANCE
Definition: drc_item.h:43
@ DRCE_DRILLED_HOLES_TOO_CLOSE
Definition: drc_item.h:51
@ DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
Definition: drc_item.h:99
@ DRCE_MICROVIA_DRILL_OUT_OF_RANGE
Definition: drc_item.h:60
@ DRCE_TEXT_HEIGHT
Definition: drc_item.h:91
@ DRCE_TEXT_THICKNESS
Definition: drc_item.h:92
@ DRCE_CONNECTION_WIDTH
Definition: drc_item.h:56
@ DRCE_ANNULAR_WIDTH
Definition: drc_item.h:55
@ ANNULAR_WIDTH_CONSTRAINT
Definition: drc_rule.h:57
@ COURTYARD_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:52
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:63
@ DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:67
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:66
@ DISALLOW_CONSTRAINT
Definition: drc_rule.h:62
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:56
@ SILK_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:53
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:50
@ MIN_RESOLVED_SPOKES_CONSTRAINT
Definition: drc_rule.h:61
@ TEXT_THICKNESS_CONSTRAINT
Definition: drc_rule.h:55
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:71
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:47
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
Definition: drc_rule.h:60
@ CONNECTION_WIDTH_CONSTRAINT
Definition: drc_rule.h:73
@ THERMAL_RELIEF_GAP_CONSTRAINT
Definition: drc_rule.h:59
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:51
@ TEXT_HEIGHT_CONSTRAINT
Definition: drc_rule.h:54
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:70
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:49
#define _(s)
#define MALFORMED_COURTYARDS
static std::vector< KICAD_T > connectedTypes
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition: layer_ids.h:901
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ F_CrtYd
Definition: layer_ids.h:117
@ Edge_Cuts
Definition: layer_ids.h:113
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ Margin
Definition: layer_ids.h:114
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
Definition: definitions.h:50
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
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
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:119
This file contains data structures that are saved in the project file or project local settings file ...
constexpr int delta
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:115
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:112
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_FP_ZONE_T
class ZONE, managed by a footprint
Definition: typeinfo.h:100
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:103
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101
@ THERMAL
Use thermal relief for pads.
@ NONE
Pads are not covered.