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->GetSelectMenuText( 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 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
776 m_frame->StringFromValue( clearance, true ) ) );
777 }
778
779 r->Flush();
780 }
781
782 if( ac && bc )
783 {
784 NETINFO_ITEM* refNet = ac->GetNet();
785 wxString coupledNet;
786 wxString dummy;
787
788 if( DRC_ENGINE::MatchDpSuffix( refNet->GetNetname(), coupledNet, dummy )
789 && bc->GetNetname() == coupledNet )
790 {
791 r = m_inspectClearanceDialog->AddPage( _( "Diff Pair" ) );
792 reportHeader( _( "Diff pair gap resolution for:" ), ac, bc, active, r );
793
794 constraint = drcEngine.EvalRules( DIFF_PAIR_GAP_CONSTRAINT, ac, bc, active, r );
795
796 r->Report( "" );
797 r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ),
798 reportMin( m_frame, constraint ),
799 reportOpt( m_frame, constraint ),
800 reportMax( m_frame, constraint ) ) );
801
802 r->Report( "" );
803 r->Report( "" );
804 r->Report( "" );
805 reportHeader( _( "Diff pair max uncoupled length resolution for:" ), ac, bc, active, r );
806
808 {
809 r->Report( "" );
810 r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
811 }
812 else
813 {
814 constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, ac, bc,
815 active, r );
816
817 r->Report( "" );
818 r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
819 reportMax( m_frame, constraint ) ) );
820 }
821 r->Flush();
822 }
823 }
824
825 auto isOnCorrespondingLayer=
826 [&]( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, wxString* aWarning )
827 {
828 if( aItem->IsOnLayer( aLayer ) )
829 return true;
830
831 PCB_LAYER_ID correspondingMask = IsFrontLayer( aLayer ) ? F_Mask : B_Mask;
832 PCB_LAYER_ID correspondingCopper = IsFrontLayer( aLayer ) ? F_Cu : B_Cu;
833
834 if( aItem->IsOnLayer( aLayer ) )
835 return true;
836
837 if( aItem->IsOnLayer( correspondingMask ) )
838 return true;
839
840 if( aItem->IsTented() && aItem->IsOnLayer( correspondingCopper ) )
841 {
842 *aWarning = wxString::Format( _( "Note: %s is tented; clearance will only be "
843 "applied to holes." ),
844 getItemDescription( aItem ) );
845 return true;
846 }
847
848 return false;
849 };
850
851 for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
852 {
853 wxString warning;
854
855 if( ( a->IsOnLayer( layer ) && isOnCorrespondingLayer( b, layer, &warning ) )
856 || ( b->IsOnLayer( layer ) && isOnCorrespondingLayer( a, layer, &warning ) ) )
857 {
858 r = m_inspectClearanceDialog->AddPage( m_frame->GetBoard()->GetLayerName( layer ) );
859 reportHeader( _( "Silkscreen clearance resolution for:" ), a, b, layer, r );
860
861 constraint = drcEngine.EvalRules( SILK_CLEARANCE_CONSTRAINT, a, b, layer, r );
862 clearance = constraint.m_Value.Min();
863
864 if( compileError )
866
867 r->Report( "" );
868
869 if( !warning.IsEmpty() )
870 r->Report( warning );
871
872 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
873 m_frame->StringFromValue( clearance, true ) ) );
874
875 r->Flush();
876 }
877 }
878
879 for( PCB_LAYER_ID layer : { F_CrtYd, B_CrtYd } )
880 {
881 bool aCourtyard = aFP && !aFP->GetCourtyard( layer ).IsEmpty();
882 bool bCourtyard = bFP && !bFP->GetCourtyard( layer ).IsEmpty();
883
884 if( aCourtyard && bCourtyard )
885 {
886 r = m_inspectClearanceDialog->AddPage( m_frame->GetBoard()->GetLayerName( layer ) );
887 reportHeader( _( "Courtyard clearance resolution for:" ), a, b, layer, r );
888
889 constraint = drcEngine.EvalRules( COURTYARD_CLEARANCE_CONSTRAINT, a, b, layer, r );
890 clearance = constraint.m_Value.Min();
891
892 if( compileError )
894
895 r->Report( "" );
896 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
897 m_frame->StringFromValue( clearance, true ) ) );
898
899 r->Flush();
900 }
901 }
902
903 if( a->HasHole() || b->HasHole() )
904 {
906 bool pageAdded = false;
907
908 if( a->HasHole() && b->IsOnLayer( active ) && IsCopperLayer( active ) )
909 layer = active;
910 else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
911 layer = active;
912 else if( a->HasHole() && b->IsOnCopperLayer() )
913 layer = b->GetLayer();
914 else if( b->HasHole() && b->IsOnCopperLayer() )
915 layer = a->GetLayer();
916
917 if( layer >= 0 )
918 {
919 if( !pageAdded )
920 {
921 r = m_inspectClearanceDialog->AddPage( _( "Hole" ) );
922 pageAdded = true;
923 }
924 else
925 {
926 r->Report( "" );
927 r->Report( "" );
928 r->Report( "" );
929 }
930
931 reportHeader( _( "Hole clearance resolution for:" ), a, b, layer, r );
932
933 constraint = drcEngine.EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
934 clearance = constraint.m_Value.Min();
935
936 if( compileError )
938
939 r->Report( "" );
940 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
941 m_frame->StringFromValue( clearance, true ) ) );
942
943 r->Flush();
944 }
945
946 if( a->HasHole() && b->HasHole() )
947 {
948 if( !pageAdded )
949 {
950 r = m_inspectClearanceDialog->AddPage( _( "Hole" ) );
951 pageAdded = true;
952 }
953 else
954 {
955 r->Report( "" );
956 r->Report( "" );
957 r->Report( "" );
958 }
959
960 reportHeader( _( "Hole to hole clearance resolution for:" ), a, b, r );
961
962 constraint = drcEngine.EvalRules( HOLE_TO_HOLE_CONSTRAINT, a, b, UNDEFINED_LAYER, r );
963 clearance = constraint.m_Value.Min();
964
965 if( compileError )
967
968 r->Report( "" );
969 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
970 m_frame->StringFromValue( clearance, true ) ) );
971
972 r->Flush();
973 }
974 }
975
976 for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
977 {
979
980 if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
981 {
982 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
983 layer = active;
984 else if( IsCopperLayer( b->GetLayer() ) )
985 layer = b->GetLayer();
986 }
987 else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
988 {
989 if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
990 layer = active;
991 else if( IsCopperLayer( a->GetLayer() ) )
992 layer = a->GetLayer();
993 }
994
995 if( layer >= 0 )
996 {
997 wxString layerName = m_frame->GetBoard()->GetLayerName( edgeLayer );
998 r = m_inspectClearanceDialog->AddPage( layerName + wxS( " " ) + _( "Clearance" ) );
999 reportHeader( _( "Edge clearance resolution for:" ), a, b, layer, r );
1000
1001 constraint = drcEngine.EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1002 clearance = constraint.m_Value.Min();
1003
1004 if( compileError )
1006
1007 r->Report( "" );
1008 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
1009 m_frame->StringFromValue( clearance, true ) ) );
1010
1011 r->Flush();
1012 }
1013 }
1014
1015 r = m_inspectClearanceDialog->AddPage( _( "Physical Clearances" ) );
1016
1017 auto reportPhysicalClearance =
1018 [&]( PCB_LAYER_ID aLayer )
1019 {
1020 reportHeader( _( "Physical clearance resolution for:" ), a, b, aLayer, r );
1021
1022 constraint = drcEngine.EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, aLayer, r );
1023 clearance = constraint.m_Value.Min();
1024
1025 if( compileError )
1026 {
1028 }
1030 {
1031 r->Report( "" );
1032 r->Report( _( "No 'physical_clearance' constraints defined." ) );
1033 }
1034 else
1035 {
1036 r->Report( "" );
1037 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
1038 m_frame->StringFromValue( clearance, true ) ) );
1039 }
1040
1041 r->Report( "" );
1042 r->Report( "" );
1043 r->Report( "" );
1044 };
1045
1046 if( layerIntersection.any() )
1047 {
1048 PCB_LAYER_ID layer = active;
1049
1050 if( !layerIntersection.test( layer ) )
1051 layer = layerIntersection.Seq().front();
1052
1053 reportPhysicalClearance( layer );
1054 }
1055
1056 if( aFP && b->IsOnLayer( Edge_Cuts ) )
1057 {
1058 if( !aFP->GetCourtyard( F_CrtYd ).IsEmpty() )
1059 reportPhysicalClearance( F_CrtYd );
1060
1061 if( !aFP->GetCourtyard( B_CrtYd ).IsEmpty() )
1062 reportPhysicalClearance( B_CrtYd );
1063 }
1064 else if( bFP && a->IsOnLayer( Edge_Cuts ) )
1065 {
1066 if( !bFP->GetCourtyard( F_CrtYd ).IsEmpty() )
1067 reportPhysicalClearance( F_CrtYd );
1068
1069 if( !bFP->GetCourtyard( B_CrtYd ).IsEmpty() )
1070 reportPhysicalClearance( B_CrtYd );
1071 }
1072
1073 if( a->HasHole() || b->HasHole() )
1074 {
1075 PCB_LAYER_ID layer;
1076
1077 if( a->HasHole() && b->IsOnLayer( active ) )
1078 layer = active;
1079 else if( b->HasHole() && a->IsOnLayer( active ) )
1080 layer = active;
1081 else if( a->HasHole() )
1082 layer = b->GetLayer();
1083 else
1084 layer = a->GetLayer();
1085
1086 reportHeader( _( "Physical hole clearance resolution for:" ), a, b, layer, r );
1087
1088 constraint = drcEngine.EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
1089 clearance = constraint.m_Value.Min();
1090
1091 if( compileError )
1092 {
1094 }
1096 {
1097 r->Report( "" );
1098 r->Report( _( "No 'physical_hole_clearance' constraints defined." ) );
1099 }
1100 else
1101 {
1102 r->Report( "" );
1103 r->Report( wxString::Format( _( "Resolved clearance: %s." ),
1104 m_frame->StringFromValue( clearance, true ) ) );
1105 }
1106 }
1107
1108 r->Flush();
1109
1110 m_inspectClearanceDialog->Raise();
1111 m_inspectClearanceDialog->Show( true );
1112 return 0;
1113}
1114
1115
1117{
1118#define EVAL_RULES( constraint, a, b, layer, r ) drcEngine.EvalRules( constraint, a, b, layer, r )
1119
1121 const PCB_SELECTION& selection = selTool->GetSelection();
1122
1123 if( selection.Size() != 1 )
1124 {
1125 m_frame->ShowInfoBarError( _( "Select an item for a constraints resolution report." ) );
1126 return 0;
1127 }
1128
1129 if( m_inspectConstraintsDialog == nullptr )
1130 {
1131 m_inspectConstraintsDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame );
1132 m_inspectConstraintsDialog->SetTitle( _( "Constraints Report" ) );
1133
1134 m_inspectConstraintsDialog->Connect( wxEVT_CLOSE_WINDOW,
1136 nullptr, this );
1137 }
1138
1139 m_inspectConstraintsDialog->DeleteAllPages();
1140
1141 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
1142 bool compileError = false;
1143 bool courtyardError = false;
1144 DRC_ENGINE drcEngine = makeDRCEngine( &compileError, &courtyardError );
1145 DRC_CONSTRAINT constraint;
1146
1147 WX_HTML_REPORT_BOX* r = nullptr;
1148
1149 if( item->Type() == PCB_TRACE_T )
1150 {
1151 r = m_inspectConstraintsDialog->AddPage( _( "Track Width" ) );
1152 reportHeader( _( "Track width resolution for:" ), item, r );
1153
1154 constraint = EVAL_RULES( TRACK_WIDTH_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1155
1156 if( compileError )
1158
1159 r->Report( "" );
1160 r->Report( wxString::Format( _( "Width constraints: min %s; opt %s; max %s." ),
1161 reportMin( m_frame, constraint ),
1162 reportOpt( m_frame, constraint ),
1163 reportMax( m_frame, constraint ) ) );
1164
1165 r->Flush();
1166 }
1167
1168 if( item->Type() == PCB_VIA_T )
1169 {
1170 r = m_inspectConstraintsDialog->AddPage( _( "Via Diameter" ) );
1171 reportHeader( _( "Via diameter resolution for:" ), item, r );
1172
1173 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1174 constraint = EVAL_RULES( VIA_DIAMETER_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1175
1176 if( compileError )
1178
1179 r->Report( "" );
1180 r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
1181 reportMin( m_frame, constraint ),
1182 reportOpt( m_frame, constraint ),
1183 reportMax( m_frame, constraint ) ) );
1184
1185 r->Flush();
1186
1187 r = m_inspectConstraintsDialog->AddPage( _( "Via Annular Width" ) );
1188 reportHeader( _( "Via annular width resolution for:" ), item, r );
1189
1190 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1191 constraint = EVAL_RULES( ANNULAR_WIDTH_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1192
1193 if( compileError )
1195
1196 r->Report( "" );
1197 r->Report( wxString::Format( _( "Annular width constraints: min %s; opt %s; max %s." ),
1198 reportMin( m_frame, constraint ),
1199 reportOpt( m_frame, constraint ),
1200 reportMax( m_frame, constraint ) ) );
1201
1202 r->Flush();
1203 }
1204
1205 if( ( item->Type() == PCB_PAD_T && static_cast<PAD*>( item )->GetDrillSize().x > 0 )
1206 || item->Type() == PCB_VIA_T )
1207 {
1208 r = m_inspectConstraintsDialog->AddPage( _( "Hole Size" ) );
1209 reportHeader( _( "Hole diameter resolution for:" ), item, r );
1210
1211 // PADSTACKS TODO: once we have padstacks we'll need to run this per-layer....
1212 constraint = EVAL_RULES( HOLE_SIZE_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1213
1214 if( compileError )
1216
1217 r->Report( "" );
1218 r->Report( wxString::Format( _( "Diameter constraints: min %s; opt %s; max %s." ),
1219 reportMin( m_frame, constraint ),
1220 reportOpt( m_frame, constraint ),
1221 reportMax( m_frame, constraint ) ) );
1222
1223 r->Flush();
1224 }
1225
1226 if( item->Type() == PCB_TEXT_T
1227 || item->Type() == PCB_TEXTBOX_T
1228 || item->Type() == PCB_FP_TEXT_T )
1229 {
1230 r = m_inspectConstraintsDialog->AddPage( _( "Text Size" ) );
1231 reportHeader( _( "Text height resolution for:" ), item, r );
1232
1233 constraint = EVAL_RULES( TEXT_HEIGHT_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1234
1235 if( compileError )
1237
1238 r->Report( "" );
1239 r->Report( wxString::Format( _( "Text height constraints: min %s; opt %s; max %s." ),
1240 reportMin( m_frame, constraint ),
1241 reportOpt( m_frame, constraint ),
1242 reportMax( m_frame, constraint ) ) );
1243
1244 r->Report( "" );
1245 r->Report( "" );
1246 r->Report( "" );
1247 reportHeader( _( "Text thickness resolution for:" ), item, r );
1248
1249 constraint = EVAL_RULES( TEXT_THICKNESS_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
1250
1251 if( compileError )
1253
1254 r->Report( "" );
1255 r->Report( wxString::Format( _( "Text thickness constraints: min %s; opt %s; max %s." ),
1256 reportMin( m_frame, constraint ),
1257 reportOpt( m_frame, constraint ),
1258 reportMax( m_frame, constraint ) ) );
1259
1260 r->Flush();
1261 }
1262
1263 r = m_inspectConstraintsDialog->AddPage( _( "Keepouts" ) );
1264 reportHeader( _( "Keepout resolution for:" ), item, r );
1265
1266 constraint = EVAL_RULES( DISALLOW_CONSTRAINT, item, nullptr, item->GetLayer(), r );
1267
1268 if( compileError )
1270
1271 if( courtyardError )
1272 {
1273 r->Report( "" );
1274 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1275 + wxT( " <a href='drc'>" ) + _( "Run DRC for a full analysis." ) + wxT( "</a>" ) );
1276 }
1277
1278 r->Report( "" );
1279
1280 if( constraint.m_DisallowFlags )
1281 r->Report( _( "Item <b>disallowed</b> at current location." ) );
1282 else
1283 r->Report( _( "Item allowed at current location." ) );
1284
1285 r->Flush();
1286
1287 r = m_inspectConstraintsDialog->AddPage( _( "Assertions" ) );
1288 reportHeader( _( "Assertions for:" ), item, r );
1289
1290 if( compileError )
1292
1293 if( courtyardError )
1294 {
1295 r->Report( "" );
1296 r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." )
1297 + wxT( " <a href='drc'>" ) + _( "Run DRC for a full analysis." ) + wxT( "</a>" ) );
1298 }
1299
1300 drcEngine.ProcessAssertions( item, []( const DRC_CONSTRAINT* c ){}, r );
1301 r->Flush();
1302
1303 m_inspectConstraintsDialog->FinishInitialization();
1305 m_inspectConstraintsDialog->Show( true );
1306 return 0;
1307}
1308
1309
1311{
1312 BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
1313
1314 m_frame->m_probingSchToPcb = true; // recursion guard
1315 {
1317
1318 if( item )
1319 m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) item );
1320 }
1321 m_frame->m_probingSchToPcb = false;
1322
1323 bool request3DviewRedraw = frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh;
1324
1325 if( item && item->Type() != PCB_FOOTPRINT_T )
1326 request3DviewRedraw = false;
1327
1328 // Update 3D viewer highlighting
1329 if( request3DviewRedraw )
1330 m_frame->Update3DView( false, true );
1331
1332 return 0;
1333}
1334
1335
1336 bool BOARD_INSPECTION_TOOL::highlightNet( const VECTOR2D& aPosition, bool aUseSelection )
1337{
1338 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1341
1342 int net = -1;
1343 bool enableHighlight = false;
1344
1345 if( aUseSelection )
1346 {
1347 const PCB_SELECTION& selection = selectionTool->GetSelection();
1348 std::set<int> netcodes;
1349
1350 for( EDA_ITEM* item : selection )
1351 {
1352 if( BOARD_CONNECTED_ITEM* ci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1353 netcodes.insert( ci->GetNetCode() );
1354 }
1355
1356 enableHighlight = !netcodes.empty();
1357
1358 if( enableHighlight && netcodes.size() > 1 )
1359 {
1360 // If we are doing a multi-highlight, cross-probing back and other stuff is not
1361 // yet supported
1362 settings->SetHighlight( netcodes );
1364
1365 for( int multiNet : netcodes )
1366 board->SetHighLightNet( multiNet, true );
1367
1368 board->HighLightON();
1370 m_currentlyHighlighted = netcodes;
1371 return true;
1372 }
1373 else if( enableHighlight )
1374 {
1375 net = *netcodes.begin();
1376 }
1377 }
1378
1379 // If we didn't get a net to highlight from the selection, use the cursor
1380 if( net < 0 )
1381 {
1383 guide.SetIgnoreZoneFills( false );
1384
1385 PCB_LAYER_ID activeLayer = static_cast<PCB_LAYER_ID>( view()->GetTopLayer() );
1386 guide.SetPreferredLayer( activeLayer );
1387
1388 GENERAL_COLLECTOR collector;
1389 collector.Collect( board, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T }, aPosition,
1390 guide );
1391
1392 if( collector.GetCount() == 0 )
1393 collector.Collect( board, { PCB_ZONE_T, PCB_FP_ZONE_T }, aPosition, guide );
1394
1395 // Apply the active selection filter, except we want to allow picking locked items for
1396 // highlighting even if the user has disabled them for selection
1397 SELECTION_FILTER_OPTIONS& filter = selectionTool->GetFilter();
1398
1399 bool saved = filter.lockedItems;
1400 filter.lockedItems = true;
1401
1402 selectionTool->FilterCollectedItems( collector, true );
1403
1404 filter.lockedItems = saved;
1405
1406 // Clear the previous highlight
1407 //m_frame->SendMessageToEESCHEMA( nullptr );
1408
1409 bool highContrast = settings->GetHighContrast();
1410 PCB_LAYER_ID contrastLayer = settings->GetPrimaryHighContrastLayer();
1411
1412 for( int i = collector.GetCount() - 1; i >= 0; i-- )
1413 {
1414 LSET itemLayers = collector[i]->GetLayerSet();
1415
1416 if( ( itemLayers & LSET::AllCuMask() ).none() ||
1417 ( highContrast && !itemLayers.Contains( contrastLayer ) ) )
1418 {
1419 collector.Remove( i );
1420 continue;
1421 }
1422 }
1423
1424 enableHighlight = ( collector.GetCount() > 0 );
1425
1426 // Obtain net code for the clicked item
1427 if( enableHighlight )
1428 {
1429 BOARD_CONNECTED_ITEM* targetItem = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] );
1430
1431 if( targetItem->Type() == PCB_PAD_T )
1432 m_frame->SendCrossProbeItem( targetItem );
1433
1434 net = targetItem->GetNetCode();
1435 }
1436 }
1437
1438 const std::set<int>& netcodes = settings->GetHighlightNetCodes();
1439
1440 // Toggle highlight when the same net was picked
1441 if( netcodes.count( net ) )
1442 enableHighlight = !settings->IsHighlightEnabled();
1443
1444 if( enableHighlight != settings->IsHighlightEnabled() || !netcodes.count( net ) )
1445 {
1446 if( !netcodes.empty() )
1447 m_lastHighlighted = netcodes;
1448
1449 settings->SetHighlight( enableHighlight, net );
1450 m_toolMgr->GetView()->UpdateAllLayersColor();
1451 }
1452
1453 // Store the highlighted netcode in the current board (for dialogs for instance)
1454 if( enableHighlight && net >= 0 )
1455 {
1456 m_currentlyHighlighted = netcodes;
1457 board->SetHighLightNet( net );
1458 board->HighLightON();
1459
1460 NETINFO_ITEM* netinfo = board->FindNet( net );
1461
1462 if( netinfo )
1463 {
1464 std::vector<MSG_PANEL_ITEM> items;
1465 netinfo->GetMsgPanelInfo( m_frame, items );
1466 m_frame->SetMsgPanel( items );
1467 m_frame->SendCrossProbeNetName( netinfo->GetNetname() );
1468 }
1469 }
1470 else
1471 {
1472 m_currentlyHighlighted.clear();
1473 board->ResetNetHighLight();
1474 m_frame->SetMsgPanel( board );
1475 m_frame->SendCrossProbeNetName( "" );
1476 }
1477
1478 return true;
1479}
1480
1481
1483{
1484 int netcode = aEvent.Parameter<intptr_t>();
1486 const std::set<int>& highlighted = settings->GetHighlightNetCodes();
1487
1488 if( netcode > 0 )
1489 {
1490 m_lastHighlighted = highlighted;
1491 settings->SetHighlight( true, netcode );
1493 m_currentlyHighlighted.clear();
1494 m_currentlyHighlighted.insert( netcode );
1495 }
1496 else if( aEvent.IsAction( &PCB_ACTIONS::highlightNetSelection ) )
1497 {
1498 // Highlight selection (cursor position will be ignored)
1499 highlightNet( getViewControls()->GetMousePosition(), true );
1500 }
1501 else if( aEvent.IsAction( &PCB_ACTIONS::toggleLastNetHighlight ) )
1502 {
1503 std::set<int> temp = highlighted;
1504 settings->SetHighlight( m_lastHighlighted );
1507 m_lastHighlighted = temp;
1508 }
1509 else if( aEvent.IsAction( &PCB_ACTIONS::toggleNetHighlight ) )
1510 {
1511 bool turnOn = highlighted.empty() && !m_currentlyHighlighted.empty();
1512 settings->SetHighlight( m_currentlyHighlighted, turnOn );
1514 }
1515 else // Highlight the net belonging to the item under the cursor
1516 {
1517 highlightNet( getViewControls()->GetMousePosition(), false );
1518 }
1519
1520 return 0;
1521}
1522
1523
1525{
1526 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
1528
1529 m_currentlyHighlighted.clear();
1530 m_lastHighlighted.clear();
1531
1533 settings->SetHighlight( false );
1537 return 0;
1538}
1539
1540
1542{
1544 BOARD* board = getModel<BOARD>();
1545
1546 // Deactivate other tools; particularly important if another PICKER is currently running
1547 Activate();
1548
1549 picker->SetCursor( KICURSOR::BULLSEYE );
1550
1551 picker->SetClickHandler(
1552 [this, board]( const VECTOR2D& pt ) -> bool
1553 {
1555
1558 PCB_SELECTION& selection = selectionTool->GetSelection();
1559
1560 if( selection.Empty() )
1561 {
1564 selection = selectionTool->GetSelection();
1565 }
1566
1567 if( selection.Empty() )
1568 {
1569 // Clear the previous local ratsnest if we click off all items
1570 for( FOOTPRINT* fp : board->Footprints() )
1571 {
1572 for( PAD* pad : fp->Pads() )
1573 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1574 }
1575 }
1576 else
1577 {
1578 for( EDA_ITEM* item : selection )
1579 {
1580 if( PAD* pad = dyn_cast<PAD*>( item) )
1581 {
1582 pad->SetLocalRatsnestVisible( !pad->GetLocalRatsnestVisible() );
1583 }
1584 else if( FOOTPRINT* fp = dyn_cast<FOOTPRINT*>( item) )
1585 {
1586 if( !fp->Pads().empty() )
1587 {
1588 bool enable = !fp->Pads()[0]->GetLocalRatsnestVisible();
1589
1590 for( PAD* childPad : fp->Pads() )
1591 childPad->SetLocalRatsnestVisible( enable );
1592 }
1593 }
1594 }
1595 }
1596
1598
1599 return true;
1600 } );
1601
1602 picker->SetFinalizeHandler(
1603 [this, board]( int aCondition )
1604 {
1605 if( aCondition != PCB_PICKER_TOOL::END_ACTIVATE )
1606 {
1607 for( FOOTPRINT* fp : board->Footprints() )
1608 {
1609 for( PAD* pad : fp->Pads() )
1610 pad->SetLocalRatsnestVisible( displayOptions().m_ShowGlobalRatsnest );
1611 }
1612 }
1613 } );
1614
1616
1617 return 0;
1618}
1619
1620
1622{
1624
1625 // If we have passed the simple move vector, we can update without recalculation
1626 if( aEvent.Parameter<VECTOR2I*>() )
1627 {
1628 delta = *aEvent.Parameter<VECTOR2I*>();
1629 delete aEvent.Parameter<VECTOR2I*>();
1630 }
1631 else
1632 {
1633 // We can delete the existing map to force a recalculation
1634 delete m_dynamicData;
1635 m_dynamicData = nullptr;
1636 }
1637
1638 auto selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1639 auto& selection = selectionTool->GetSelection();
1640 auto connectivity = getModel<BOARD>()->GetConnectivity();
1641
1642 if( selection.Empty() )
1643 {
1644 connectivity->ClearLocalRatsnest();
1645 delete m_dynamicData;
1646 m_dynamicData = nullptr;
1647 }
1648 else
1649 {
1651 }
1652
1653 return 0;
1654}
1655
1656
1658{
1659 getModel<BOARD>()->GetConnectivity()->ClearLocalRatsnest();
1660 delete m_dynamicData;
1661 m_dynamicData = nullptr;
1662
1663 return 0;
1664}
1665
1666
1668{
1670 SELECTION& selection = selectionTool->GetSelection();
1671 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board()->GetConnectivity();
1672 std::vector<BOARD_ITEM*> items;
1673 std::deque<EDA_ITEM*> queued_items( selection.begin(), selection.end() );
1674
1675 for( std::size_t i = 0; i < queued_items.size(); ++i )
1676 {
1677 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( queued_items[i] );
1678
1679 if( item->Type() == PCB_FOOTPRINT_T )
1680 {
1681 for( PAD* pad : static_cast<FOOTPRINT*>( item )->Pads() )
1682 {
1683 if( pad->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1684 items.push_back( pad );
1685 }
1686 }
1687 else if( item->Type() == PCB_GROUP_T )
1688 {
1689 PCB_GROUP *group = static_cast<PCB_GROUP*>( item );
1690 group->RunOnDescendants( [ &queued_items ]( BOARD_ITEM *aItem )
1691 {
1692 queued_items.push_back( aItem );
1693 } );
1694 }
1695 else if( BOARD_CONNECTED_ITEM* boardItem = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
1696 {
1697 if( boardItem->GetLocalRatsnestVisible() || displayOptions().m_ShowModuleRatsnest )
1698 items.push_back( boardItem );
1699 }
1700 }
1701
1702 if( items.empty() || std::none_of( items.begin(), items.end(),
1703 []( const BOARD_ITEM* aItem )
1704 {
1705 return( aItem->Type() == PCB_TRACE_T
1706 || aItem->Type() == PCB_PAD_T
1707 || aItem->Type() == PCB_ARC_T
1708 || aItem->Type() == PCB_ZONE_T
1709 || aItem->Type() == PCB_FOOTPRINT_T
1710 || aItem->Type() == PCB_VIA_T );
1711 } ) )
1712 {
1713 return;
1714 }
1715
1716 if( !m_dynamicData )
1717 {
1718 m_dynamicData = new CONNECTIVITY_DATA( items, true );
1719 connectivity->BlockRatsnestItems( items );
1720 }
1721 else
1722 {
1723 m_dynamicData->Move( aDelta );
1724 }
1725
1726 connectivity->ComputeLocalRatsnest( items, m_dynamicData );
1727}
1728
1729
1731{
1732 if( m_listNetsDialog == nullptr )
1733 {
1735 std::make_unique<DIALOG_NET_INSPECTOR>( m_frame, m_listNetsDialogSettings );
1736
1737 m_listNetsDialog->Connect( wxEVT_CLOSE_WINDOW,
1738 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr,
1739 this );
1740
1741 m_listNetsDialog->Connect( wxEVT_BUTTON,
1742 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr,
1743 this );
1744 }
1745
1746 m_listNetsDialog->Raise();
1747 m_listNetsDialog->Show( true );
1748 return 0;
1749}
1750
1751
1753{
1755
1756 m_listNetsDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1757 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
1758
1759 m_listNetsDialog->Disconnect( wxEVT_BUTTON,
1760 wxCommandEventHandler( BOARD_INSPECTION_TOOL::onListNetsDialogClosed ), nullptr, this );
1761
1762 m_listNetsDialog->Destroy();
1763 m_listNetsDialog.release();
1764}
1765
1766
1768{
1769 m_inspectClearanceDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1771 nullptr, this );
1772
1773 m_inspectClearanceDialog->Destroy();
1774 m_inspectClearanceDialog.release();
1775}
1776
1777
1779{
1780 m_inspectConstraintsDialog->Disconnect( wxEVT_CLOSE_WINDOW,
1782 nullptr, this );
1783
1784 m_inspectConstraintsDialog->Destroy();
1786}
1787
1788
1790{
1791 doHideRatsnestNet( aEvent.Parameter<intptr_t>(), true );
1792 return 0;
1793}
1794
1795
1797{
1798 doHideRatsnestNet( aEvent.Parameter<intptr_t>(), false );
1799 return 0;
1800}
1801
1802
1803void BOARD_INSPECTION_TOOL::doHideRatsnestNet( int aNetCode, bool aHide )
1804{
1807
1809 SELECTION& selection = selectionTool->GetSelection();
1810
1811 if( aNetCode <= 0 && !selection.Empty() )
1812 {
1813 for( EDA_ITEM* item : selection )
1814 {
1815 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
1816 {
1817 if( bci->GetNetCode() > 0 )
1818 doHideRatsnestNet( bci->GetNetCode(), aHide );
1819 }
1820 }
1821
1822 return;
1823 }
1824
1825 if( aHide )
1826 rs->GetHiddenNets().insert( aNetCode );
1827 else
1828 rs->GetHiddenNets().erase( aNetCode );
1829
1832
1833 m_frame->GetAppearancePanel()->OnNetVisibilityChanged( aNetCode, !aHide );
1834}
1835
1836
1838{
1842
1847
1854
1857}
@ 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:158
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:58
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:180
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:115
virtual bool IsTented() const
Definition: board_item.h:133
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:245
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:185
virtual bool IsOnCopperLayer() const
Definition: board_item.h:123
virtual bool HasHole() const
Definition: board_item.h:128
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
ZONES & Zones()
Definition: board.h:313
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2012
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:943
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2003
FOOTPRINTS & Footprints()
Definition: board.h:307
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:410
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:628
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2025
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:424
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:147
int m_DisallowFlags
Definition: drc_rule.h:171
ZONE_CONNECTION m_ZoneConnection
Definition: drc_rule.h:172
MINOPTMAX< int > m_Value
Definition: drc_rule.h:170
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:671
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
Definition: drc_engine.cpp:512
DRC_CONSTRAINT EvalZoneConnection(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
Definition: drc_engine.cpp:610
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
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:144
virtual wxString GetSelectMenuText(UNITS_PROVIDER *aUnitsProvider) const
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: eda_item.cpp:108
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:2041
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:2054
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:2199
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
Definition: footprint.cpp:2187
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:758
virtual int GetTopLayer() const
Definition: view.cpp:813
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:530
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:600
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:66
const wxString & GetNetname() const
Definition: netinfo.h:119
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:59
const VECTOR2I & GetDrillSize() const
Definition: pad.h:262
PAD_ATTRIB GetAttribute() const
Definition: pad.h:395
DISPLAY_OPTIONS m_Display
static TOOL_ACTION highlightItem
Definition: pcb_actions.h:491
static TOOL_ACTION listNets
Definition: pcb_actions.h:373
static TOOL_ACTION toggleNetHighlight
Definition: pcb_actions.h:489
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:487
static TOOL_ACTION hideNetInRatsnest
Definition: pcb_actions.h:494
static TOOL_ACTION hideLocalRatsnest
Definition: pcb_actions.h:497
static TOOL_ACTION showNetInRatsnest
Definition: pcb_actions.h:495
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION toggleLastNetHighlight
Definition: pcb_actions.h:488
static TOOL_ACTION inspectConstraints
Definition: pcb_actions.h:483
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:486
static TOOL_ACTION inspectClearance
Definition: pcb_actions.h:482
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:498
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:490
static TOOL_ACTION boardStatistics
Definition: pcb_actions.h:478
static TOOL_ACTION localRatsnestTool
Definition: pcb_actions.h:496
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
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:65
ITER end()
Definition: selection.h:72
ITER begin()
Definition: selection.h:71
int Size() const
Returns the number of selected parts.
Definition: selection.h:113
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:107
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:214
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:88
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.
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: zone.cpp:467
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:314
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:121
@ 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:56
@ COURTYARD_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:51
@ VIA_DIAMETER_CONSTRAINT
Definition: drc_rule.h:62
@ DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT
Definition: drc_rule.h:66
@ DIFF_PAIR_GAP_CONSTRAINT
Definition: drc_rule.h:65
@ DISALLOW_CONSTRAINT
Definition: drc_rule.h:61
@ TRACK_WIDTH_CONSTRAINT
Definition: drc_rule.h:55
@ SILK_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:52
@ EDGE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:49
@ MIN_RESOLVED_SPOKES_CONSTRAINT
Definition: drc_rule.h:60
@ TEXT_THICKNESS_CONSTRAINT
Definition: drc_rule.h:54
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:70
@ CLEARANCE_CONSTRAINT
Definition: drc_rule.h:46
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
Definition: drc_rule.h:59
@ CONNECTION_WIDTH_CONSTRAINT
Definition: drc_rule.h:72
@ THERMAL_RELIEF_GAP_CONSTRAINT
Definition: drc_rule.h:58
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:47
@ HOLE_SIZE_CONSTRAINT
Definition: drc_rule.h:50
@ TEXT_HEIGHT_CONSTRAINT
Definition: drc_rule.h:53
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:69
@ HOLE_TO_HOLE_CONSTRAINT
Definition: drc_rule.h:48
#define _(s)
#define MALFORMED_COURTYARDS
static std::vector< KICAD_T > connectedTypes
E_SERIE r
Definition: eserie.cpp:41
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition: layer_ids.h:899
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:825
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
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
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.