KiCad PCB EDA Suite
Loading...
Searching...
No Matches
lib_symbol.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) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 2022 CERN
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <font/outline_font.h>
24#include <sch_draw_panel.h>
25#include <plotters/plotter.h>
26#include <sch_screen.h>
27#include <template_fieldnames.h>
28#include <transform.h>
30#include <sch_pin.h>
31#include <sch_shape.h>
32#include <trace_helpers.h>
33#include <common.h>
35
36// TODO(JE) remove m_library; shouldn't be needed with legacy remapping
38
39#include <algorithm>
40#include <memory>
41#include <unordered_map>
42#include <unordered_set>
43#include <advanced_config.h>
44#include <properties/property.h>
46
47
55static std::shared_ptr<LIB_SYMBOL> GetSafeRootSymbol( const LIB_SYMBOL* aSymbol, const char* aCallerName )
56{
57 std::set<const LIB_SYMBOL*> visited;
58 visited.insert( aSymbol );
59
60 std::shared_ptr<LIB_SYMBOL> current = aSymbol->SharedPtr();
61 std::shared_ptr<LIB_SYMBOL> parent = aSymbol->GetParent().lock();
62
63 while( parent )
64 {
65 if( visited.count( parent.get() ) )
66 {
67 // Build chain description for logging
68 wxString chain = aSymbol->GetName();
69
70 for( const LIB_SYMBOL* sym : visited )
71 {
72 if( sym != aSymbol )
73 chain += wxT( " -> " ) + sym->GetName();
74 }
75
76 chain += wxT( " -> " ) + parent->GetName() + wxT( " (CYCLE)" );
77
78 wxLogTrace( traceSymbolInheritance,
79 wxT( "%s: Circular inheritance detected in symbol '%s' (lib: %s). Chain: %s" ),
80 aCallerName,
81 aSymbol->GetName(),
82 aSymbol->GetLibId().GetLibNickname().wx_str(),
83 chain );
84
85 // Return current (last valid symbol before cycle)
86 return current;
87 }
88
89 visited.insert( parent.get() );
90 current = parent;
91 parent = parent->GetParent().lock();
92 }
93
94 return current;
95}
96
97
98wxString LIB_SYMBOL::GetShownDescription( int aDepth ) const
99{
101}
102
104{
105 wxString shownText = GetDescriptionField().GetShownText( false, 0 );
106
107 if( shownText.IsEmpty() && IsDerived() )
108 {
109 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
110
111 if( root.get() != this )
112 shownText = root->GetDescriptionField().GetShownText( false, 0 );
113 }
114
115 m_shownDescriptionCache = shownText;
116}
117
118
119void LIB_SYMBOL::SetDescription( const wxString& aDescription )
120{
121 GetDescriptionField().SetText( aDescription );
124}
125
126
127void LIB_SYMBOL::SetKeyWords( const wxString& aKeyWords )
128{
129 m_keyWords = aKeyWords;
131}
132
133
134wxString LIB_SYMBOL::GetShownKeyWords( int aDepth ) const
135{
136 wxString text = GetKeyWords();
137
138 std::function<bool( wxString* )> libSymbolResolver = [&]( wxString* token ) -> bool
139 {
140 return ResolveTextVar( token, aDepth + 1 );
141 };
142
143 text = ResolveTextVars( text, &libSymbolResolver, aDepth );
144
145 return text;
146}
147
148
155
156
158{
159 m_searchTermsCache.clear();
160 m_searchTermsCache.reserve( 6 );
161
162 // Order matters, see SEARCH_TERM_CACHE_INDEX
163 m_searchTermsCache.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) );
164 m_searchTermsCache.emplace_back( SEARCH_TERM( GetName(), 8, true ) );
165 m_searchTermsCache.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16, true ) );
166
167 wxStringTokenizer keywordTokenizer( GetShownKeyWords(), " \t\r\n", wxTOKEN_STRTOK );
168
169 while( keywordTokenizer.HasMoreTokens() )
170 m_searchTermsCache.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) );
171
172 // Also include keywords as one long string, just in case
173 m_searchTermsCache.emplace_back( SEARCH_TERM( GetShownKeyWords(), 1 ) );
174 m_searchTermsCache.emplace_back( SEARCH_TERM( GetShownDescription(), 1 ) );
175
176 wxString footprint = GetFootprint();
177
178 if( !footprint.IsEmpty() )
179 m_searchTermsCache.emplace_back( SEARCH_TERM( footprint, 1 ) );
180}
181
182
183void LIB_SYMBOL::GetChooserFields( std::map<wxString, wxString>& aColumnMap )
184{
185 aColumnMap = m_chooserFieldsCache;
186}
187
188
190{
191 m_chooserFieldsCache.clear();
192
193 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
194 {
195 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
196
197 if( field->ShowInChooser() )
198 m_chooserFieldsCache[field->GetName()] = field->EDA_TEXT::GetShownText( false );
199 }
200
201 // If the user has a field named "Keywords", then prefer that. Otherwise add the KiCad
202 // keywords.
203 const wxString localizedKeywords = _( "Keywords" );
204
205 if( !m_chooserFieldsCache.contains( localizedKeywords ) )
206 m_chooserFieldsCache[localizedKeywords] = GetShownKeyWords();
207}
208
209
210bool operator<( const LIB_SYMBOL& aItem1, const LIB_SYMBOL& aItem2 )
211{
212 return aItem1.GetName() < aItem2.GetName();
213}
214
215
218{
219 void operator()( void const* ) const {}
220};
221
222
223LIB_SYMBOL::LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent, LEGACY_SYMBOL_LIB* aLibrary ) :
225 m_me( this, null_deleter() )
226{
227 m_lastModDate = 0;
228 m_unitCount = 1;
229 m_demorgan = false;
232 m_unitsLocked = false;
234 m_library = nullptr;
235
236 auto addField = [&]( FIELD_T id, bool visible )
237 {
238 SCH_FIELD* field = new SCH_FIELD( this, id );
239 field->SetVisible( visible );
240 m_drawings[SCH_FIELD_T].push_back( field );
241 };
242
243 // construct only the mandatory fields
244 addField( FIELD_T::REFERENCE, true );
245 addField( FIELD_T::VALUE, true );
246 addField( FIELD_T::FOOTPRINT, false );
247 addField( FIELD_T::DATASHEET, false );
248 addField( FIELD_T::DESCRIPTION, false );
249
250 SetName( aName );
251 SetParent( aParent );
252 SetLib( aLibrary );
257}
258
259
260LIB_SYMBOL::LIB_SYMBOL( const LIB_SYMBOL& aSymbol, LEGACY_SYMBOL_LIB* aLibrary, bool aCopyEmbeddedFiles ) :
261 SYMBOL( aSymbol ),
262 EMBEDDED_FILES( aSymbol, aCopyEmbeddedFiles ),
263 m_me( this, null_deleter() )
264{
265 m_library = aLibrary;
266 m_name = aSymbol.m_name;
267 m_fpFilters = wxArrayString( aSymbol.m_fpFilters );
268 m_pinMaps = aSymbol.m_pinMaps;
270 m_unitCount = aSymbol.m_unitCount;
271 m_demorgan = aSymbol.m_demorgan;
274 m_options = aSymbol.m_options;
275 m_libId = aSymbol.m_libId;
276 m_keyWords = aSymbol.m_keyWords;
277
280
283
285
286 for( const SCH_ITEM& oldItem : aSymbol.m_drawings )
287 {
288 if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
289 continue;
290
291 try
292 {
293 SCH_ITEM* newItem = (SCH_ITEM*) oldItem.Clone();
294 newItem->ClearSelected();
295 newItem->SetParent( this );
296 m_drawings.push_back( newItem );
297 }
298 catch( ... )
299 {
300 wxFAIL_MSG( "Failed to clone SCH_ITEM." );
301 return;
302 }
303 }
304
305 SetParent( aSymbol.m_parent.lock().get() );
310}
311
312
314{
315 if( &aSymbol == this )
316 return aSymbol;
317
318 SYMBOL::operator=( aSymbol );
319
320 m_library = aSymbol.m_library;
321 m_name = aSymbol.m_name;
322 m_fpFilters = wxArrayString( aSymbol.m_fpFilters );
323 m_pinMaps = aSymbol.m_pinMaps;
325 m_unitCount = aSymbol.m_unitCount;
326 m_demorgan = aSymbol.m_demorgan;
329 m_options = aSymbol.m_options;
330 m_libId = aSymbol.m_libId;
331 m_keyWords = aSymbol.m_keyWords;
332
335
338
339 m_drawings.clear();
340
341 for( const SCH_ITEM& oldItem : aSymbol.m_drawings )
342 {
343 if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
344 continue;
345
346 SCH_ITEM* newItem = (SCH_ITEM*) oldItem.Clone();
347 newItem->SetParent( this );
348 m_drawings.push_back( newItem );
349 }
350
351 m_drawings.sort();
352
353 SetParent( aSymbol.m_parent.lock().get() );
354
355 EMBEDDED_FILES::operator=( aSymbol );
356
361
362 return *this;
363}
364
365
372{
373 static LIB_SYMBOL* symbol;
374
375 if( !symbol )
376 {
377 symbol = new LIB_SYMBOL( wxEmptyString );
378
380
381 square->SetPosition( VECTOR2I( schIUScale.MilsToIU( -200 ), schIUScale.MilsToIU( 200 ) ) );
382 square->SetEnd( VECTOR2I( schIUScale.MilsToIU( 200 ), schIUScale.MilsToIU( -200 ) ) );
383 symbol->AddDrawItem( square );
384
385 SCH_TEXT* text = new SCH_TEXT( { 0, 0 }, wxT( "??" ), LAYER_DEVICE );
386
387 text->SetTextSize( VECTOR2I( schIUScale.MilsToIU( 150 ), schIUScale.MilsToIU( 150 ) ) );
388 symbol->AddDrawItem( text );
389 }
390
391 return symbol;
392}
393
394
396{
397 unsigned depth = 0;
398 std::set<const LIB_SYMBOL*> visited;
399 visited.insert( this );
400
401 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
402
403 while( parent )
404 {
405 // Cycle detected - parent chain points back to an already visited symbol
406 if( visited.count( parent.get() ) )
407 {
408 wxLogTrace( traceSymbolInheritance,
409 wxT( "GetInheritanceDepth: Circular inheritance detected in symbol '%s' "
410 "(lib: %s)" ),
411 m_name, m_libId.GetLibNickname().wx_str() );
412 break;
413 }
414
415 visited.insert( parent.get() );
416 depth++;
417 parent = parent->m_parent.lock();
418 }
419
420 return depth;
421}
422
423
424std::shared_ptr<LIB_SYMBOL> LIB_SYMBOL::GetRootSymbol() const
425{
426 std::set<const LIB_SYMBOL*> visited;
427 visited.insert( this );
428
429 std::shared_ptr<LIB_SYMBOL> current = m_me;
430 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
431
432 while( parent )
433 {
434 // Cycle detected - parent chain points back to an already visited symbol
435 if( visited.count( parent.get() ) )
436 {
437 wxLogTrace( traceSymbolInheritance,
438 wxT( "GetRootSymbol: Circular inheritance detected in symbol '%s' "
439 "(lib: %s)" ),
440 m_name, m_libId.GetLibNickname().wx_str() );
441 break;
442 }
443
444 visited.insert( parent.get() );
445 current = parent;
446 parent = parent->m_parent.lock();
447 }
448
449 return current;
450}
451
452
453wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
454{
455 if( m_unitDisplayNames.contains( aUnit ) )
456 return m_unitDisplayNames.at( aUnit );
457 else if( aLabel )
458 return wxString::Format( _( "Unit %s" ), LIB_SYMBOL::LetterSubReference( aUnit, 'A' ) );
459 else
460 return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
461}
462
463
464wxString LIB_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
465{
467 {
468 if( aBodyStyle == BODY_STYLE::DEMORGAN )
469 return aLabel ? _( "Alternate" ) : wxString( _HKI( "Alternate" ) );
470 else if( aBodyStyle == BODY_STYLE::BASE )
471 return aLabel ? _( "Standard" ) : wxString( _HKI( "Standard" ) );
472 }
473 else if( IsMultiBodyStyle() )
474 {
475 if( aBodyStyle <= (int) m_bodyStyleNames.size() )
476 return m_bodyStyleNames[aBodyStyle - 1];
477 }
478
479 return wxT( "?" );
480}
481
482
483void LIB_SYMBOL::SetName( const wxString& aName )
484{
485 m_name = aName;
486 m_libId.SetLibItemName( aName );
487
488 if( m_searchTermsCache.empty() )
490
493}
494
495
496void LIB_SYMBOL::SetLibId( const LIB_ID& aLibId )
497{
498 m_libId = aLibId;
499
500 if( m_searchTermsCache.empty() )
502
504}
505
506
508{
509 if( aParent )
510 {
511 // Prevent circular inheritance by checking if aParent is derived from this symbol
512 std::set<const LIB_SYMBOL*> visited;
513 visited.insert( this );
514
515 std::shared_ptr<LIB_SYMBOL> ancestor = aParent->SharedPtr();
516
517 while( ancestor )
518 {
519 if( visited.count( ancestor.get() ) )
520 {
521 wxLogTrace( traceSymbolInheritance,
522 wxT( "SetParent: Rejecting parent '%s' for symbol '%s' - would create "
523 "circular inheritance (lib: %s)" ),
524 aParent->GetName(), m_name, m_libId.GetLibNickname().wx_str() );
525
526 // Don't set the parent - it would create circular inheritance
527 return;
528 }
529
530 visited.insert( ancestor.get() );
531 ancestor = ancestor->m_parent.lock();
532 }
533
534 m_parent = aParent->SharedPtr();
535
536 // Keep the recorded parent name in sync so serialization never has to dereference the live
537 // parent pointer (which can dangle, see SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol).
538 m_parentName = aParent->GetName();
539 }
540 else
541 {
542 // Only drop the live pointer. The recorded parent name is left untouched so a derived
543 // symbol whose live parent has been lost can still be serialized by name.
544 m_parent.reset();
545 }
546}
547
548
550{
552 return wxEmptyString;
553
554 return GetFootprintField().GetShownText( false );
555}
556
557
558std::unique_ptr<LIB_SYMBOL> LIB_SYMBOL::Flatten() const
559{
560 std::unique_ptr<LIB_SYMBOL> retv;
561
562 if( IsDerived() )
563 {
564 // Build parent chain with cycle detection - collect from this symbol up to root
565 std::vector<const LIB_SYMBOL*> parentChain;
566 std::set<const LIB_SYMBOL*> visited;
567 visited.insert( this );
568
569 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
570
571 wxCHECK_MSG( parent, retv, wxString::Format( "Parent of derived symbol '%s' undefined", m_name ) );
572
573 while( parent )
574 {
575 // Cycle detected - parent chain points back to an already visited symbol
576 if( visited.count( parent.get() ) )
577 {
578 wxLogTrace( traceSymbolInheritance,
579 wxT( "Flatten: Circular inheritance detected in symbol '%s' (lib: %s)" ),
580 m_name, m_libId.GetLibNickname().wx_str() );
581 break;
582 }
583
584 visited.insert( parent.get() );
585 parentChain.push_back( parent.get() );
586 parent = parent->m_parent.lock();
587 }
588
589 // Start with the root (last in chain) and work down
590 if( !parentChain.empty() )
591 {
592 retv = std::make_unique<LIB_SYMBOL>( *parentChain.back() );
593
594 // Apply each derived symbol's overrides from root down (skip the root itself)
595 for( int i = static_cast<int>( parentChain.size() ) - 2; i >= 0; --i )
596 {
597 const LIB_SYMBOL* derived = parentChain[i];
598
599 // Overwrite parent's mandatory fields for fields which are defined in derived.
600 for( FIELD_T fieldId : MANDATORY_FIELDS )
601 {
602 if( !derived->GetField( fieldId )->GetText().IsEmpty() )
603 *retv->GetField( fieldId ) = *derived->GetField( fieldId );
604 }
605
606 // Grab all the rest of derived symbol fields.
607 for( const SCH_ITEM& item : derived->m_drawings[SCH_FIELD_T] )
608 {
609 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
610
611 if( field->IsMandatory() )
612 continue;
613
614 SCH_FIELD* newField = new SCH_FIELD( *field );
615 newField->SetParent( retv.get() );
616
617 SCH_FIELD* parentField = retv->GetField( field->GetName() );
618
619 if( !parentField )
620 {
621 retv->AddDrawItem( newField );
622 }
623 else
624 {
625 retv->RemoveDrawItem( parentField );
626 retv->AddDrawItem( newField );
627 }
628 }
629
630 if( !derived->m_keyWords.IsEmpty() )
631 retv->SetKeyWords( derived->m_keyWords );
632
633 if( !derived->m_fpFilters.IsEmpty() )
634 retv->SetFPFilters( derived->m_fpFilters );
635 }
636 }
637 else
638 {
639 // Cycle detected at immediate parent level - just copy this symbol
640 retv = std::make_unique<LIB_SYMBOL>( *this );
641 retv->m_parent.reset();
642 return retv;
643 }
644
645 // Now apply this symbol's overrides (the original "this" symbol)
646 retv->m_name = m_name;
647 retv->SetLibId( m_libId );
648
649 // Overwrite parent's mandatory fields for fields which are defined in this.
650 for( FIELD_T fieldId : MANDATORY_FIELDS )
651 {
652 if( !GetField( fieldId )->GetText().IsEmpty() )
653 *retv->GetField( fieldId ) = *GetField( fieldId );
654 }
655
656 // Grab all the rest of derived symbol fields.
657 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
658 {
659 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
660
661 // Mandatory fields were already resolved.
662 if( field->IsMandatory() )
663 continue;
664
665 SCH_FIELD* newField = new SCH_FIELD( *field );
666 newField->SetParent( retv.get() );
667
668 SCH_FIELD* parentField = retv->GetField( field->GetName() );
669
670 if( !parentField ) // Derived symbol field does not exist in parent symbol.
671 {
672 retv->AddDrawItem( newField );
673 }
674 else // Derived symbol field overrides the parent symbol field.
675 {
676 retv->RemoveDrawItem( parentField );
677 retv->AddDrawItem( newField );
678 }
679 }
680
681 // Use this symbol's keywords/filters if set, otherwise keep inherited ones
682 if( !m_keyWords.IsEmpty() )
683 retv->SetKeyWords( m_keyWords );
684
685 if( !m_fpFilters.IsEmpty() )
686 retv->SetFPFilters( m_fpFilters );
687
688 for( const auto& file : EmbeddedFileMap() )
689 {
691 retv->AddFile( newFile );
692 }
693
694 // Get excluded flags from the immediate parent (first in chain)
695 if( !parentChain.empty() )
696 {
697 retv->SetExcludedFromSim( parentChain.front()->GetExcludedFromSim() );
698 retv->SetExcludedFromBOM( parentChain.front()->GetExcludedFromBOM() );
699 retv->SetExcludedFromBoard( parentChain.front()->GetExcludedFromBoard() );
700 retv->SetExcludedFromPosFiles( parentChain.front()->GetExcludedFromPosFiles() );
701 }
702
703 // Pin maps and associated footprints inherit as a coupled bundle; copy the resolved
704 // effective bundle so the flattened symbol is self-contained.
705 retv->m_pinMaps = GetEffectivePinMaps();
706 retv->m_associatedFootprints = GetEffectiveAssociatedFootprints();
707
708 retv->m_parent.reset();
709 }
710 else
711 {
712 retv = std::make_unique<LIB_SYMBOL>( *this );
713 }
714
715 return retv;
716}
717
718
720{
721 m_library = aLibrary;
722
723 if( m_searchTermsCache.empty() )
725
727}
728
729
730const wxString LIB_SYMBOL::GetLibraryName() const
731{
732 if( m_library )
733 return m_library->GetName();
734
735 return m_libId.GetLibNickname();
736}
737
738
740{
741 if( IsDerived() )
742 {
743 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
744
745 if( root.get() != this )
746 return root->IsLocalPower();
747 }
748
750}
751
752
754{
755 if( IsDerived() )
756 {
757 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
758
759 if( root.get() != this )
760 {
761 root->SetLocalPower();
762 return;
763 }
764 }
765
767}
768
769
771{
772 if( IsDerived() )
773 {
774 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
775
776 if( root.get() != this )
777 return root->IsGlobalPower();
778 }
779
781}
782
783
785{
786 return IsLocalPower() || IsGlobalPower();
787}
788
789
791{
792 if( IsDerived() )
793 {
794 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
795
796 if( root.get() != this )
797 {
798 root->SetGlobalPower();
799 return;
800 }
801 }
802
804}
805
806
808{
809 if( IsDerived() )
810 {
811 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
812
813 if( root.get() != this )
814 return root->IsNormal();
815 }
816
817 return m_options == ENTRY_NORMAL;
818}
819
820
822{
823 if( IsDerived() )
824 {
825 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
826
827 if( root.get() != this )
828 {
829 root->SetNormal();
830 return;
831 }
832 }
833
835}
836
837
838wxString LIB_SYMBOL::LetterSubReference( int aUnit, wxChar aInitialLetter )
839{
840 // use letters as notation. To allow more than 26 units, the sub ref
841 // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
842 // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
843 int u;
844 wxString suffix;
845
846 do
847 {
848 u = ( aUnit - 1 ) % 26;
849 suffix = wxChar( aInitialLetter + u ) + suffix;
850 aUnit = ( aUnit - u ) / 26;
851 } while( aUnit > 0 );
852
853 return suffix;
854}
855
856
857bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const
858{
859 wxString footprint;
860
861 for( const SCH_ITEM& item : m_drawings )
862 {
863 if( item.Type() == SCH_FIELD_T )
864 {
865 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
866
867 if( field.GetId() == FIELD_T::FOOTPRINT )
868 footprint = field.GetShownText( nullptr, false, aDepth + 1 );
869
870 if( token->IsSameAs( field.GetCanonicalName().Upper() ) || token->IsSameAs( field.GetName(), false ) )
871 {
872 *token = field.GetShownText( nullptr, false, aDepth + 1 );
873 return true;
874 }
875 }
876 }
877
878 // Consider missing simulation fields as empty, not un-resolved
879 if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) || token->IsSameAs( wxT( "SIM.TYPE" ) )
880 || token->IsSameAs( wxT( "SIM.PINS" ) ) || token->IsSameAs( wxT( "SIM.PARAMS" ) )
881 || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) || token->IsSameAs( wxT( "SIM.NAME" ) ) )
882 {
883 *token = wxEmptyString;
884 return true;
885 }
886
887 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
888 {
889 wxArrayString parts = wxSplit( footprint, ':' );
890
891 if( parts.Count() > 0 )
892 *token = parts[0];
893 else
894 *token = wxEmptyString;
895
896 return true;
897 }
898 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
899 {
900 wxArrayString parts = wxSplit( footprint, ':' );
901
902 if( parts.Count() > 1 )
903 *token = parts[std::min( 1, (int) parts.size() - 1 )];
904 else
905 *token = wxEmptyString;
906
907 return true;
908 }
909 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
910 {
911 *token = m_libId.GetUniStringLibNickname();
912 return true;
913 }
914 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
915 {
916 *token = m_libId.GetUniStringLibItemName();
917 return true;
918 }
919 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
920 {
921 *token = GetShownDescription( aDepth + 1 );
922 return true;
923 }
924 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
925 {
926 *token = GetShownKeyWords( aDepth + 1 );
927 return true;
928 }
929 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
930 {
931 *token = this->GetExcludedFromBOM() ? _( "Excluded from BOM" ) : wxString( "" );
932 return true;
933 }
934 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
935 {
936 *token = this->GetExcludedFromBoard() ? _( "Excluded from board" ) : wxString( "" );
937 return true;
938 }
939 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
940 {
941 *token = this->GetExcludedFromSim() ? _( "Excluded from simulation" ) : wxString( "" );
942 return true;
943 }
944 else if( token->IsSameAs( wxT( "DNP" ) ) )
945 {
946 *token = this->GetDNP() ? _( "DNP" ) : wxString( "" );
947 return true;
948 }
949
950 return false;
951}
952
953
954void LIB_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle,
955 const VECTOR2I& aOffset, bool aDimmed )
956{
957 wxASSERT( aPlotter != nullptr );
958
959 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
960 COLOR4D color = renderSettings->GetLayerColor( LAYER_DEVICE );
961 COLOR4D bg = renderSettings->GetBackgroundColor();
962
963 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
964 bg = COLOR4D::WHITE;
965
966 if( color.m_text && Schematic() )
967 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
968
969 if( aDimmed )
970 {
971 color.Desaturate();
972 color = color.Mix( bg, 0.5f );
973 }
974
975 aPlotter->SetColor( color );
976
977 for( SCH_ITEM& item : m_drawings )
978 {
979 // Do not plot private items
980 if( item.IsPrivate() )
981 continue;
982
983 // LIB_FIELDs are not plotted here, because this plot function is used to plot schematic
984 // items which have their own SCH_FIELDs
985 if( item.Type() == SCH_FIELD_T )
986 continue;
987
988 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
989 continue;
990
991 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
992 continue;
993
994 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
995 }
996}
997
998
999void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
1000 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1001{
1002 wxASSERT( aPlotter != nullptr );
1003
1004 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1005 COLOR4D color = renderSettings->GetLayerColor( LAYER_FIELDS );
1006 COLOR4D bg = renderSettings->GetBackgroundColor();
1007
1008 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
1009 bg = COLOR4D::WHITE;
1010
1011 if( aDimmed )
1012 {
1013 color.Desaturate();
1014 color = color.Mix( bg, 0.5f );
1015 }
1016
1017 aPlotter->SetColor( color );
1018
1019 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1020 {
1021 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1022
1023 if( !renderSettings->m_ShowHiddenFields && !field.IsVisible() )
1024 continue;
1025
1026 // The reference is a special case: we should change the basic text
1027 // to add '?' and the part id
1028 wxString tmp = field.GetText();
1029
1030 field.SetText( field.GetFullText( aUnit ) );
1031 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1032
1033 field.SetText( tmp );
1034 }
1035}
1036
1037
1039{
1040 std::vector<SCH_SHAPE*> potential_top_items;
1041 std::vector<SCH_ITEM*> bottom_items;
1042
1043 for( SCH_ITEM& item : m_drawings )
1044 {
1045 if( item.Type() == SCH_SHAPE_T )
1046 {
1047 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
1048
1049 if( shape.GetFillMode() == FILL_T::FILLED_WITH_COLOR )
1050 potential_top_items.push_back( &shape );
1051 else
1052 bottom_items.push_back( &item );
1053 }
1054 else
1055 {
1056 bottom_items.push_back( &item );
1057 }
1058 }
1059
1060 std::sort( potential_top_items.begin(), potential_top_items.end(),
1061 []( SCH_ITEM* a, SCH_ITEM* b )
1062 {
1063 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
1064 } );
1065
1066 for( SCH_SHAPE* item : potential_top_items )
1067 {
1068 for( SCH_ITEM* bottom_item : bottom_items )
1069 {
1070 if( item->GetBoundingBox().Contains( bottom_item->GetBoundingBox() ) )
1071 {
1072 item->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1073 break;
1074 }
1075 }
1076 }
1077}
1078
1079
1081{
1082 wxASSERT( aItem != nullptr );
1083
1084 // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
1085 // omitted when saving to disk.
1086 if( aItem->Type() == SCH_FIELD_T )
1087 {
1088 if( static_cast<SCH_FIELD*>( aItem )->IsMandatory() )
1089 return;
1090 }
1091
1092 LIB_ITEMS& items = m_drawings[aItem->Type()];
1093
1094 for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
1095 {
1096 if( &*i == aItem )
1097 {
1098 items.erase( i );
1099 cachePinCount();
1101 break;
1102 }
1103 }
1104}
1105
1106
1107void LIB_SYMBOL::AddDrawItem( SCH_ITEM* aItem, bool aSort )
1108{
1109 if( aItem )
1110 {
1111 aItem->SetParent( this );
1112
1113 m_drawings.push_back( aItem );
1114
1115 if( aSort )
1116 m_drawings.sort();
1117
1118 cachePinCount();
1120 }
1121}
1122
1123
1124std::vector<const SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle ) const
1125{
1126 if( IsDerived() )
1127 {
1128 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1129
1130 if( root.get() != this )
1131 return const_cast<const LIB_SYMBOL*>( root.get() )->GetGraphicalPins( aUnit, aBodyStyle );
1132 }
1133
1134 std::vector<const SCH_PIN*> pins;
1135
1136 /* Notes:
1137 * when aUnit == 0: no unit filtering
1138 * when aBodyStyle == 0: no body style filtering
1139 * when m_unit == 0, the item is common to all units
1140 * when m_bodyStyle == 0, the item is common to all body styles
1141 */
1142
1143 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1144 {
1145 // Unit filtering:
1146 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1147 continue;
1148
1149 // Body style filtering:
1150 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1151 continue;
1152
1153 pins.push_back( static_cast<const SCH_PIN*>( &item ) );
1154 }
1155
1156 return pins;
1157}
1158
1159
1160std::vector<SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle )
1161{
1162 if( IsDerived() )
1163 {
1164 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1165
1166 if( root.get() != this )
1167 return root->GetGraphicalPins( aUnit, aBodyStyle );
1168 }
1169
1170 std::vector<SCH_PIN*> pins;
1171
1172 /* Notes:
1173 * when aUnit == 0: no unit filtering
1174 * when aBodyStyle == 0: no body style filtering
1175 * when m_unit == 0, the item is common to all units
1176 * when m_bodyStyle == 0, the item is common to all body styles
1177 */
1178
1179 for( SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1180 {
1181 // Unit filtering:
1182 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1183 continue;
1184
1185 // Body style filtering:
1186 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1187 continue;
1188
1189 pins.push_back( static_cast<SCH_PIN*>( &item ) );
1190 }
1191
1192 return pins;
1193}
1194
1195
1196std::vector<LIB_SYMBOL::UNIT_PIN_INFO> LIB_SYMBOL::GetUnitPinInfo() const
1197{
1198 std::vector<UNIT_PIN_INFO> units;
1199
1200 int unitCount = std::max( GetUnitCount(), 1 );
1201
1202 auto compareByPosition =
1203 []( const SCH_PIN* a, const SCH_PIN* b )
1204 {
1205 VECTOR2I positionA = a->GetPosition();
1206 VECTOR2I positionB = b->GetPosition();
1207
1208 if( positionA.x != positionB.x )
1209 return positionA.x < positionB.x;
1210
1211 return positionA.y < positionB.y;
1212 };
1213
1214 for( int unitIdx = 1; unitIdx <= unitCount; ++unitIdx )
1215 {
1216 UNIT_PIN_INFO unitInfo;
1217 unitInfo.m_unitName = GetUnitDisplayName( unitIdx, false );
1218
1219 std::vector<const SCH_PIN*> pinList = GetGraphicalPins( unitIdx, 0 );
1220
1221 std::sort( pinList.begin(), pinList.end(), compareByPosition );
1222
1223 std::unordered_set<wxString> seenNumbers;
1224
1225 for( const SCH_PIN* basePin : pinList )
1226 {
1227 bool stackedValid = false;
1228 std::vector<wxString> expandedNumbers = basePin->GetStackedPinNumbers( &stackedValid );
1229
1230 if( stackedValid && !expandedNumbers.empty() )
1231 {
1232 for( const wxString& number : expandedNumbers )
1233 {
1234 if( seenNumbers.insert( number ).second )
1235 unitInfo.m_pinNumbers.push_back( number );
1236 }
1237
1238 continue;
1239 }
1240
1241 const wxString& number = basePin->GetNumber();
1242
1243 if( !number.IsEmpty() && seenNumbers.insert( number ).second )
1244 unitInfo.m_pinNumbers.push_back( number );
1245 }
1246
1247 units.push_back( std::move( unitInfo ) );
1248 }
1249
1250 return units;
1251}
1252
1253
1254std::vector<LIB_SYMBOL::LOGICAL_PIN> LIB_SYMBOL::GetLogicalPins( int aUnit, int aBodyStyle ) const
1255{
1256 std::vector<LOGICAL_PIN> out;
1257
1258 for( const SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1259 {
1260 bool valid = false;
1261 std::vector<wxString> expanded = pin->GetStackedPinNumbers( &valid );
1262
1263 if( valid && !expanded.empty() )
1264 {
1265 for( const wxString& num : expanded )
1266 {
1267 out.push_back( LOGICAL_PIN{ pin, num } );
1268 wxLogTrace( traceStackedPins, "GetLogicalPins: base='%s' -> '%s'", pin->GetShownNumber(), num );
1269 }
1270 }
1271 else
1272 {
1273 out.push_back( LOGICAL_PIN{ pin, pin->GetShownNumber() } );
1274 wxLogTrace( traceStackedPins, "GetLogicalPins: base='%s' (no expansion)", pin->GetShownNumber() );
1275 }
1276 }
1277
1278 return out;
1279}
1280
1281
1283{
1284 return m_pinCountCache;
1285}
1286
1287
1289{
1290 m_pinCountCache = 0;
1291
1292 for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) )
1293 {
1294 int pinCount = pin->GetStackedPinCount();
1295 m_pinCountCache += pinCount;
1296 }
1297}
1298
1299
1300const SCH_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aBodyStyle ) const
1301{
1302 for( const SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1303 {
1304 if( aNumber == pin->GetNumber() )
1305 return pin;
1306 }
1307
1308 return nullptr;
1309}
1310
1311
1312std::vector<SCH_PIN*> LIB_SYMBOL::GetPinsByNumber( const wxString& aNumber, int aUnit, int aBodyStyle )
1313{
1314 std::vector<SCH_PIN*> pins;
1315
1316 for( SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1317 {
1318 if( aNumber == pin->GetNumber() )
1319 pins.push_back( pin );
1320 }
1321
1322 return pins;
1323}
1324
1325
1326bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames, bool aTestType,
1327 bool aTestOrientation, bool aTestLength ) const
1328{
1329 for( const SCH_PIN* pin : GetGraphicalPins() )
1330 {
1331 wxASSERT( pin );
1332 bool foundMatch = false;
1333
1334 for( const SCH_PIN* otherPin : aOtherPart.GetGraphicalPins() )
1335 {
1336 wxASSERT( otherPin );
1337
1338 // Same unit?
1339 if( pin->GetUnit() != otherPin->GetUnit() )
1340 continue;
1341
1342 // Same body stype?
1343 if( pin->GetBodyStyle() != otherPin->GetBodyStyle() )
1344 continue;
1345
1346 // Same position?
1347 if( pin->GetPosition() != otherPin->GetPosition() )
1348 continue;
1349
1350 // Same number?
1351 if( aTestNums && ( pin->GetNumber() != otherPin->GetNumber() ) )
1352 continue;
1353
1354 // Same name?
1355 if( aTestNames && ( pin->GetName() != otherPin->GetName() ) )
1356 continue;
1357
1358 // Same electrical type?
1359 if( aTestType && ( pin->GetType() != otherPin->GetType() ) )
1360 continue;
1361
1362 // Same orientation?
1363 if( aTestOrientation && ( pin->GetOrientation() != otherPin->GetOrientation() ) )
1364 continue;
1365
1366 // Same length?
1367 if( aTestLength && ( pin->GetLength() != otherPin->GetLength() ) )
1368 continue;
1369
1370 foundMatch = true;
1371 break; // Match found so search is complete.
1372 }
1373
1374 if( !foundMatch )
1375 {
1376 // This means there was not an identical (according to the arguments)
1377 // pin at the same position in the other symbol.
1378 return true;
1379 }
1380 }
1381
1382 // The loop never gave up, so no conflicts were found.
1383 return false;
1384}
1385
1386std::vector<SCH_PIN*> LIB_SYMBOL::GetPins() const
1387{
1388 // Back-compat shim: return graphical pins for all units/body styles, violating const
1389 return const_cast<LIB_SYMBOL*>( this )->GetGraphicalPins( 0, 0 );
1390}
1391
1392
1393const BOX2I LIB_SYMBOL::GetUnitBoundingBox( int aUnit, int aBodyStyle, bool aIgnoreHiddenFields,
1394 bool aIgnoreLabelsOnInvisiblePins ) const
1395{
1396 BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works
1397
1398 if( IsDerived() )
1399 {
1400 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1401
1402 if( root.get() != this )
1403 bBox = root->GetUnitBoundingBox( aUnit, aBodyStyle, aIgnoreHiddenFields, aIgnoreLabelsOnInvisiblePins );
1404 }
1405
1406 for( const SCH_ITEM& item : m_drawings )
1407 {
1408 if( item.m_unit > 0 && m_unitCount > 1 && aUnit > 0 && aUnit != item.m_unit )
1409 continue;
1410
1411 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1412 continue;
1413
1414 if( aIgnoreHiddenFields && item.Type() == SCH_FIELD_T )
1415 {
1416 if( !static_cast<const SCH_FIELD&>( item ).IsVisible() )
1417 continue;
1418 }
1419
1420 if( item.Type() == SCH_PIN_T && !aIgnoreLabelsOnInvisiblePins )
1421 {
1422 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1423 bBox.Merge( pin.GetBoundingBox( true, true, false ) );
1424 }
1425 else
1426 {
1427 bBox.Merge( item.GetBoundingBox() );
1428 }
1429 }
1430
1431 return bBox;
1432}
1433
1434
1435const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aIncludePins,
1436 bool aIncludePrivateItems ) const
1437{
1438 BOX2I bbox;
1439
1440 for( const SCH_ITEM& item : m_drawings )
1441 {
1442 if( item.m_unit > 0 && aUnit > 0 && aUnit != item.m_unit )
1443 continue;
1444
1445 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1446 continue;
1447
1448 if( item.IsPrivate() && !aIncludePrivateItems )
1449 continue;
1450
1451 if( item.Type() == SCH_FIELD_T )
1452 continue;
1453
1454 if( item.Type() == SCH_PIN_T )
1455 {
1456 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1457
1458 if( pin.IsVisible() )
1459 {
1460 // Note: the roots of the pins are always included for symbols that don't have
1461 // a well-defined body.
1462
1463 if( aIncludePins )
1464 bbox.Merge( pin.GetBoundingBox( false, false, false ) );
1465 else
1466 bbox.Merge( pin.GetPinRoot() );
1467 }
1468 }
1469 else
1470 {
1471 bbox.Merge( item.GetBoundingBox() );
1472 }
1473 }
1474
1475 return bbox;
1476}
1477
1478
1480{
1481 // cacheSearchTerms() reads the shown-description cache, so refresh it first.
1484 cachePinCount();
1486}
1487
1488
1495
1496
1498{
1499 AddDrawItem( aField );
1500}
1501
1502
1503void LIB_SYMBOL::SetFields( const std::vector<SCH_FIELD>& aFieldsList )
1504{
1506
1507 for( const SCH_FIELD& src : aFieldsList )
1508 {
1509 // drawings is a ptr_vector, new and copy an object on the heap.
1510 SCH_FIELD* field = new SCH_FIELD( src );
1511
1512 field->SetParent( this );
1513 m_drawings.push_back( field );
1514 }
1515
1516 m_drawings.sort();
1520}
1521
1522
1523void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aList, bool aVisibleOnly ) const
1524{
1525 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1526 {
1527 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1528
1529 if( aVisibleOnly )
1530 {
1531 if( !field->IsVisible() || field->GetText().IsEmpty() )
1532 continue;
1533 }
1534
1535 aList.push_back( const_cast<SCH_FIELD*>( field ) );
1536 }
1537
1538 std::sort( aList.begin(), aList.end(),
1539 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1540 {
1541 return lhs->GetOrdinal() < rhs->GetOrdinal();
1542 } );
1543}
1544
1545
1546void LIB_SYMBOL::CopyFields( std::vector<SCH_FIELD>& aList )
1547{
1548 std::vector<SCH_FIELD*> orderedFields;
1549
1550 GetFields( orderedFields );
1551
1552 for( SCH_FIELD* field : orderedFields )
1553 aList.emplace_back( *field );
1554}
1555
1556
1558{
1559 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
1560
1561 if( !parent )
1562 return;
1563
1564 std::unique_ptr<LIB_SYMBOL> flattenedParent = parent->Flatten();
1565
1566 auto selected =
1567 [&]( const wxString& aFieldName )
1568 {
1569 return aOptions.m_updateAllFields
1570 || aOptions.m_updateFields.count( aFieldName ) > 0;
1571 };
1572
1573 std::vector<SCH_FIELD> fields;
1574 std::vector<SCH_FIELD> result;
1575 CopyFields( fields );
1576
1577 for( SCH_FIELD& field : fields )
1578 {
1579 bool copy = true;
1580 SCH_FIELD* parentField = nullptr;
1581
1582 if( selected( field.GetName() ) )
1583 {
1584 if( field.IsMandatory() )
1585 parentField = flattenedParent->GetField( field.GetId() );
1586 else
1587 parentField = flattenedParent->GetField( field.GetName() );
1588
1589 if( parentField )
1590 {
1591 bool resetText = parentField->GetText().IsEmpty() ? aOptions.m_resetEmptyText
1592 : aOptions.m_resetText;
1593
1594 if( resetText )
1595 field.SetText( parentField->GetText() );
1596
1597 if( aOptions.m_resetVisibility )
1598 {
1599 field.SetVisible( parentField->IsVisible() );
1600 field.SetNameShown( parentField->IsNameShown() );
1601 }
1602
1603 if( aOptions.m_resetEffects )
1604 {
1605 // SetAttributes() also overwrites the visible bit and position, so save
1606 // and restore them here.
1607 bool visible = field.IsVisible();
1608 VECTOR2I pos = field.GetPosition();
1609
1610 field.SetAttributes( *parentField );
1611
1612 field.SetVisible( visible );
1613 field.SetPosition( pos );
1614 }
1615
1616 if( aOptions.m_resetPositions )
1617 field.SetTextPos( parentField->GetTextPos() );
1618 }
1619 else if( aOptions.m_removeExtraFields )
1620 {
1621 copy = false;
1622 }
1623 }
1624
1625 if( copy )
1626 result.emplace_back( std::move( field ) );
1627 }
1628
1629 std::vector<SCH_FIELD*> parentFields;
1630
1631 flattenedParent->GetFields( parentFields );
1632
1633 for( SCH_FIELD* parentField : parentFields )
1634 {
1635 if( !selected( parentField->GetName() ) )
1636 continue;
1637
1638 if( !GetField( parentField->GetName() ) )
1639 {
1640 result.emplace_back( this, FIELD_T::USER );
1641 SCH_FIELD* newField = &result.back();
1642
1643 newField->SetName( parentField->GetCanonicalName() );
1644 newField->SetText( parentField->GetText() );
1645 newField->SetAttributes( *parentField ); // Includes visible bit and position
1646 }
1647 }
1648
1649 SetFields( result );
1650}
1651
1652
1654{
1655 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id
1656
1657 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1658 ordinal = std::max( ordinal, static_cast<const SCH_FIELD*>( &item )->GetOrdinal() + 1 );
1659
1660 return ordinal;
1661}
1662
1663
1664const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const
1665{
1666 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1667 {
1668 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1669
1670 if( field->GetId() == aFieldType )
1671 return field;
1672 }
1673
1674 return nullptr;
1675}
1676
1677
1679{
1680 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1681 {
1682 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1683
1684 if( field->GetId() == aFieldType )
1685 return field;
1686 }
1687
1688 return nullptr;
1689}
1690
1691
1692const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const
1693{
1694 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1695 {
1696 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1697
1698 if( field.GetName() == aFieldName )
1699 return &field;
1700 }
1701
1702 return nullptr;
1703}
1704
1705
1706SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName )
1707{
1708 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1709 {
1710 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1711
1712 if( field.GetName() == aFieldName )
1713 return &field;
1714 }
1715
1716 return nullptr;
1717}
1718
1719
1721{
1722 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1723 {
1724 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1725
1726 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1727 return &field;
1728 }
1729
1730 return nullptr;
1731}
1732
1733
1734const SCH_FIELD* LIB_SYMBOL::FindFieldCaseInsensitive( const wxString& aFieldName ) const
1735{
1736 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1737 {
1738 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1739
1740 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1741 return &field;
1742 }
1743
1744 return nullptr;
1745}
1746
1747
1749{
1750 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
1751 wxASSERT( field != nullptr );
1752 return *field;
1753}
1754
1755
1757{
1758 const SCH_FIELD* field = GetField( FIELD_T::REFERENCE );
1759 wxASSERT( field != nullptr );
1760 return *field;
1761}
1762
1763
1765{
1766 const SCH_FIELD* field = GetField( FIELD_T::FOOTPRINT );
1767 wxASSERT( field != nullptr );
1768 return *field;
1769}
1770
1771
1773{
1774 const SCH_FIELD* field = GetField( FIELD_T::DATASHEET );
1775 wxASSERT( field != nullptr );
1776 return *field;
1777}
1778
1779
1781{
1782 const SCH_FIELD* field = GetField( FIELD_T::DESCRIPTION );
1783 wxASSERT( field != nullptr );
1784 return *field;
1785}
1786
1787
1789{
1790 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
1791
1792 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1793
1794 wxString prefix = refDesignator;
1795
1796 while( prefix.Length() )
1797 {
1798 wxUniCharRef last = prefix.Last();
1799
1800 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1801 prefix.RemoveLast();
1802 else
1803 break;
1804 }
1805
1806 // Avoid a prefix containing trailing/leading spaces
1807 prefix.Trim( true );
1808 prefix.Trim( false );
1809
1810 return prefix;
1811}
1812
1813
1814void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1815{
1816 for( SCH_ITEM& item : m_drawings )
1817 aFunction( &item );
1818}
1819
1820
1821void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1822{
1823 for( SCH_ITEM& item : m_drawings )
1824 item.Move( aOffset );
1825}
1826
1827
1828// Before V10 we didn't store the number of body styles in a symbol -- we just looked through all
1829// its drawings each time we wanted to know. This is now only used to set the count when a legacy
1830// symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count
1831// is always 1 or 2, and when 2 it is always a De Morgan pair.)
1833{
1834 for( const SCH_ITEM& item : m_drawings )
1835 {
1836 if( item.m_bodyStyle > BODY_STYLE::BASE )
1837 return true;
1838 }
1839
1840 if( IsDerived() )
1841 {
1842 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1843
1844 if( root.get() != this )
1845 return root->HasLegacyAlternateBodyStyle();
1846 }
1847
1848 return false;
1849}
1850
1851
1853{
1854 if( IsDerived() )
1855 {
1856 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1857
1858 if( root.get() != this )
1859 return root->GetMaxPinNumber();
1860 }
1861
1862 int maxPinNumber = 0;
1863
1864 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1865 {
1866 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1867 long currentPinNumber = 0;
1868
1869 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1870 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1871 }
1872
1873 return maxPinNumber;
1874}
1875
1876
1878{
1880
1881 for( SCH_ITEM& item : m_drawings )
1882 item.ClearTempFlags();
1883}
1884
1885
1887{
1889
1890 for( SCH_ITEM& item : m_drawings )
1891 item.ClearEditFlags();
1892}
1893
1894
1895SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint )
1896{
1897 for( SCH_ITEM& item : m_drawings )
1898 {
1899 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1900 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1901 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1902 {
1903 continue;
1904 }
1905
1906 if( item.HitTest( aPoint ) )
1907 return &item;
1908 }
1909
1910 return nullptr;
1911}
1912
1913
1914SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint,
1915 const TRANSFORM& aTransform )
1916{
1917 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1918 * VECTOR2I& pt ) to search items.
1919 * because this function uses DefaultTransform as orient/mirror matrix
1920 * we temporary copy aTransform in DefaultTransform
1921 */
1922 TRANSFORM transform = DefaultTransform;
1923 DefaultTransform = aTransform;
1924
1925 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1926
1927 // Restore matrix
1928 DefaultTransform = transform;
1929
1930 return item;
1931}
1932
1933
1934INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
1935{
1936 // The part itself is never inspected, only its children
1937 for( SCH_ITEM& item : m_drawings )
1938 {
1939 if( item.IsType( aScanTypes ) )
1940 {
1941 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1942 return INSPECT_RESULT::QUIT;
1943 }
1944 }
1945
1947}
1948
1949
1950void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1951{
1952 // A LIB_SYMBOL must always have at least one unit. Passing a value less than 1 would
1953 // erase the mandatory fields (which all have m_unit == 0), leaving the symbol in a
1954 // broken state that crashes later when callers dereference GetReferenceField() etc.
1955 wxCHECK_RET( aCount >= 1,
1956 wxString::Format( wxT( "Invalid unit count %d, ignoring." ), aCount ) );
1957
1958 if( m_unitCount == aCount )
1959 return;
1960
1961 if( aCount < m_unitCount )
1962 {
1963 // Iterate each drawing-type bucket and erase items that belong to units > aCount.
1964 for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
1965 {
1966 auto it = m_drawings.begin( type );
1967
1968 while( it != m_drawings.end( type ) )
1969 {
1970 if( it->m_unit > aCount )
1971 it = m_drawings.erase( it ); // returns next iterator
1972 else
1973 ++it;
1974 }
1975 }
1976 }
1977 else if( aDuplicateDrawItems )
1978 {
1979 int prevCount = m_unitCount;
1980
1981 // Temporary storage for new items, as adding new items directly to
1982 // m_drawings may cause the buffer reallocation which invalidates the
1983 // iterators
1984 std::vector<SCH_ITEM*> tmp;
1985
1986 for( SCH_ITEM& item : m_drawings )
1987 {
1988 if( item.m_unit != 1 )
1989 continue;
1990
1991 for( int j = prevCount + 1; j <= aCount; j++ )
1992 {
1993 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1994 newItem->m_unit = j;
1995 tmp.push_back( newItem );
1996 }
1997 }
1998
1999 for( SCH_ITEM* item : tmp )
2000 m_drawings.push_back( item );
2001 }
2002
2003 m_drawings.sort();
2004 m_unitCount = aCount;
2005}
2006
2007
2009{
2010 if( IsDerived() )
2011 {
2012 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
2013
2014 if( root.get() != this )
2015 return root->GetUnitCount();
2016 }
2017
2018 return m_unitCount;
2019}
2020
2021
2022void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins )
2023{
2024 int prevCount = GetBodyStyleCount();
2025
2026 if( prevCount == aCount )
2027 return;
2028
2029 // Duplicate items to create the converted shape
2030 if( prevCount < aCount )
2031 {
2032 if( aDuplicateDrawItems || aDuplicatePins )
2033 {
2034 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
2035
2036 for( SCH_ITEM& item : m_drawings )
2037 {
2038 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
2039 continue;
2040
2041 if( item.m_bodyStyle == 1 )
2042 {
2043 for( int j = prevCount + 1; j <= aCount; j++ )
2044 {
2045 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
2046 newItem->m_bodyStyle = j;
2047 tmp.push_back( newItem );
2048 }
2049 }
2050 }
2051
2052 // Transfer the new pins to the LIB_SYMBOL.
2053 for( SCH_ITEM* item : tmp )
2054 m_drawings.push_back( item );
2055 }
2056 }
2057 else
2058 {
2059 // Delete converted shape items because the converted shape does not exist
2061
2062 while( i != m_drawings.end() )
2063 {
2064 if( i->m_bodyStyle > aCount )
2065 i = m_drawings.erase( i );
2066 else
2067 ++i;
2068 }
2069 }
2070
2071 m_drawings.sort();
2072}
2073
2074
2075std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
2076{
2077 std::vector<SCH_ITEM*> unitItems;
2078
2079 for( SCH_ITEM& item : m_drawings )
2080 {
2081 if( item.Type() == SCH_FIELD_T )
2082 continue;
2083
2084 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
2085 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
2086 {
2087 unitItems.push_back( &item );
2088 }
2089 }
2090
2091 return unitItems;
2092}
2093
2094
2095std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
2096{
2097 std::vector<LIB_SYMBOL_UNIT> units;
2098
2099 for( SCH_ITEM& item : m_drawings )
2100 {
2101 if( item.Type() == SCH_FIELD_T )
2102 continue;
2103
2104 int unit = item.GetUnit();
2105 int bodyStyle = item.GetBodyStyle();
2106
2107 auto it = std::find_if( units.begin(), units.end(),
2108 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
2109 {
2110 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
2111 } );
2112
2113 if( it == units.end() )
2114 {
2115 LIB_SYMBOL_UNIT newUnit;
2116 newUnit.m_unit = item.GetUnit();
2117 newUnit.m_bodyStyle = item.GetBodyStyle();
2118 newUnit.m_items.push_back( &item );
2119 units.emplace_back( newUnit );
2120 }
2121 else
2122 {
2123 it->m_items.push_back( &item );
2124 }
2125 }
2126
2127 return units;
2128}
2129
2130
2131#define REPORT( msg ) \
2132 { \
2133 if( aReporter ) \
2134 aReporter->Report( msg ); \
2135 }
2136#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
2137
2138int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
2139{
2140 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
2141
2142 if( m_me == aRhs.m_me )
2143 return 0;
2144
2145 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2146 {
2147 if( int tmp = m_name.Cmp( aRhs.m_name ) )
2148 return tmp;
2149
2150 if( int tmp = m_libId.compare( aRhs.m_libId ) )
2151 return tmp;
2152
2153 if( m_parent.lock() < aRhs.m_parent.lock() )
2154 return -1;
2155
2156 if( m_parent.lock() > aRhs.m_parent.lock() )
2157 return 1;
2158 }
2159
2160 int retv = 0;
2161
2162 if( m_options != aRhs.m_options )
2163 {
2164 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
2165 REPORT( _( "Power flag differs." ) );
2166
2167 if( !aReporter )
2168 return retv;
2169 }
2170
2171 if( int tmp = m_unitCount - aRhs.m_unitCount )
2172 {
2173 retv = tmp;
2174 REPORT( _( "Unit count differs." ) );
2175
2176 if( !aReporter )
2177 return retv;
2178 }
2179
2180 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
2181
2182 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
2183 std::set<const SCH_FIELD*> aFields;
2184 std::set<const SCH_PIN*> aPins;
2185
2186 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
2187 {
2188 if( it->Type() == SCH_SHAPE_T )
2189 aShapes.insert( &( *it ) );
2190 else if( it->Type() == SCH_FIELD_T )
2191 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2192 else if( it->Type() == SCH_PIN_T )
2193 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2194 }
2195
2196 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
2197 std::set<const SCH_FIELD*> bFields;
2198 std::set<const SCH_PIN*> bPins;
2199
2200 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
2201 {
2202 if( it->Type() == SCH_SHAPE_T )
2203 bShapes.insert( &( *it ) );
2204 else if( it->Type() == SCH_FIELD_T )
2205 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2206 else if( it->Type() == SCH_PIN_T )
2207 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2208 }
2209
2210 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
2211 {
2212 retv = tmp;
2213 REPORT( _( "Graphic item count differs." ) );
2214
2215 if( !aReporter )
2216 return retv;
2217 }
2218 else
2219 {
2220 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
2221 {
2222 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
2223 {
2224 retv = tmp2;
2225 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
2226 ITEM_DESC( *bIt ) ) );
2227
2228 if( !aReporter )
2229 return retv;
2230 }
2231 }
2232 }
2233
2234 for( const SCH_PIN* aPin : aPins )
2235 {
2236 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
2237
2238 if( !bPin )
2239 {
2240 retv = 1;
2241 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
2242
2243 if( !aReporter )
2244 return retv;
2245 }
2246 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
2247 {
2248 retv = tmp;
2249 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
2250 ITEM_DESC( bPin ) ) );
2251
2252 if( !aReporter )
2253 return retv;
2254 }
2255 }
2256
2257 for( const SCH_PIN* bPin : bPins )
2258 {
2259 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
2260
2261 if( !aPin )
2262 {
2263 retv = 1;
2264 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
2265
2266 if( !aReporter )
2267 return retv;
2268 }
2269 }
2270
2271 for( const SCH_FIELD* aField : aFields )
2272 {
2273 const SCH_FIELD* bField = nullptr;
2274
2275 if( aField->IsMandatory() )
2276 bField = aRhs.GetField( aField->GetId() );
2277 else
2278 bField = aRhs.GetField( aField->GetName() );
2279
2280 if( !bField )
2281 {
2282 retv = 1;
2283 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
2284
2285 if( !aReporter )
2286 return retv;
2287 }
2288 else
2289 {
2290 int tmp = 0;
2291
2292 // For EQUALITY comparison, we need to compare field content directly
2293 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
2294 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
2295 {
2296 // Compare field text content
2297 tmp = aField->GetText().compare( bField->GetText() );
2298 }
2299
2300 if( tmp == 0 )
2301 {
2302 int fieldCompareFlags = aCompareFlags;
2303
2304 // SCH_FIELD::compare() injects SKIP_TST_POS for ERC, but it is bypassed
2305 // by the base-class call below, so mirror it here (issue 24657).
2306 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC )
2307 fieldCompareFlags |= SCH_ITEM::COMPARE_FLAGS::SKIP_TST_POS;
2308
2309 // Fall back to base class comparison for other properties
2310 tmp = aField->SCH_ITEM::compare( *bField, fieldCompareFlags );
2311 }
2312
2313 if( tmp != 0 )
2314 {
2315 retv = tmp;
2316 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
2317 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
2318
2319 if( !aReporter )
2320 return retv;
2321 }
2322 }
2323 }
2324
2325 for( const SCH_FIELD* bField : bFields )
2326 {
2327 const SCH_FIELD* aField = nullptr;
2328
2329 if( bField->IsMandatory() )
2330 aField = aRhs.GetField( bField->GetId() );
2331 else
2332 aField = aRhs.GetField( bField->GetName() );
2333
2334 if( !aField )
2335 {
2336 retv = 1;
2337 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
2338
2339 if( !aReporter )
2340 return retv;
2341 }
2342 }
2343
2344 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
2345 {
2346 retv = tmp;
2347 REPORT( _( "Footprint filter count differs." ) );
2348
2349 if( !aReporter )
2350 return retv;
2351 }
2352 else
2353 {
2354 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
2355 {
2356 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
2357 {
2358 retv = tmp2;
2359 REPORT( _( "Footprint filters differ." ) );
2360
2361 if( !aReporter )
2362 return retv;
2363 }
2364 }
2365 }
2366
2367 if( int tmp = static_cast<int>( m_pinMaps.GetAll().size() - aRhs.m_pinMaps.GetAll().size() ) )
2368 {
2369 retv = tmp;
2370 REPORT( _( "Pin map count differs." ) );
2371
2372 if( !aReporter )
2373 return retv;
2374 }
2375 else if( m_pinMaps != aRhs.m_pinMaps )
2376 {
2377 retv = 1;
2378 REPORT( _( "Pin maps differ." ) );
2379
2380 if( !aReporter )
2381 return retv;
2382 }
2383
2384 if( int tmp = static_cast<int>( m_associatedFootprints.size() - aRhs.m_associatedFootprints.size() ) )
2385 {
2386 retv = tmp;
2387 REPORT( _( "Associated footprint count differs." ) );
2388
2389 if( !aReporter )
2390 return retv;
2391 }
2393 {
2394 retv = 1;
2395 REPORT( _( "Associated footprints differ." ) );
2396
2397 if( !aReporter )
2398 return retv;
2399 }
2400
2401 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
2402 {
2403 retv = tmp;
2404 REPORT( _( "Symbol keywords differ." ) );
2405
2406 if( !aReporter )
2407 return retv;
2408 }
2409
2410 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
2411 {
2412 retv = tmp;
2413 REPORT( _( "Symbol pin name offsets differ." ) );
2414
2415 if( !aReporter )
2416 return retv;
2417 }
2418
2419 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2420 {
2421 if( m_showPinNames != aRhs.m_showPinNames )
2422 {
2423 retv = ( m_showPinNames ) ? 1 : -1;
2424 REPORT( _( "Show pin names settings differ." ) );
2425
2426 if( !aReporter )
2427 return retv;
2428 }
2429
2431 {
2432 retv = ( m_showPinNumbers ) ? 1 : -1;
2433 REPORT( _( "Show pin numbers settings differ." ) );
2434
2435 if( !aReporter )
2436 return retv;
2437 }
2438
2440 {
2441 retv = ( m_excludedFromSim ) ? -1 : 1;
2442 REPORT( _( "Exclude from simulation settings differ." ) );
2443
2444 if( !aReporter )
2445 return retv;
2446 }
2447
2449 {
2450 retv = ( m_excludedFromBOM ) ? -1 : 1;
2451 REPORT( _( "Exclude from bill of materials settings differ." ) );
2452
2453 if( !aReporter )
2454 return retv;
2455 }
2456
2458 {
2459 retv = ( m_excludedFromBoard ) ? -1 : 1;
2460 REPORT( _( "Exclude from board settings differ." ) );
2461
2462 if( !aReporter )
2463 return retv;
2464 }
2465
2467 {
2468 retv = ( m_excludedFromPosFiles ) ? -1 : 1;
2469 REPORT( _( "Exclude from position files settings differ." ) );
2470
2471 if( !aReporter )
2472 return retv;
2473 }
2474 }
2475
2476 if( !aReporter )
2477 {
2478 if( m_unitsLocked != aRhs.m_unitsLocked )
2479 return ( m_unitsLocked ) ? 1 : -1;
2480
2481 // Compare unit display names...
2483 return -1;
2484 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
2485 return 1;
2486
2487 // ... and body style names.
2489 return -1;
2490 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
2491 return 1;
2492 }
2493
2494 return retv;
2495}
2496
2497
2498int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2499{
2500 if( Type() != aOther.Type() )
2501 return Type() - aOther.Type();
2502
2503 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
2504
2505 return Compare( *tmp, aCompareFlags );
2506}
2507
2508
2509double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2510{
2511 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
2512
2513 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
2514 double similarity = 0.0;
2515 int totalItems = 0;
2516
2517 if( m_Uuid == aOther.m_Uuid )
2518 return 1.0;
2519
2520 for( const SCH_ITEM& item : m_drawings )
2521 {
2522 totalItems += 1;
2523 double max_similarity = 0.0;
2524
2525 for( const SCH_ITEM& otherItem : other.m_drawings )
2526 {
2527 double temp_similarity = item.Similarity( otherItem );
2528 max_similarity = std::max( max_similarity, temp_similarity );
2529
2530 if( max_similarity == 1.0 )
2531 break;
2532 }
2533
2534 similarity += max_similarity;
2535 }
2536
2537 for( const SCH_PIN* pin : GetGraphicalPins( 0, 0 ) )
2538 {
2539 totalItems += 1;
2540 double max_similarity = 0.0;
2541
2542 for( const SCH_PIN* otherPin : other.GetGraphicalPins( 0, 0 ) )
2543 {
2544 double temp_similarity = pin->Similarity( *otherPin );
2545 max_similarity = std::max( max_similarity, temp_similarity );
2546
2547 if( max_similarity == 1.0 )
2548 break;
2549 }
2550
2551 similarity += max_similarity;
2552 }
2553
2554 if( totalItems == 0 )
2555 similarity = 0.0;
2556 else
2557 similarity /= totalItems;
2558
2560 similarity *= 0.9;
2561
2563 similarity *= 0.9;
2564
2566 similarity *= 0.9;
2567
2569 similarity *= 0.9;
2570
2571 if( m_flags != other.m_flags )
2572 similarity *= 0.9;
2573
2574 if( m_unitCount != other.m_unitCount )
2575 similarity *= 0.5;
2576
2577 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
2578 similarity *= 0.5;
2579 else if( m_bodyStyleNames != other.m_bodyStyleNames )
2580 similarity *= 0.9;
2581
2582 if( m_pinNameOffset != other.m_pinNameOffset )
2583 similarity *= 0.9;
2584
2585 if( m_showPinNames != other.m_showPinNames )
2586 similarity *= 0.9;
2587
2588 if( m_showPinNumbers != other.m_showPinNumbers )
2589 similarity *= 0.9;
2590
2591 return similarity;
2592}
2593
2594
2596{
2597 return static_cast<EMBEDDED_FILES*>( this );
2598}
2599
2600
2602{
2603 return static_cast<const EMBEDDED_FILES*>( this );
2604}
2605
2606
2607void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2608{
2609 std::set<const LIB_SYMBOL*> visited;
2610 visited.insert( this );
2611
2612 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2613
2614 while( parent )
2615 {
2616 // Cycle detected - parent chain points back to an already visited symbol
2617 if( visited.count( parent.get() ) )
2618 {
2619 wxLogTrace( traceSymbolInheritance,
2620 wxT( "AppendParentEmbeddedFiles: Circular inheritance detected in "
2621 "symbol '%s' (lib: %s)" ),
2622 m_name, m_libId.GetLibNickname().wx_str() );
2623 break;
2624 }
2625
2626 visited.insert( parent.get() );
2627 aStack.push_back( parent->GetEmbeddedFiles() );
2628 parent = parent->GetParent().lock();
2629 }
2630}
2631
2632
2633std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2634{
2635 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2636
2637 std::set<KIFONT::OUTLINE_FONT*> fonts;
2638
2639 for( const SCH_ITEM& item : m_drawings )
2640 {
2641 if( item.Type() == SCH_TEXT_T )
2642 {
2643 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2644
2645 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2646 {
2647 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2648 auto permission = outline->GetEmbeddingPermission();
2649
2650 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2651 {
2652 fonts.insert( outline );
2653 }
2654 }
2655 }
2656 }
2657
2658 return fonts;
2659}
2660
2661
2663{
2664 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2665
2666 for( KIFONT::OUTLINE_FONT* font : fonts )
2667 {
2668 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2670 }
2671}
2672
2673
2674std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2675{
2676 for( const std::set<wxString>& group : m_jumperPinGroups )
2677 {
2678 if( group.contains( aPinNumber ) )
2679 return group;
2680 }
2681
2682 return std::nullopt;
2683}
2684
2685static struct LIB_SYMBOL_DESC
2686{
2688 {
2692
2693 const wxString groupFields = _HKI( "Fields" );
2694
2697 groupFields );
2700 groupFields );
2703 groupFields );
2706 groupFields );
2709 groupFields );
2710
2711 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2712
2713 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2716 groupSymbolDef );
2717 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2720 groupSymbolDef );
2721
2722 const wxString groupPinDisplay = _HKI( "Pin Display" );
2723
2724 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2726 groupPinDisplay );
2727 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2729 groupPinDisplay );
2730 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2733 groupPinDisplay );
2734 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2736 groupPinDisplay );
2737
2738 const wxString groupAttributes = _HKI( "Attributes" );
2739
2740 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2743 groupAttributes );
2744 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
2747 groupAttributes );
2748 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2751 groupAttributes );
2752 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
2755 groupAttributes );
2756
2757 const wxString groupUnits = _HKI( "Units and Body Styles" );
2758
2759 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2761 groupUnits );
2762 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2765 groupUnits );
2766
2767 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2768 {
2769 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2770 return symbol->IsMultiBodyStyle();
2771
2772 return false;
2773 };
2774
2777 groupUnits )
2778 .SetAvailableFunc( multiBodyStyle )
2780 []( INSPECTABLE* aItem )
2781 {
2782 wxPGChoices choices;
2783
2784 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2785 {
2786 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2787 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2788 }
2789
2790 return choices;
2791 } );
2792 }
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
double square(double x)
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:654
static const COLOR4D WHITE
Definition color4d.h:401
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:398
virtual void ClearEditFlags()
Definition eda_item.h:166
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
void ClearSelected()
Definition eda_item.h:147
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:542
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:143
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:89
EDA_ITEM_FLAGS GetFlags() const
Definition eda_item.h:155
virtual void ClearTempFlags()
Definition eda_item.h:179
FILL_T GetFillMode() const
Definition eda_shape.h:158
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:294
virtual bool IsVisible() const
Definition eda_text.h:208
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:428
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
bool IsEmpty() const
EMBEDDED_FILES & operator=(EMBEDDED_FILES &&other) noexcept
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
EMBEDDED_FILES()=default
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:38
Class OUTLINE_FONT implements outline font drawing.
EMBEDDING_PERMISSION GetEmbeddingPermission() const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:395
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:528
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition color4d.h:292
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
Object used to load, save, search, and otherwise manipulate symbol library files.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
UTF8 Format() const
Definition lib_id.cpp:132
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
Define a library symbol object.
Definition lib_symbol.h:114
LIB_ITEMS_CONTAINER m_drawings
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
SCH_FIELD & GetDescriptionField()
Return reference to the description field.
Definition lib_symbol.h:444
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:183
const BOX2I GetUnitBoundingBox(int aUnit, int aBodyStyle, bool aIgnoreHiddenFields=true, bool aIgnoreLabelsOnInvisiblePins=true) const
Get the bounding box for the symbol.
wxString GetKeyWords() const override
Definition lib_symbol.h:210
void SetGlobalPower()
std::weak_ptr< LIB_SYMBOL > & GetParent()
Definition lib_symbol.h:145
wxString GetBodyStyleProp() const override
Definition lib_symbol.h:574
LIBRENTRYOPTIONS m_options
Special symbol features such as POWER or NORMAL.
Definition lib_symbol.h:999
wxString GetRefProp() const
Definition lib_symbol.h:463
bool PinsConflictWith(const LIB_SYMBOL &aOtherSymbol, bool aTestNums, bool aTestNames, bool aTestType, bool aTestOrientation, bool aTestLength) const
Return true if this symbol's pins do not match another symbol's pins.
bool GetUnitsInterchangeableProp() const
Definition lib_symbol.h:564
wxString m_shownDescriptionCache
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
void GetFields(std::vector< SCH_FIELD * > &aList, bool aVisibleOnly=false) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
bool IsPower() const override
wxString GetPrefix()
wxString GetShownKeyWords(int aDepth=0) const override
const std::vector< ASSOCIATED_FOOTPRINT > & GetEffectiveAssociatedFootprints() const
Definition lib_symbol.h:290
SCH_FIELD & GetDatasheetField()
Return reference to the datasheet field.
Definition lib_symbol.h:440
void RefreshLibraryTreeCaches()
std::weak_ptr< LIB_SYMBOL > m_parent
Use for inherited symbols.
Definition lib_symbol.h:983
void SetExcludedFromBoardProp(bool aExclude)
Definition lib_symbol.h:610
void cachePinCount()
std::vector< struct LIB_SYMBOL_UNIT > GetUnitDrawItems()
Return a list of SCH_ITEM objects separated by unit and convert number.
std::map< int, wxString > m_unitDisplayNames
std::vector< std::set< wxString > > m_jumperPinGroups
A list of jumper pin groups, each of which is a set of pin numbers that should be jumpered together (...
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
void SetKeywordsProp(const wxString &aKeywords)
Definition lib_symbol.h:508
bool IsDerived() const
Definition lib_symbol.h:231
std::map< int, wxString > & GetUnitDisplayNames()
Definition lib_symbol.h:847
bool m_demorgan
True if there are two body styles: normal and De Morgan If false, the body style count is taken from ...
Definition lib_symbol.h:995
wxString GetFootprint() override
For items with footprint fields.
const wxString GetLibraryName() const
void SetFields(const std::vector< SCH_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
void SetExcludedFromPosFilesProp(bool aExclude)
Definition lib_symbol.h:616
void SetLib(LEGACY_SYMBOL_LIB *aLibrary)
bool GetPowerSymbolProp() const
Definition lib_symbol.h:513
bool IsMultiBodyStyle() const override
Definition lib_symbol.h:871
int GetMaxPinNumber() const
std::vector< SEARCH_TERM > m_searchTermsCache
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
SCH_FIELD * GetField(const wxString &aFieldName)
Find a field within this symbol matching aFieldName; return nullptr if not found.
SCH_FIELD & GetFootprintField()
Return reference to the footprint field.
Definition lib_symbol.h:436
int Compare(const LIB_SYMBOL &aRhs, int aCompareFlags=0, REPORTER *aReporter=nullptr) const
Comparison test that can be used for operators.
void FixupDrawItems()
This function finds the filled draw items that are covering up smaller draw items and replaces their ...
bool IsNormal() const override
wxString m_name
void SetUnitsInterchangeableProp(bool aInterchangeable)
Definition lib_symbol.h:569
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
LEGACY_SYMBOL_LIB * m_library
bool GetExcludedFromPosFilesProp() const
Definition lib_symbol.h:615
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
wxString m_keyWords
Search keywords.
SCH_ITEM * LocateDrawItem(int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I &aPoint)
Locate a draw object.
static wxString LetterSubReference(int aUnit, wxChar aInitialLetter)
double Similarity(const SCH_ITEM &aSymbol) const override
Return a measure of similarity between this symbol and aSymbol.
static LIB_SYMBOL * GetDummy()
Returns a dummy LIB_SYMBOL, used when one is missing in the schematic.
void PlotFields(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed)
Plot symbol fields.
wxString GetDatasheetProp() const
Definition lib_symbol.h:493
std::shared_ptr< LIB_SYMBOL > GetRootSymbol() const
Get the parent symbol that does not have another parent.
void SetRefProp(const wxString &aRef)
Definition lib_symbol.h:468
void SetParent(LIB_SYMBOL *aParent=nullptr)
std::vector< UNIT_PIN_INFO > GetUnitPinInfo() const
Return pin-number lists for each unit, ordered consistently for gate swapping.
wxString GetName() const override
Definition lib_symbol.h:176
void SetUnitCount(int aCount, bool aDuplicateDrawItems)
Set the units per symbol count.
void SetDescription(const wxString &aDescription)
Gets the Description field text value *‍/.
void cacheChooserFields()
std::shared_ptr< LIB_SYMBOL > m_me
Definition lib_symbol.h:982
wxString GetValueProp() const
Definition lib_symbol.h:473
bool GetExcludedFromBOMProp() const
Definition lib_symbol.h:595
void SetKeyWords(const wxString &aKeyWords)
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:428
bool IsLocalPower() const override
LIB_SYMBOL(const wxString &aName, LIB_SYMBOL *aParent=nullptr, LEGACY_SYMBOL_LIB *aLibrary=nullptr)
int GetUnitProp() const
Definition lib_symbol.h:554
void RemoveDrawItem(SCH_ITEM *aItem)
Remove draw aItem from list.
void GetChooserFields(std::map< wxString, wxString > &aColumnMap) override
Retrieves a key/value map of the fields on this item that should be exposed to the library browser/ch...
bool HasLegacyAlternateBodyStyle() const
Before V10 we didn't store the number of body styles in a symbol – we just looked through all its dra...
std::shared_ptr< LIB_SYMBOL > SharedPtr() const
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared.
Definition lib_symbol.h:123
bool GetPinNamesInsideProp() const
Definition lib_symbol.h:541
const std::vector< wxString > & GetBodyStyleNames() const
Definition lib_symbol.h:884
void SetBodyStyleProp(const wxString &aBodyStyle) override
Definition lib_symbol.h:579
int compare(const SCH_ITEM &aOther, int aCompareFlags=SCH_ITEM::COMPARE_FLAGS::EQUALITY) const override
The library symbol specific sort order is as follows:
timestamp_t m_lastModDate
Definition lib_symbol.h:989
void SetExcludedFromSimProp(bool aExclude)
Definition lib_symbol.h:590
bool GetExcludedFromBoardProp() const
Definition lib_symbol.h:605
std::optional< const std::set< wxString > > GetJumperPinGroup(const wxString &aPinNumber) const
Retrieves the jumper group containing the specified pin number, if one exists.
LIB_ID m_libId
Definition lib_symbol.h:987
void SetLocalPower()
std::vector< SCH_PIN * > GetPins() const override
void SetBodyStyleCount(int aCount, bool aDuplicateDrawItems, bool aDuplicatePins)
Set or clear the alternate body style (DeMorgan) for the symbol.
wxString GetLibNickname() const override
Sets the Description field text value.
Definition lib_symbol.h:189
void SetFootprintProp(const wxString &aFootprint)
Definition lib_symbol.h:488
std::vector< LOGICAL_PIN > GetLogicalPins(int aUnit, int aBodyStyle) const
Return all logical pins (expanded) filtered by unit/body.
bool HasDeMorganBodyStyles() const override
Definition lib_symbol.h:881
const LIB_SYMBOL & operator=(const LIB_SYMBOL &aSymbol)
bool m_unitsLocked
True if symbol has multiple units and changing one unit does not automatically change another unit.
Definition lib_symbol.h:992
wxArrayString m_fpFilters
List of suitable footprint names for the symbol (wild card names accepted).
void Move(const VECTOR2I &aOffset) override
Move the symbol aOffset.
const PIN_MAP_SET & GetEffectivePinMaps() const
Definition lib_symbol.h:275
void CopyFields(std::vector< SCH_FIELD > &aList)
Create a copy of the SCH_FIELDs, sorted in ordinal order.
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
bool GetExcludedFromSimProp() const
Definition lib_symbol.h:585
int GetBodyStyleCount() const override
Definition lib_symbol.h:873
void SetDatasheetProp(const wxString &aDatasheet)
Definition lib_symbol.h:498
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
EMBEDDED_FILES * GetEmbeddedFiles() override
void SetPowerSymbolProp(bool aIsPower)
Definition lib_symbol.h:518
void SetExcludedFromBOMProp(bool aExclude)
Definition lib_symbol.h:600
int m_unitCount
Number of units (parts) per package.
Definition lib_symbol.h:991
wxString GetShownDescription(int aDepth=0) const override
void SyncFieldsFromParent(const LIB_FIELD_SYNC_OPTIONS &aOptions)
Reconcile this derived symbol's fields with those of its (flattened) parent.
bool IsGlobalPower() const override
wxString GetBodyStyleDescription(int aBodyStyle, bool aLabel) const override
unsigned GetInheritanceDepth() const
Get the number of parents for this symbol.
int GetUnitCount() const override
PIN_MAP_SET m_pinMaps
Named pin-to-pad maps owned by this symbol (issue #2282).
wxString GetKeywordsProp() const
Definition lib_symbol.h:503
std::vector< wxString > m_bodyStyleNames
void AppendParentEmbeddedFiles(std::vector< EMBEDDED_FILES * > &aStack) const
std::vector< SCH_PIN * > GetPinsByNumber(const wxString &aNumber, int aUnit=0, int aBodyStyle=0)
Return all pin objects with the requested pin aNumber.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
BOX2I GetBodyBoundingBox() const override
Return a bounding box for the symbol body but not the pins or fields.
Definition lib_symbol.h:334
void SetValueProp(const wxString &aValue)
Definition lib_symbol.h:478
int GetPinCount() override
std::map< wxString, wxString > m_chooserFieldsCache
void SetLibId(const LIB_ID &aLibId)
void cacheSearchTerms()
void AddField(SCH_FIELD *aField)
Add a field.
void ClearEditFlags() override
int m_pinCountCache
bool GetLocalPowerSymbolProp() const
Definition lib_symbol.h:526
void deleteAllFields()
LIB_ID GetLIB_ID() const override
Definition lib_symbol.h:178
std::vector< ASSOCIATED_FOOTPRINT > m_associatedFootprints
Footprints associated with this symbol, each tied to a named pin map.
const SCH_PIN * GetPin(const wxString &aNumber, int aUnit=0, int aBodyStyle=0) const
Return pin object with the requested pin aNumber.
bool m_duplicatePinNumbersAreJumpers
Flag that this symbol should automatically treat sets of two or more pins with the same number as jum...
void SetUnitProp(int aUnits)
Definition lib_symbol.h:559
wxString GetFootprintProp() const
Definition lib_symbol.h:483
void SetPinNamesInsideProp(bool aInside)
Definition lib_symbol.h:546
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
wxString GetUnitDisplayName(int aUnit, bool aLabel) const override
Return the user-defined display name for aUnit for symbols with units.
wxString m_parentName
The name of the parent symbol or empty if root symbol.
Definition lib_symbol.h:985
void EmbedFonts() override
void SetLocalPowerSymbolProp(bool aIsLocalPower)
Definition lib_symbol.h:531
virtual void SetName(const wxString &aName)
void SetNormal()
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:432
void cacheShownDescription()
int GetNextFieldOrdinal() const
Return the next ordinal for a user field for this symbol.
ITERATOR_BASE< SCH_ITEM, MULTIVECTOR< SCH_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
ITERATOR end(int aType=UNDEFINED_TYPE)
ITERATOR begin(int aType=UNDEFINED_TYPE)
const std::vector< PIN_MAP > & GetAll() const
Definition pin_map.h:138
Base plotter engine class.
Definition plotter.h:133
bool GetColorMode() const
Definition plotter.h:161
virtual void SetColor(const COLOR4D &color)=0
PROPERTY_BASE & SetChoicesFunc(std::function< wxPGChoices(INSPECTABLE *)> aFunc)
Definition property.h:276
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:262
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:72
bool IsMandatory() const
wxString GetFullText(int unit=1) const
Return the text of a field.
bool IsNameShown() const
Definition sch_field.h:218
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:128
FIELD_T GetId() const
Definition sch_field.h:132
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetName(const wxString &aName)
bool ShowInChooser() const
Definition sch_field.h:239
void SetText(const wxString &aText) override
int m_unit
Definition sch_item.h:776
int m_bodyStyle
Definition sch_item.h:777
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:724
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:268
friend class LIB_SYMBOL
Definition sch_item.h:797
@ SKIP_TST_POS
Definition sch_item.h:707
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:377
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:350
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:59
bool m_showPinNumbers
Definition symbol.h:268
bool m_excludedFromPosFiles
Definition symbol.h:273
SYMBOL(KICAD_T idType)
Definition symbol.h:61
bool m_excludedFromSim
Definition symbol.h:270
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
Definition symbol.h:236
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition symbol.h:170
bool m_showPinNames
Definition symbol.h:267
int GetPinNameOffset() const
Definition symbol.h:159
virtual void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition symbol.h:164
bool m_excludedFromBOM
Definition symbol.h:271
virtual bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:197
bool m_excludedFromBoard
Definition symbol.h:272
virtual bool GetShowPinNames() const
Definition symbol.h:165
void SetPinNameOffset(int aOffset)
Set the offset in mils of the pin name text from the pin symbol.
Definition symbol.h:158
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:212
virtual bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:182
SYMBOL & operator=(const SYMBOL &aItem)
Definition symbol.h:89
virtual bool GetShowPinNumbers() const
Definition symbol.h:171
int m_pinNameOffset
The offset in mils to draw the pin name.
Definition symbol.h:265
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:42
wxString wx_str() const
Definition utf8.cpp:41
wxString ResolveTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aResolver, int &aDepth)
Multi-pass text variable expansion and math expression evaluation.
Definition common.cpp:310
The common library.
#define DEFAULT_PIN_NAME_OFFSET
The intersheets references prefix string.
#define _(s)
RECURSE_MODE
Definition eda_item.h:48
INSPECT_RESULT
Definition eda_item.h:42
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:89
#define IGNORE_PARENT_GROUP
Definition eda_item.h:53
#define IS_NEW
New item, just created.
#define STRUCT_DELETED
flag indication structures to be erased
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
@ FILLED_WITH_COLOR
Definition eda_shape.h:63
@ FILLED_WITH_BG_BODYCOLOR
Definition eda_shape.h:62
TRANSFORM DefaultTransform
Definition transform.cpp:28
const wxChar *const traceSymbolInheritance
Flag to enable tracing of circular symbol inheritance detection.
const wxChar *const traceStackedPins
Flag to enable debug output for stacked pins handling in symbol/pin code.
@ LAYER_DEVICE
Definition layer_ids.h:472
@ LAYER_FIELDS
Definition layer_ids.h:468
#define REPORT(msg)
static std::shared_ptr< LIB_SYMBOL > GetSafeRootSymbol(const LIB_SYMBOL *aSymbol, const char *aCallerName)
Helper to safely get the root symbol, detecting and logging circular inheritance.
static struct LIB_SYMBOL_DESC _LIB_SYMBOL_DESC
SEARCH_TERM_CACHE_INDEX
@ STCI_LIB_ID
@ STCI_LIB_SYMBOL_NAME
@ STCI_LIB_NICKNAME
bool operator<(const LIB_SYMBOL &aItem1, const LIB_SYMBOL &aItem2)
#define ITEM_DESC(item)
@ ENTRY_NORMAL
Definition lib_symbol.h:57
@ ENTRY_LOCAL_POWER
Definition lib_symbol.h:59
@ ENTRY_GLOBAL_POWER
Definition lib_symbol.h:58
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
Definition lib_symbol.h:51
#define _HKI(x)
Definition page_info.cpp:40
#define TYPE_HASH(x)
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
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:194
@ BASE
Definition sch_item.h:56
@ DEMORGAN
Definition sch_item.h:57
Options controlling how a derived symbol's fields are reconciled with its parent.
Definition lib_symbol.h:80
bool m_removeExtraFields
Drop fields not present in the parent.
Definition lib_symbol.h:88
bool m_resetPositions
Copy parent field positions.
Definition lib_symbol.h:97
bool m_resetVisibility
Copy parent visibility and name-shown flags.
Definition lib_symbol.h:91
bool m_updateAllFields
Reconcile every field. When false only the names in m_updateFields are touched.
Definition lib_symbol.h:82
std::set< wxString > m_updateFields
Field names to reconcile when m_updateAllFields is false.
Definition lib_symbol.h:85
bool m_resetEffects
Copy parent text effects (font, justification, etc.) but keep local visibility/position.
Definition lib_symbol.h:94
bool m_resetEmptyText
Copy parent text even when the parent value is empty.
Definition lib_symbol.h:103
bool m_resetText
Copy parent text when the parent value is non-empty.
Definition lib_symbol.h:100
Logical pins: Return expanded logical pins based on stacked-pin notation.
Definition lib_symbol.h:685
std::vector< wxString > m_pinNumbers
Definition lib_symbol.h:699
int m_bodyStyle
The alternate body style of the unit.
Definition lib_symbol.h:69
std::vector< SCH_ITEM * > m_items
The items unique to this unit and alternate body style.
Definition lib_symbol.h:70
int m_unit
The unit number.
Definition lib_symbol.h:68
A structure for storing weighted search terms.
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared
void operator()(void const *) const
#define MANDATORY_FIELDS
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS_PIN * pin
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:71
@ LIB_SYMBOL_T
Definition typeinfo.h:145
@ TYPE_NOT_INIT
Definition typeinfo.h:74
@ SCH_FIELD_T
Definition typeinfo.h:147
@ SCH_SHAPE_T
Definition typeinfo.h:146
@ SCH_TEXT_T
Definition typeinfo.h:148
@ SCH_PIN_T
Definition typeinfo.h:150
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683