KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_netlist_updater.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 CERN
6 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
7 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
8 *
9 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you may find one here:
23 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24 * or you may search the http://www.gnu.org website for the version 2 license,
25 * or you may write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29
30#include <common.h> // for PAGE_INFO
31
32#include <base_units.h>
33#include <board.h>
35#include <netinfo.h>
36#include <footprint.h>
37#include <pad.h>
38#include <pcb_track.h>
39#include <zone.h>
40#include <string_utils.h>
41#include <pcbnew_settings.h>
42#include <pcb_edit_frame.h>
45#include <reporter.h>
46
48
49
51 m_frame( aFrame ),
52 m_commit( aFrame ),
53 m_board( aBoard )
54{
56
58 m_isDryRun = false;
60 m_lookupByTimestamp = false;
61
63 m_errorCount = 0;
65}
66
67
69{
70}
71
72
73// These functions allow inspection of pad nets during dry runs by keeping a cache of
74// current pad netnames indexed by pad.
75
76void BOARD_NETLIST_UPDATER::cacheNetname( PAD* aPad, const wxString& aNetname )
77{
78 m_padNets[ aPad ] = aNetname;
79}
80
81
83{
84 if( m_isDryRun && m_padNets.count( aPad ) )
85 return m_padNets[ aPad ];
86 else
87 return aPad->GetNetname();
88}
89
90
91void BOARD_NETLIST_UPDATER::cachePinFunction( PAD* aPad, const wxString& aPinFunction )
92{
93 m_padPinFunctions[ aPad ] = aPinFunction;
94}
95
96
98{
99 if( m_isDryRun && m_padPinFunctions.count( aPad ) )
100 return m_padPinFunctions[ aPad ];
101 else
102 return aPad->GetPinFunction();
103}
104
105
107{
108 VECTOR2I bestPosition;
109
110 if( !m_board->IsEmpty() )
111 {
112 // Position new components below any existing board features.
114
115 if( bbox.GetWidth() || bbox.GetHeight() )
116 {
117 bestPosition.x = bbox.Centre().x;
118 bestPosition.y = bbox.GetBottom() + pcbIUScale.mmToIU( 10 );
119 }
120 }
121 else
122 {
123 // Position new components in the center of the page when the board is empty.
125
126 bestPosition.x = pageSize.x / 2;
127 bestPosition.y = pageSize.y / 2;
128 }
129
130 return bestPosition;
131}
132
133
135{
136 wxString msg;
137
138 if( aComponent->GetFPID().empty() )
139 {
140 msg.Printf( _( "Cannot add %s (no footprint assigned)." ),
141 aComponent->GetReference(),
142 aComponent->GetFPID().Format().wx_str() );
144 ++m_errorCount;
145 return nullptr;
146 }
147
148 FOOTPRINT* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
149
150 if( footprint == nullptr )
151 {
152 msg.Printf( _( "Cannot add %s (footprint '%s' not found)." ),
153 aComponent->GetReference(),
154 aComponent->GetFPID().Format().wx_str() );
156 ++m_errorCount;
157 return nullptr;
158 }
159
160 if( m_isDryRun )
161 {
162 msg.Printf( _( "Add %s (footprint '%s')." ),
163 aComponent->GetReference(),
164 aComponent->GetFPID().Format().wx_str() );
165
166 delete footprint;
167 footprint = nullptr;
168 }
169 else
170 {
171 for( PAD* pad : footprint->Pads() )
172 {
173 // Set the pads ratsnest settings to the global settings
174 pad->SetLocalRatsnestVisible( m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
175
176 // Pads in the library all have orphaned nets. Replace with Default.
177 pad->SetNetCode( 0 );
178 }
179
180 footprint->SetParent( m_board );
182
183 // This flag is used to prevent connectivity from considering the footprint during its
184 // initial build after the footprint is committed, because we're going to immediately start
185 // a move operation on the footprint and don't want its pads to drive nets onto vias/tracks
186 // it happens to land on at the initial position.
187 footprint->SetAttributes( footprint->GetAttributes() | FP_JUST_ADDED );
188
189 m_addedFootprints.push_back( footprint );
190 m_commit.Add( footprint );
191
192 msg.Printf( _( "Added %s (footprint '%s')." ),
193 aComponent->GetReference(),
194 aComponent->GetFPID().Format().wx_str() );
195 }
196
199 return footprint;
200}
201
202
204 COMPONENT* aNewComponent )
205{
206 wxString msg;
207
208 if( aNewComponent->GetFPID().empty() )
209 {
210 msg.Printf( _( "Cannot update %s (no footprint assigned)." ),
211 aNewComponent->GetReference(),
212 aNewComponent->GetFPID().Format().wx_str() );
214 ++m_errorCount;
215 return nullptr;
216 }
217
218 FOOTPRINT* newFootprint = m_frame->LoadFootprint( aNewComponent->GetFPID() );
219
220 if( newFootprint == nullptr )
221 {
222 msg.Printf( _( "Cannot update %s (footprint '%s' not found)." ),
223 aNewComponent->GetReference(),
224 aNewComponent->GetFPID().Format().wx_str() );
226 ++m_errorCount;
227 return nullptr;
228 }
229
230 if( m_isDryRun )
231 {
232 msg.Printf( _( "Change %s footprint from '%s' to '%s'."),
233 aFootprint->GetReference(),
234 aFootprint->GetFPID().Format().wx_str(),
235 aNewComponent->GetFPID().Format().wx_str() );
236
237 delete newFootprint;
238 newFootprint = nullptr;
239 }
240 else
241 {
242 m_frame->ExchangeFootprint( aFootprint, newFootprint, m_commit );
243
244 msg.Printf( _( "Changed %s footprint from '%s' to '%s'."),
245 aFootprint->GetReference(),
246 aFootprint->GetFPID().Format().wx_str(),
247 aNewComponent->GetFPID().Format().wx_str() );
248 }
249
252 return newFootprint;
253}
254
255
257 COMPONENT* aNetlistComponent )
258{
259 wxString msg;
260
261 // Create a copy only if the footprint has not been added during this update
262 FOOTPRINT* copy = nullptr;
263
264 if( !m_commit.GetStatus( aPcbFootprint ) )
265 {
266 copy = static_cast<FOOTPRINT*>( aPcbFootprint->Clone() );
267 copy->SetParentGroup( nullptr );
268 }
269
270 bool changed = false;
271
272 // Test for reference designator field change.
273 if( aPcbFootprint->GetReference() != aNetlistComponent->GetReference() )
274 {
275 if( m_isDryRun )
276 {
277 msg.Printf( _( "Change %s reference designator to %s." ),
278 aPcbFootprint->GetReference(),
279 aNetlistComponent->GetReference() );
280 }
281 else
282 {
283 msg.Printf( _( "Changed %s reference designator to %s." ),
284 aPcbFootprint->GetReference(),
285 aNetlistComponent->GetReference() );
286
287 changed = true;
288 aPcbFootprint->SetReference( aNetlistComponent->GetReference() );
289 }
290
292 }
293
294 // Test for value field change.
295 if( aPcbFootprint->GetValue() != aNetlistComponent->GetValue() )
296 {
297 if( m_isDryRun )
298 {
299 msg.Printf( _( "Change %s value from %s to %s." ),
300 aPcbFootprint->GetReference(),
301 aPcbFootprint->GetValue(),
302 aNetlistComponent->GetValue() );
303 }
304 else
305 {
306 msg.Printf( _( "Changed %s value from %s to %s." ),
307 aPcbFootprint->GetReference(),
308 aPcbFootprint->GetValue(),
309 aNetlistComponent->GetValue() );
310
311 changed = true;
312 aPcbFootprint->SetValue( aNetlistComponent->GetValue() );
313 }
314
316 }
317
318 // Test for footprint change. This is controlled by a separate flag, that will output
319 // its own message if the footprint is changed, so we just set the field here.
320 if( ( m_replaceFootprints || ( aPcbFootprint->GetAttributes() & FP_JUST_ADDED ) )
321 && !m_isDryRun )
322 {
323 aPcbFootprint->Footprint().SetText(
324 aNetlistComponent->GetFields()[GetCanonicalFieldName( FOOTPRINT_FIELD )] );
325 }
326
327 // Test for time stamp change.
328 KIID_PATH new_path = aNetlistComponent->GetPath();
329
330 if( !aNetlistComponent->GetKIIDs().empty() )
331 new_path.push_back( aNetlistComponent->GetKIIDs().front() );
332
333 if( aPcbFootprint->GetPath() != new_path )
334 {
335 if( m_isDryRun )
336 {
337 msg.Printf( _( "Update %s symbol association from %s to %s." ),
338 aPcbFootprint->GetReference(),
339 aPcbFootprint->GetPath().AsString(),
340 new_path.AsString() );
341 }
342 else
343 {
344 msg.Printf( _( "Updated %s symbol association from %s to %s." ),
345 aPcbFootprint->GetReference(),
346 aPcbFootprint->GetPath().AsString(),
347 new_path.AsString() );
348
349 changed = true;
350 aPcbFootprint->SetPath( new_path );
351 }
352
354 }
355
356 nlohmann::ordered_map<wxString, wxString> fpFieldsAsMap;
357
358 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
359 {
360 // These fields are individually checked above
361 if( field->IsReference() || field->IsValue() || field->IsFootprint() )
362 continue;
363
364 fpFieldsAsMap[field->GetName()] = field->GetText();
365 }
366
367 // Remove the ref/value/footprint fields that are individually handled
368 nlohmann::ordered_map<wxString, wxString> compFields = aNetlistComponent->GetFields();
369 compFields.erase( GetCanonicalFieldName( REFERENCE_FIELD ) );
370 compFields.erase( GetCanonicalFieldName( VALUE_FIELD ) );
371 compFields.erase( GetCanonicalFieldName( FOOTPRINT_FIELD ) );
372
373 // Fields are stored as an ordered map, but we don't (yet) support reordering
374 // the footprint fields to match the symbol, so we manually check the fields
375 // in the order they are stored in the symbol.
376 bool same = true;
377
378 for( std::pair<wxString, wxString> field : compFields )
379 {
380 if( fpFieldsAsMap.count( field.first ) == 0 || fpFieldsAsMap[field.first] != field.second )
381 {
382 same = false;
383 break;
384 }
385 }
386
387 if( !same )
388 {
389 if( m_isDryRun )
390 {
391 msg.Printf( _( "Update %s fields." ), aPcbFootprint->GetReference() );
393
394 // Remove fields that aren't present in the symbol
395 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
396 {
397 if( field->IsMandatoryField() )
398 continue;
399
400 if( compFields.count( field->GetName() ) == 0 )
401 {
402 msg.Printf( _( "Remove %s footprint fields not in symbol." ),
403 aPcbFootprint->GetReference() );
405 break;
406 }
407 }
408 }
409 else
410 {
411 msg.Printf( _( "Updated %s fields." ), aPcbFootprint->GetReference() );
413
414 changed = true;
415
416 // Add or change field value
417 for( auto& [name, value] : compFields )
418 {
419 if( aPcbFootprint->HasFieldByName( name ) )
420 {
421 aPcbFootprint->GetFieldByName( name )->SetText( value );
422 }
423 else
424 {
425 int idx = aPcbFootprint->GetFieldCount();
426 PCB_FIELD* newField = aPcbFootprint->AddField( PCB_FIELD( aPcbFootprint, idx ) );
427
428 newField->SetName( name );
429 newField->SetText( value );
430 newField->SetVisible( false );
431 newField->SetLayer( aPcbFootprint->GetLayer() == F_Cu ? F_Fab : B_Fab );
432
433 // Give the relative position (0,0) in footprint
434 newField->SetPosition( aPcbFootprint->GetPosition() );
435 // Give the footprint orientation
436 newField->Rotate( aPcbFootprint->GetPosition(), aPcbFootprint->GetOrientation() );
437
438 if( m_frame )
439 {
442 view->Add( newField );
443 }
444 }
445 }
446
447 // Remove fields that aren't present in the symbol
448 bool warned = false;
449
450 for( PCB_FIELD* field : aPcbFootprint->GetFields() )
451 {
452 if( field->IsMandatoryField() )
453 continue;
454
455 if( compFields.count( field->GetName() ) == 0 )
456 {
457 if( !warned )
458 {
459 warned = true;
460 msg.Printf( _( "Removed %s footprint fields not in symbol." ),
461 aPcbFootprint->GetReference() );
463 }
464
465 aPcbFootprint->RemoveField( field->GetCanonicalName() );
466
467 if( m_frame )
468 m_frame->GetCanvas()->GetView()->Remove( field );
469 }
470 }
471 }
472 }
473
474 wxString sheetname;
475 wxString sheetfile;
476 wxString fpFilters;
477
478 if( aNetlistComponent->GetProperties().count( wxT( "Sheetname" ) ) > 0 )
479 sheetname = aNetlistComponent->GetProperties().at( wxT( "Sheetname" ) );
480
481 if( aNetlistComponent->GetProperties().count( wxT( "Sheetfile" ) ) > 0 )
482 sheetfile = aNetlistComponent->GetProperties().at( wxT( "Sheetfile" ) );
483
484 if( aNetlistComponent->GetProperties().count( wxT( "ki_fp_filters" ) ) > 0 )
485 fpFilters = aNetlistComponent->GetProperties().at( wxT( "ki_fp_filters" ) );
486
487 if( sheetname != aPcbFootprint->GetSheetname() )
488 {
489 if( m_isDryRun )
490 {
491 msg.Printf( _( "Update %s sheetname to '%s'." ),
492 aPcbFootprint->GetReference(),
493 sheetname );
494 }
495 else
496 {
497 aPcbFootprint->SetSheetname( sheetname );
498 msg.Printf( _( "Updated %s sheetname to '%s'." ),
499 aPcbFootprint->GetReference(),
500 sheetname );
501 }
502
504 }
505
506 if( sheetfile != aPcbFootprint->GetSheetfile() )
507 {
508 if( m_isDryRun )
509 {
510 msg.Printf( _( "Update %s sheetfile to '%s'." ),
511 aPcbFootprint->GetReference(),
512 sheetfile );
513 }
514 else
515 {
516 aPcbFootprint->SetSheetfile( sheetfile );
517 msg.Printf( _( "Updated %s sheetfile to '%s'." ),
518 aPcbFootprint->GetReference(),
519 sheetfile );
520 }
521
523 }
524
525 if( fpFilters != aPcbFootprint->GetFilters() )
526 {
527 if( m_isDryRun )
528 {
529 msg.Printf( _( "Update %s footprint filters to '%s'." ),
530 aPcbFootprint->GetReference(),
531 fpFilters );
532 }
533 else
534 {
535 aPcbFootprint->SetFilters( fpFilters );
536 msg.Printf( _( "Updated %s footprint filters to '%s'." ),
537 aPcbFootprint->GetReference(),
538 fpFilters );
539 }
540
542 }
543
544 if( ( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) > 0 )
545 != ( ( aPcbFootprint->GetAttributes() & FP_EXCLUDE_FROM_BOM ) > 0 ) )
546 {
547 if( m_isDryRun )
548 {
549 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
550 {
551 msg.Printf( _( "Add %s 'exclude from BOM' fabrication attribute." ),
552 aPcbFootprint->GetReference() );
553 }
554 else
555 {
556 msg.Printf( _( "Remove %s 'exclude from BOM' fabrication attribute." ),
557 aPcbFootprint->GetReference() );
558 }
559 }
560 else
561 {
562 int attributes = aPcbFootprint->GetAttributes();
563
564 if( aNetlistComponent->GetProperties().count( wxT( "exclude_from_bom" ) ) )
565 {
566 attributes |= FP_EXCLUDE_FROM_BOM;
567 msg.Printf( _( "Added %s 'exclude from BOM' fabrication attribute." ),
568 aPcbFootprint->GetReference() );
569 }
570 else
571 {
572 attributes &= ~FP_EXCLUDE_FROM_BOM;
573 msg.Printf( _( "Removed %s 'exclude from BOM' fabrication attribute." ),
574 aPcbFootprint->GetReference() );
575 }
576
577 changed = true;
578 aPcbFootprint->SetAttributes( attributes );
579 }
580
582 }
583
584 if( ( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) > 0 )
585 != ( ( aPcbFootprint->GetAttributes() & FP_DNP ) > 0 ) )
586 {
587 if( m_isDryRun )
588 {
589 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
590 {
591 msg.Printf( _( "Add %s 'Do not place' fabrication attribute." ),
592 aPcbFootprint->GetReference() );
593 }
594 else
595 {
596 msg.Printf( _( "Remove %s 'Do not place' fabrication attribute." ),
597 aPcbFootprint->GetReference() );
598 }
599 }
600 else
601 {
602 int attributes = aPcbFootprint->GetAttributes();
603
604 if( aNetlistComponent->GetProperties().count( wxT( "dnp" ) ) )
605 {
606 attributes |= FP_DNP;
607 msg.Printf( _( "Added %s 'Do not place' fabrication attribute." ),
608 aPcbFootprint->GetReference() );
609 }
610 else
611 {
612 attributes &= ~FP_DNP;
613 msg.Printf( _( "Removed %s 'Do not place' fabrication attribute." ),
614 aPcbFootprint->GetReference() );
615 }
616
617 changed = true;
618 aPcbFootprint->SetAttributes( attributes );
619 }
620
622 }
623
624 if( changed && copy )
625 m_commit.Modified( aPcbFootprint, copy );
626 else if( copy )
627 delete copy;
628
629 return true;
630}
631
632
634 COMPONENT* aNewComponent )
635{
636 wxString msg;
637
638 // Create a copy only if the footprint has not been added during this update
639 FOOTPRINT* copy = nullptr;
640
641 if( !m_isDryRun && !m_commit.GetStatus( aFootprint ) )
642 {
643 copy = static_cast<FOOTPRINT*>( aFootprint->Clone() );
644 copy->SetParentGroup( nullptr );
645 }
646
647 bool changed = false;
648
649 // At this point, the component footprint is updated. Now update the nets.
650 PADS pads = aFootprint->Pads();
651 std::set<wxString> padNetnames;
652
653 std::sort( pads.begin(), pads.end(),
654 []( PAD* a, PAD* b )
655 {
656 return a->m_Uuid < b->m_Uuid;
657 } );
658
659 for( PAD* pad : pads )
660 {
661 const COMPONENT_NET& net = aNewComponent->GetNet( pad->GetNumber() );
662
663 wxString pinFunction;
664 wxString pinType;
665
666 if( net.IsValid() ) // i.e. the pad has a name
667 {
668 pinFunction = net.GetPinFunction();
669 pinType = net.GetPinType();
670 }
671
672 if( !m_isDryRun )
673 {
674 if( pad->GetPinFunction() != pinFunction )
675 {
676 changed = true;
677 pad->SetPinFunction( pinFunction );
678 }
679
680 if( pad->GetPinType() != pinType )
681 {
682 changed = true;
683 pad->SetPinType( pinType );
684 }
685 }
686 else
687 {
688 cachePinFunction( pad, pinFunction );
689 }
690
691 // Test if new footprint pad has no net (pads not on copper layers have no net).
692 if( !net.IsValid() || !pad->IsOnCopperLayer() )
693 {
694 if( !pad->GetNetname().IsEmpty() )
695 {
696 if( m_isDryRun )
697 {
698 msg.Printf( _( "Disconnect %s pin %s." ),
699 aFootprint->GetReference(),
700 pad->GetNumber() );
701 }
702 else
703 {
704 msg.Printf( _( "Disconnected %s pin %s." ),
705 aFootprint->GetReference(),
706 pad->GetNumber() );
707 }
708
710 }
711 else if( pad->IsOnCopperLayer() && !pad->GetNumber().IsEmpty() )
712 {
713 // pad is connectable but has no net found in netlist
714 msg.Printf( _( "No net found for component %s pad %s (no pin %s in symbol)." ),
715 pad->GetNumber(),
716 aFootprint->GetReference(),
717 pad->GetNumber() );
720 }
721
722 if( !m_isDryRun )
723 {
724 changed = true;
725 pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
726
727 // If the pad has no net from netlist (i.e. not in netlist
728 // it cannot have a pin function
729 if( pad->GetNetname().IsEmpty() )
730 pad->SetPinFunction( wxEmptyString );
731
732 }
733 else
734 {
735 cacheNetname( pad, wxEmptyString );
736 }
737 }
738 else // New footprint pad has a net.
739 {
740 wxString netName = net.GetNetName();
741
742 if( pad->IsNoConnectPad() )
743 {
744 for( int jj = 0; !padNetnames.insert( netName ).second; jj++ )
745 netName = wxString::Format( wxS( "%s_%d" ), net.GetNetName(), jj );
746 }
747
748 NETINFO_ITEM* netinfo = m_board->FindNet( netName );
749
750 if( netinfo && !m_isDryRun )
751 netinfo->SetIsCurrent( true );
752
753 if( pad->GetNetname() != netName )
754 {
755
756 if( netinfo == nullptr )
757 {
758 // It might be a new net that has not been added to the board yet
759 if( m_addedNets.count( netName ) )
760 netinfo = m_addedNets[ netName ];
761 }
762
763 if( netinfo == nullptr )
764 {
765 netinfo = new NETINFO_ITEM( m_board, netName );
766
767 // It is a new net, we have to add it
768 if( !m_isDryRun )
769 {
770 changed = true;
771 m_commit.Add( netinfo );
772 }
773
774 m_addedNets[netName] = netinfo;
775 msg.Printf( _( "Add net %s." ), UnescapeString( netName ) );
777 }
778
779 if( !pad->GetNetname().IsEmpty() )
780 {
781 m_oldToNewNets[ pad->GetNetname() ] = netName;
782
783 if( m_isDryRun )
784 {
785 msg.Printf( _( "Reconnect %s pin %s from %s to %s."),
786 aFootprint->GetReference(),
787 pad->GetNumber(),
788 UnescapeString( pad->GetNetname() ),
789 UnescapeString( netName ) );
790 }
791 else
792 {
793 msg.Printf( _( "Reconnected %s pin %s from %s to %s."),
794 aFootprint->GetReference(),
795 pad->GetNumber(),
796 UnescapeString( pad->GetNetname() ),
797 UnescapeString( netName ) );
798 }
799 }
800 else
801 {
802 if( m_isDryRun )
803 {
804 msg.Printf( _( "Connect %s pin %s to %s."),
805 aFootprint->GetReference(),
806 pad->GetNumber(),
807 UnescapeString( netName ) );
808 }
809 else
810 {
811 msg.Printf( _( "Connected %s pin %s to %s."),
812 aFootprint->GetReference(),
813 pad->GetNumber(),
814 UnescapeString( netName ) );
815 }
816 }
817
819
820 if( !m_isDryRun )
821 {
822 changed = true;
823 pad->SetNet( netinfo );
824 }
825 else
826 {
827 cacheNetname( pad, netName );
828 }
829 }
830 }
831 }
832
833 if( changed && copy )
834 m_commit.Modified( aFootprint, copy );
835 else if( copy )
836 delete copy;
837
838 return true;
839}
840
841
843{
844 for( ZONE* zone : m_board->Zones() )
845 {
846 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
847 continue;
848
849 m_zoneConnectionsCache[ zone ] = m_board->GetConnectivity()->GetConnectedPads( zone );
850 }
851}
852
853
855{
856 wxString msg;
857 std::set<wxString> netlistNetnames;
858
859 for( int ii = 0; ii < (int) aNetlist.GetCount(); ii++ )
860 {
861 const COMPONENT* component = aNetlist.GetComponent( ii );
862
863 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
864 {
865 const COMPONENT_NET& net = component->GetNet( jj );
866 netlistNetnames.insert( net.GetNetName() );
867 }
868 }
869
870 for( PCB_TRACK* via : m_board->Tracks() )
871 {
872 if( via->Type() != PCB_VIA_T )
873 continue;
874
875 if( netlistNetnames.count( via->GetNetname() ) == 0 )
876 {
877 wxString updatedNetname = wxEmptyString;
878
879 // Take via name from name change map if it didn't match to a new pad
880 // (this is useful for stitching vias that don't connect to tracks)
881 if( m_oldToNewNets.count( via->GetNetname() ) )
882 {
883 updatedNetname = m_oldToNewNets[via->GetNetname()];
884 }
885
886 if( !updatedNetname.IsEmpty() )
887 {
888 if( m_isDryRun )
889 {
890 wxString originalNetname = via->GetNetname();
891
892 msg.Printf( _( "Reconnect via from %s to %s." ),
893 UnescapeString( originalNetname ),
894 UnescapeString( updatedNetname ) );
895
897 }
898 else
899 {
900 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
901
902 if( !netinfo )
903 netinfo = m_addedNets[updatedNetname];
904
905 if( netinfo )
906 {
907 wxString originalNetname = via->GetNetname();
908
910 via->SetNet( netinfo );
911
912 msg.Printf( _( "Reconnected via from %s to %s." ),
913 UnescapeString( originalNetname ),
914 UnescapeString( updatedNetname ) );
915
917 }
918 }
919 }
920 else
921 {
922 msg.Printf( _( "Via connected to unknown net (%s)." ),
923 UnescapeString( via->GetNetname() ) );
926 }
927 }
928 }
929
930 // Test copper zones to detect "dead" nets (nets without any pad):
931 for( ZONE* zone : m_board->Zones() )
932 {
933 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
934 continue;
935
936 if( netlistNetnames.count( zone->GetNetname() ) == 0 )
937 {
938 // Look for a pad in the zone's connected-pad-cache which has been updated to
939 // a new net and use that. While this won't always be the right net, the dead
940 // net is guaranteed to be wrong.
941 wxString updatedNetname = wxEmptyString;
942
943 for( PAD* pad : m_zoneConnectionsCache[ zone ] )
944 {
945 if( getNetname( pad ) != zone->GetNetname() )
946 {
947 updatedNetname = getNetname( pad );
948 break;
949 }
950 }
951
952 // Take zone name from name change map if it didn't match to a new pad
953 // (this is useful for zones on internal layers)
954 if( updatedNetname.IsEmpty() && m_oldToNewNets.count( zone->GetNetname() ) )
955 {
956 updatedNetname = m_oldToNewNets[ zone->GetNetname() ];
957 }
958
959 if( !updatedNetname.IsEmpty() )
960 {
961 if( m_isDryRun )
962 {
963 wxString originalNetname = zone->GetNetname();
964
965 if( !zone->GetZoneName().IsEmpty() )
966 {
967 msg.Printf( _( "Reconnect copper zone '%s' from %s to %s." ),
968 zone->GetZoneName(),
969 UnescapeString( originalNetname ),
970 UnescapeString( updatedNetname ) );
971 }
972 else
973 {
974 msg.Printf( _( "Reconnect copper zone from %s to %s." ),
975 UnescapeString( originalNetname ),
976 UnescapeString( updatedNetname ) );
977 }
978
980 }
981 else
982 {
983 NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
984
985 if( !netinfo )
986 netinfo = m_addedNets[ updatedNetname ];
987
988 if( netinfo )
989 {
990 wxString originalNetname = zone->GetNetname();
991
992 m_commit.Modify( zone );
993 zone->SetNet( netinfo );
994
995 if( !zone->GetZoneName().IsEmpty() )
996 {
997 msg.Printf( _( "Reconnected copper zone '%s' from %s to %s." ),
998 zone->GetZoneName(),
999 UnescapeString( originalNetname ),
1000 UnescapeString( updatedNetname ) );
1001 }
1002 else
1003 {
1004 msg.Printf( _( "Reconnected copper zone from %s to %s." ),
1005 UnescapeString( originalNetname ),
1006 UnescapeString( updatedNetname ) );
1007 }
1008
1010 }
1011 }
1012 }
1013 else
1014 {
1015 if( !zone->GetZoneName().IsEmpty() )
1016 {
1017 msg.Printf( _( "Copper zone '%s' has no pads connected." ),
1018 zone->GetZoneName() );
1019 }
1020 else
1021 {
1022 PCB_LAYER_ID layer = zone->GetLayer();
1023 VECTOR2I pos = zone->GetPosition();
1024
1025 msg.Printf( _( "Copper zone on layer %s at (%s, %s) has no pads connected." ),
1026 m_board->GetLayerName( layer ),
1028 m_frame->MessageTextFromValue( pos.y ) );
1029 }
1030
1033 }
1034 }
1035 }
1036
1037 return true;
1038}
1039
1040
1042 std::map<COMPONENT*, FOOTPRINT*>& aFootprintMap )
1043{
1044 // Verify that board contains all pads in netlist: if it doesn't then footprints are
1045 // wrong or missing.
1046
1047 wxString msg;
1048 wxString padNumber;
1049
1050 for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
1051 {
1052 COMPONENT* component = aNetlist.GetComponent( i );
1053 FOOTPRINT* footprint = aFootprintMap[component];
1054
1055 if( !footprint ) // It can be missing in partial designs
1056 continue;
1057
1058 // Explore all pins/pads in component
1059 for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
1060 {
1061 padNumber = component->GetNet( jj ).GetPinName();
1062
1063 if( padNumber.IsEmpty() )
1064 {
1065 // bad symbol, report error
1066 msg.Printf( _( "Symbol %s has pins with no number. These pins can not be matched "
1067 "to pads in %s." ),
1068 component->GetReference(),
1069 footprint->GetFPID().Format().wx_str() );
1071 ++m_errorCount;
1072 }
1073 else if( !footprint->FindPadByNumber( padNumber ) )
1074 {
1075 // not found: bad footprint, report error
1076 msg.Printf( _( "%s pad %s not found in %s." ),
1077 component->GetReference(),
1078 padNumber,
1079 footprint->GetFPID().Format().wx_str() );
1081 ++m_errorCount;
1082 }
1083 }
1084 }
1085
1086 return true;
1087}
1088
1089
1091{
1092 FOOTPRINT* lastPreexistingFootprint = nullptr;
1093 COMPONENT* component = nullptr;
1094 wxString msg;
1095
1096 m_errorCount = 0;
1097 m_warningCount = 0;
1099
1100 std::map<COMPONENT*, FOOTPRINT*> footprintMap;
1101
1102 if( !m_board->Footprints().empty() )
1103 lastPreexistingFootprint = m_board->Footprints().back();
1104
1106
1107 // First mark all nets (except <no net>) as stale; we'll update those which are current
1108 // in the following two loops.
1109 //
1110 if( !m_isDryRun )
1111 {
1112 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1113 net->SetIsCurrent( net->GetNetCode() == 0 );
1114 }
1115
1116 // Next go through the netlist updating all board footprints which have matching component
1117 // entries and adding new footprints for those that don't.
1118 //
1119 for( unsigned i = 0; i < aNetlist.GetCount(); i++ )
1120 {
1121 component = aNetlist.GetComponent( i );
1122
1123 if( component->GetProperties().count( wxT( "exclude_from_board" ) ) )
1124 continue;
1125
1126 msg.Printf( _( "Processing symbol '%s:%s'." ),
1127 component->GetReference(),
1128 component->GetFPID().Format().wx_str() );
1130
1131 int matchCount = 0;
1132
1133 for( FOOTPRINT* footprint : m_board->Footprints() )
1134 {
1135 bool match = false;
1136
1138 {
1139 for( const KIID& uuid : component->GetKIIDs() )
1140 {
1141 KIID_PATH base = component->GetPath();
1142 base.push_back( uuid );
1143
1144 if( footprint->GetPath() == base )
1145 {
1146 match = true;
1147 break;
1148 }
1149 }
1150 }
1151 else
1152 {
1153 match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
1154 }
1155
1156 if( match )
1157 {
1158 FOOTPRINT* tmp = footprint;
1159
1160 if( m_replaceFootprints && component->GetFPID() != footprint->GetFPID() )
1161 tmp = replaceFootprint( aNetlist, footprint, component );
1162
1163 if( tmp )
1164 {
1165 footprintMap[ component ] = tmp;
1166
1167 updateFootprintParameters( tmp, component );
1168 updateComponentPadConnections( tmp, component );
1169 }
1170
1171 matchCount++;
1172 }
1173
1174 if( footprint == lastPreexistingFootprint )
1175 {
1176 // No sense going through the newly-created footprints: end of loop
1177 break;
1178 }
1179 }
1180
1181 if( matchCount == 0 )
1182 {
1183 FOOTPRINT* footprint = addNewFootprint( component );
1184
1185 if( footprint )
1186 {
1187 footprintMap[ component ] = footprint;
1188
1189 updateFootprintParameters( footprint, component );
1190 updateComponentPadConnections( footprint, component );
1191 }
1192 }
1193 else if( matchCount > 1 )
1194 {
1195 msg.Printf( _( "Multiple footprints found for '%s'." ), component->GetReference() );
1197 m_errorCount++;
1198 }
1199 }
1200
1201 updateCopperZoneNets( aNetlist );
1202
1203 // Finally go through the board footprints and update all those that *don't* have matching
1204 // component entries.
1205 //
1206 for( FOOTPRINT* footprint : m_board->Footprints() )
1207 {
1208 bool matched = false;
1209 bool doDelete = m_deleteUnusedFootprints;
1210
1211 if( ( footprint->GetAttributes() & FP_BOARD_ONLY ) > 0 )
1212 doDelete = false;
1213
1215 component = aNetlist.GetComponentByPath( footprint->GetPath() );
1216 else
1217 component = aNetlist.GetComponentByReference( footprint->GetReference() );
1218
1219 if( component && component->GetProperties().count( wxT( "exclude_from_board" ) ) == 0 )
1220 matched = true;
1221
1222 if( doDelete && !matched && footprint->IsLocked() )
1223 {
1224 if( m_isDryRun )
1225 {
1226 msg.Printf( _( "Cannot remove unused footprint %s (locked)." ),
1227 footprint->GetReference() );
1228 }
1229 else
1230 {
1231 msg.Printf( _( "Could not remove unused footprint %s (locked)." ),
1232 footprint->GetReference() );
1233 }
1234
1236 m_errorCount++;
1237 doDelete = false;
1238 }
1239
1240 if( doDelete && !matched )
1241 {
1242 if( m_isDryRun )
1243 {
1244 msg.Printf( _( "Remove unused footprint %s." ), footprint->GetReference() );
1245 }
1246 else
1247 {
1248 m_commit.Remove( footprint );
1249 msg.Printf( _( "Removed unused footprint %s." ), footprint->GetReference() );
1250 }
1251
1253 }
1254 else if( !m_isDryRun )
1255 {
1256 if( !matched )
1257 footprint->SetPath( KIID_PATH() );
1258
1259 for( PAD* pad : footprint->Pads() )
1260 {
1261 if( pad->GetNet() )
1262 pad->GetNet()->SetIsCurrent( true );
1263 }
1264 }
1265 }
1266
1267 if( !m_isDryRun )
1268 {
1270 testConnectivity( aNetlist, footprintMap );
1271
1272 for( NETINFO_ITEM* net : m_board->GetNetInfo() )
1273 {
1274 if( !net->IsCurrent() )
1275 {
1276 msg.Printf( _( "Removed unused net %s." ), net->GetNetname() );
1278 }
1279 }
1280
1282
1283 // When new footprints are added, the automatic zone refill is disabled because:
1284 // * it creates crashes when calculating dynamic ratsnests if auto refill is enabled.
1285 // (the auto refills rebuild the connectivity with incomplete data)
1286 // * it is useless because zones will be refilled after placing new footprints
1287 m_commit.Push( _( "Update netlist" ), m_newFootprintsCount ? ZONE_FILL_OP : 0 );
1288
1290
1291 // Although m_commit will probably also set this, it's not guaranteed, and we need to make
1292 // sure any modification to netclasses gets persisted to project settings through a save.
1293 m_frame->OnModify();
1294 }
1295
1296 if( m_isDryRun )
1297 {
1298 for( const std::pair<const wxString, NETINFO_ITEM*>& addedNet : m_addedNets )
1299 delete addedNet.second;
1300
1301 m_addedNets.clear();
1302 }
1303
1304 // Update the ratsnest
1307
1308 msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
1310
1311 return true;
1312}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
#define ZONE_FILL_OP
Definition: board_commit.h:43
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:259
std::map< PAD *, wxString > m_padNets
void cacheNetname(PAD *aPad, const wxString &aNetname)
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
wxString getNetname(PAD *aPad)
wxString getPinFunction(PAD *aPad)
std::vector< FOOTPRINT * > m_addedFootprints
std::map< wxString, wxString > m_oldToNewNets
bool updateFootprintParameters(FOOTPRINT *aPcbFootprint, COMPONENT *aNetlistComponent)
std::map< wxString, NETINFO_ITEM * > m_addedNets
bool testConnectivity(NETLIST &aNetlist, std::map< COMPONENT *, FOOTPRINT * > &aFootprintMap)
bool updateCopperZoneNets(NETLIST &aNetlist)
void cachePinFunction(PAD *aPad, const wxString &aPinFunction)
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
bool updateComponentPadConnections(FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
std::map< PAD *, wxString > m_padPinFunctions
std::map< ZONE *, std::vector< PAD * > > m_zoneConnectionsCache
FOOTPRINT * replaceFootprint(NETLIST &aNetlist, FOOTPRINT *aFootprint, COMPONENT *aNewComponent)
FOOTPRINT * addNewFootprint(COMPONENT *aComponent)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:276
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:827
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:885
const PAGE_INFO & GetPageSettings() const
Definition: board.h:649
ZONES & Zones()
Definition: board.h:324
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1642
bool BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:182
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1775
FOOTPRINTS & Footprints()
Definition: board.h:318
void RemoveUnusedNets(BOARD_COMMIT *aCommit)
Definition: board.h:832
TRACKS & Tracks()
Definition: board.h:315
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:536
bool IsEmpty() const
Definition: board.h:372
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:441
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetWidth() const
Definition: box2.h:188
Vec Centre() const
Definition: box2.h:71
coord_type GetBottom() const
Definition: box2.h:191
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
Definition: commit.h:90
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
COMMIT & Modified(EDA_ITEM *aItem, EDA_ITEM *aCopy, BASE_SCREEN *aScreen=nullptr)
Definition: commit.h:110
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:78
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition: commit.cpp:128
Used to store the component pin name to net name (and pin function) associations stored in a netlist.
Definition: pcb_netlist.h:45
const wxString & GetNetName() const
Definition: pcb_netlist.h:59
bool IsValid() const
Definition: pcb_netlist.h:63
const wxString & GetPinFunction() const
Definition: pcb_netlist.h:60
const wxString & GetPinName() const
Definition: pcb_netlist.h:58
const wxString & GetPinType() const
Definition: pcb_netlist.h:61
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:86
const COMPONENT_NET & GetNet(unsigned aIndex) const
Definition: pcb_netlist.h:112
const KIID_PATH & GetPath() const
Definition: pcb_netlist.h:150
const wxString & GetReference() const
Definition: pcb_netlist.h:127
const wxString & GetValue() const
Definition: pcb_netlist.h:130
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
Definition: pcb_netlist.h:136
const std::map< wxString, wxString > & GetProperties() const
Definition: pcb_netlist.h:142
const std::vector< KIID > & GetKIIDs() const
Definition: pcb_netlist.h:152
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:145
unsigned GetNetCount() const
Definition: pcb_netlist.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:229
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:1997
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: footprint.h:674
EDA_ANGLE GetOrientation() const
Definition: footprint.h:209
bool HasFieldByName(const wxString &aFieldName) const
Definition: footprint.cpp:283
PCB_FIELD * GetFieldByName(const wxString &aFieldName)
Return a field in this symbol.
Definition: footprint.cpp:294
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:336
wxString GetSheetname() const
Definition: footprint.h:245
void SetPath(const KIID_PATH &aPath)
Definition: footprint.h:243
void SetFilters(const wxString &aFilters)
Definition: footprint.h:252
PCB_FIELD & Footprint()
Definition: footprint.h:594
void SetAttributes(int aAttributes)
Definition: footprint.h:278
void SetSheetfile(const wxString &aSheetfile)
Definition: footprint.h:249
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:1695
int GetAttributes() const
Definition: footprint.h:277
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:218
wxString GetSheetfile() const
Definition: footprint.h:248
PADS & Pads()
Definition: footprint.h:188
const LIB_ID & GetFPID() const
Definition: footprint.h:230
void SetReference(const wxString &aReference)
Definition: footprint.h:562
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:321
void SetValue(const wxString &aValue)
Definition: footprint.h:583
void RemoveField(const wxString &aFieldName)
Remove a user field from the footprint.
Definition: footprint.cpp:345
wxString GetFilters() const
Definition: footprint.h:251
void SetSheetname(const wxString &aSheetname)
Definition: footprint.h:246
const wxString & GetValue() const
Definition: footprint.h:578
const wxString & GetReference() const
Definition: footprint.h:556
const KIID_PATH & GetPath() const
Definition: footprint.h:242
VECTOR2I GetPosition() const override
Definition: footprint.h:206
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1496
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition: pcb_view.cpp:59
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition: pcb_view.cpp:68
wxString AsString() const
Definition: kiid.cpp:362
Definition: kiid.h:49
bool empty() const
Definition: lib_id.h:193
UTF8 Format() const
Definition: lib_id.cpp:118
Handle the data for a net.
Definition: netinfo.h:56
void SetIsCurrent(bool isCurrent)
Definition: netinfo.h:152
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:370
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
Definition: pcb_netlist.h:223
unsigned GetCount() const
Definition: pcb_netlist.h:244
COMPONENT * GetComponentByPath(const KIID_PATH &aPath)
Return a COMPONENT by aPath.
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
Definition: pcb_netlist.h:252
static REPORTER & GetInstance()
Definition: reporter.cpp:119
Definition: pad.h:59
const wxString & GetPinFunction() const
Definition: pad.h:142
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:170
DISPLAY_OPTIONS m_Display
PCBNEW_SETTINGS * GetPcbNewSettings() const
FOOTPRINT * LoadFootprint(const LIB_ID &aFootprintId)
Attempt to load aFootprintId from the footprint library table.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
The main frame for Pcbnew.
void OnModify() override
Must be called after a board change to set the modified flag.
void ExchangeFootprint(FOOTPRINT *aExisting, FOOTPRINT *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool reset3DModels=true, bool *aUpdated=nullptr)
Replace aExisting footprint by aNew footprint using the Existing footprint settings (position,...
void SetName(const wxString &aName)
Definition: pcb_field.h:104
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
Definition: pcb_text.cpp:256
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:84
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_text.cpp:323
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:99
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString wx_str() const
Definition: utf8.cpp:45
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
The common library.
#define _(s)
@ FP_DNP
Definition: footprint.h:80
@ FP_BOARD_ONLY
Definition: footprint.h:76
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:75
@ FP_JUST_ADDED
Definition: footprint.h:77
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_Fab
Definition: layer_ids.h:121
@ F_Cu
Definition: layer_ids.h:65
@ B_Fab
Definition: layer_ids.h:120
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
wxString UnescapeString(const wxString &aSource)
const double IU_PER_MILS
Definition: base_units.h:78
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
wxString GetCanonicalFieldName(int idx)
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:95