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 ) );
165 m_searchTermsCache.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) );
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 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id
1560
1561 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1562 ordinal = std::max( ordinal, static_cast<const SCH_FIELD*>( &item )->GetOrdinal() + 1 );
1563
1564 return ordinal;
1565}
1566
1567
1568const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const
1569{
1570 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1571 {
1572 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1573
1574 if( field->GetId() == aFieldType )
1575 return field;
1576 }
1577
1578 return nullptr;
1579}
1580
1581
1583{
1584 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1585 {
1586 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1587
1588 if( field->GetId() == aFieldType )
1589 return field;
1590 }
1591
1592 return nullptr;
1593}
1594
1595
1596const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const
1597{
1598 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1599 {
1600 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1601
1602 if( field.GetName() == aFieldName )
1603 return &field;
1604 }
1605
1606 return nullptr;
1607}
1608
1609
1610SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName )
1611{
1612 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1613 {
1614 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1615
1616 if( field.GetName() == aFieldName )
1617 return &field;
1618 }
1619
1620 return nullptr;
1621}
1622
1623
1625{
1626 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1627 {
1628 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1629
1630 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1631 return &field;
1632 }
1633
1634 return nullptr;
1635}
1636
1637
1638const SCH_FIELD* LIB_SYMBOL::FindFieldCaseInsensitive( const wxString& aFieldName ) const
1639{
1640 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1641 {
1642 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1643
1644 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1645 return &field;
1646 }
1647
1648 return nullptr;
1649}
1650
1651
1653{
1654 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
1655 wxASSERT( field != nullptr );
1656 return *field;
1657}
1658
1659
1661{
1662 const SCH_FIELD* field = GetField( FIELD_T::REFERENCE );
1663 wxASSERT( field != nullptr );
1664 return *field;
1665}
1666
1667
1669{
1670 const SCH_FIELD* field = GetField( FIELD_T::FOOTPRINT );
1671 wxASSERT( field != nullptr );
1672 return *field;
1673}
1674
1675
1677{
1678 const SCH_FIELD* field = GetField( FIELD_T::DATASHEET );
1679 wxASSERT( field != nullptr );
1680 return *field;
1681}
1682
1683
1685{
1686 const SCH_FIELD* field = GetField( FIELD_T::DESCRIPTION );
1687 wxASSERT( field != nullptr );
1688 return *field;
1689}
1690
1691
1693{
1694 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
1695
1696 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1697
1698 wxString prefix = refDesignator;
1699
1700 while( prefix.Length() )
1701 {
1702 wxUniCharRef last = prefix.Last();
1703
1704 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1705 prefix.RemoveLast();
1706 else
1707 break;
1708 }
1709
1710 // Avoid a prefix containing trailing/leading spaces
1711 prefix.Trim( true );
1712 prefix.Trim( false );
1713
1714 return prefix;
1715}
1716
1717
1718void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1719{
1720 for( SCH_ITEM& item : m_drawings )
1721 aFunction( &item );
1722}
1723
1724
1725void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1726{
1727 for( SCH_ITEM& item : m_drawings )
1728 item.Move( aOffset );
1729}
1730
1731
1732// Before V10 we didn't store the number of body styles in a symbol -- we just looked through all
1733// its drawings each time we wanted to know. This is now only used to set the count when a legacy
1734// symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count
1735// is always 1 or 2, and when 2 it is always a De Morgan pair.)
1737{
1738 for( const SCH_ITEM& item : m_drawings )
1739 {
1740 if( item.m_bodyStyle > BODY_STYLE::BASE )
1741 return true;
1742 }
1743
1744 if( IsDerived() )
1745 {
1746 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1747
1748 if( root.get() != this )
1749 return root->HasLegacyAlternateBodyStyle();
1750 }
1751
1752 return false;
1753}
1754
1755
1757{
1758 if( IsDerived() )
1759 {
1760 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1761
1762 if( root.get() != this )
1763 return root->GetMaxPinNumber();
1764 }
1765
1766 int maxPinNumber = 0;
1767
1768 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1769 {
1770 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1771 long currentPinNumber = 0;
1772
1773 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1774 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1775 }
1776
1777 return maxPinNumber;
1778}
1779
1780
1782{
1784
1785 for( SCH_ITEM& item : m_drawings )
1786 item.ClearTempFlags();
1787}
1788
1789
1791{
1793
1794 for( SCH_ITEM& item : m_drawings )
1795 item.ClearEditFlags();
1796}
1797
1798
1799SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint )
1800{
1801 for( SCH_ITEM& item : m_drawings )
1802 {
1803 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1804 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1805 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1806 {
1807 continue;
1808 }
1809
1810 if( item.HitTest( aPoint ) )
1811 return &item;
1812 }
1813
1814 return nullptr;
1815}
1816
1817
1818SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint,
1819 const TRANSFORM& aTransform )
1820{
1821 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1822 * VECTOR2I& pt ) to search items.
1823 * because this function uses DefaultTransform as orient/mirror matrix
1824 * we temporary copy aTransform in DefaultTransform
1825 */
1826 TRANSFORM transform = DefaultTransform;
1827 DefaultTransform = aTransform;
1828
1829 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1830
1831 // Restore matrix
1832 DefaultTransform = transform;
1833
1834 return item;
1835}
1836
1837
1838INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
1839{
1840 // The part itself is never inspected, only its children
1841 for( SCH_ITEM& item : m_drawings )
1842 {
1843 if( item.IsType( aScanTypes ) )
1844 {
1845 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1846 return INSPECT_RESULT::QUIT;
1847 }
1848 }
1849
1851}
1852
1853
1854void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1855{
1856 // A LIB_SYMBOL must always have at least one unit. Passing a value less than 1 would
1857 // erase the mandatory fields (which all have m_unit == 0), leaving the symbol in a
1858 // broken state that crashes later when callers dereference GetReferenceField() etc.
1859 wxCHECK_RET( aCount >= 1,
1860 wxString::Format( wxT( "Invalid unit count %d, ignoring." ), aCount ) );
1861
1862 if( m_unitCount == aCount )
1863 return;
1864
1865 if( aCount < m_unitCount )
1866 {
1867 // Iterate each drawing-type bucket and erase items that belong to units > aCount.
1868 for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
1869 {
1870 auto it = m_drawings.begin( type );
1871
1872 while( it != m_drawings.end( type ) )
1873 {
1874 if( it->m_unit > aCount )
1875 it = m_drawings.erase( it ); // returns next iterator
1876 else
1877 ++it;
1878 }
1879 }
1880 }
1881 else if( aDuplicateDrawItems )
1882 {
1883 int prevCount = m_unitCount;
1884
1885 // Temporary storage for new items, as adding new items directly to
1886 // m_drawings may cause the buffer reallocation which invalidates the
1887 // iterators
1888 std::vector<SCH_ITEM*> tmp;
1889
1890 for( SCH_ITEM& item : m_drawings )
1891 {
1892 if( item.m_unit != 1 )
1893 continue;
1894
1895 for( int j = prevCount + 1; j <= aCount; j++ )
1896 {
1897 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1898 newItem->m_unit = j;
1899 tmp.push_back( newItem );
1900 }
1901 }
1902
1903 for( SCH_ITEM* item : tmp )
1904 m_drawings.push_back( item );
1905 }
1906
1907 m_drawings.sort();
1908 m_unitCount = aCount;
1909}
1910
1911
1913{
1914 if( IsDerived() )
1915 {
1916 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1917
1918 if( root.get() != this )
1919 return root->GetUnitCount();
1920 }
1921
1922 return m_unitCount;
1923}
1924
1925
1926void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins )
1927{
1928 int prevCount = GetBodyStyleCount();
1929
1930 if( prevCount == aCount )
1931 return;
1932
1933 // Duplicate items to create the converted shape
1934 if( prevCount < aCount )
1935 {
1936 if( aDuplicateDrawItems || aDuplicatePins )
1937 {
1938 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1939
1940 for( SCH_ITEM& item : m_drawings )
1941 {
1942 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
1943 continue;
1944
1945 if( item.m_bodyStyle == 1 )
1946 {
1947 for( int j = prevCount + 1; j <= aCount; j++ )
1948 {
1949 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1950 newItem->m_bodyStyle = j;
1951 tmp.push_back( newItem );
1952 }
1953 }
1954 }
1955
1956 // Transfer the new pins to the LIB_SYMBOL.
1957 for( SCH_ITEM* item : tmp )
1958 m_drawings.push_back( item );
1959 }
1960 }
1961 else
1962 {
1963 // Delete converted shape items because the converted shape does not exist
1965
1966 while( i != m_drawings.end() )
1967 {
1968 if( i->m_bodyStyle > aCount )
1969 i = m_drawings.erase( i );
1970 else
1971 ++i;
1972 }
1973 }
1974
1975 m_drawings.sort();
1976}
1977
1978
1979std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1980{
1981 std::vector<SCH_ITEM*> unitItems;
1982
1983 for( SCH_ITEM& item : m_drawings )
1984 {
1985 if( item.Type() == SCH_FIELD_T )
1986 continue;
1987
1988 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1989 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1990 {
1991 unitItems.push_back( &item );
1992 }
1993 }
1994
1995 return unitItems;
1996}
1997
1998
1999std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
2000{
2001 std::vector<LIB_SYMBOL_UNIT> units;
2002
2003 for( SCH_ITEM& item : m_drawings )
2004 {
2005 if( item.Type() == SCH_FIELD_T )
2006 continue;
2007
2008 int unit = item.GetUnit();
2009 int bodyStyle = item.GetBodyStyle();
2010
2011 auto it = std::find_if( units.begin(), units.end(),
2012 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
2013 {
2014 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
2015 } );
2016
2017 if( it == units.end() )
2018 {
2019 LIB_SYMBOL_UNIT newUnit;
2020 newUnit.m_unit = item.GetUnit();
2021 newUnit.m_bodyStyle = item.GetBodyStyle();
2022 newUnit.m_items.push_back( &item );
2023 units.emplace_back( newUnit );
2024 }
2025 else
2026 {
2027 it->m_items.push_back( &item );
2028 }
2029 }
2030
2031 return units;
2032}
2033
2034
2035#define REPORT( msg ) \
2036 { \
2037 if( aReporter ) \
2038 aReporter->Report( msg ); \
2039 }
2040#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
2041
2042int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
2043{
2044 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
2045
2046 if( m_me == aRhs.m_me )
2047 return 0;
2048
2049 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2050 {
2051 if( int tmp = m_name.Cmp( aRhs.m_name ) )
2052 return tmp;
2053
2054 if( int tmp = m_libId.compare( aRhs.m_libId ) )
2055 return tmp;
2056
2057 if( m_parent.lock() < aRhs.m_parent.lock() )
2058 return -1;
2059
2060 if( m_parent.lock() > aRhs.m_parent.lock() )
2061 return 1;
2062 }
2063
2064 int retv = 0;
2065
2066 if( m_options != aRhs.m_options )
2067 {
2068 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
2069 REPORT( _( "Power flag differs." ) );
2070
2071 if( !aReporter )
2072 return retv;
2073 }
2074
2075 if( int tmp = m_unitCount - aRhs.m_unitCount )
2076 {
2077 retv = tmp;
2078 REPORT( _( "Unit count differs." ) );
2079
2080 if( !aReporter )
2081 return retv;
2082 }
2083
2084 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
2085
2086 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
2087 std::set<const SCH_FIELD*> aFields;
2088 std::set<const SCH_PIN*> aPins;
2089
2090 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
2091 {
2092 if( it->Type() == SCH_SHAPE_T )
2093 aShapes.insert( &( *it ) );
2094 else if( it->Type() == SCH_FIELD_T )
2095 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2096 else if( it->Type() == SCH_PIN_T )
2097 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2098 }
2099
2100 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
2101 std::set<const SCH_FIELD*> bFields;
2102 std::set<const SCH_PIN*> bPins;
2103
2104 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
2105 {
2106 if( it->Type() == SCH_SHAPE_T )
2107 bShapes.insert( &( *it ) );
2108 else if( it->Type() == SCH_FIELD_T )
2109 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2110 else if( it->Type() == SCH_PIN_T )
2111 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2112 }
2113
2114 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
2115 {
2116 retv = tmp;
2117 REPORT( _( "Graphic item count differs." ) );
2118
2119 if( !aReporter )
2120 return retv;
2121 }
2122 else
2123 {
2124 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
2125 {
2126 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
2127 {
2128 retv = tmp2;
2129 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
2130 ITEM_DESC( *bIt ) ) );
2131
2132 if( !aReporter )
2133 return retv;
2134 }
2135 }
2136 }
2137
2138 for( const SCH_PIN* aPin : aPins )
2139 {
2140 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
2141
2142 if( !bPin )
2143 {
2144 retv = 1;
2145 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
2146
2147 if( !aReporter )
2148 return retv;
2149 }
2150 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
2151 {
2152 retv = tmp;
2153 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
2154 ITEM_DESC( bPin ) ) );
2155
2156 if( !aReporter )
2157 return retv;
2158 }
2159 }
2160
2161 for( const SCH_PIN* bPin : bPins )
2162 {
2163 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
2164
2165 if( !aPin )
2166 {
2167 retv = 1;
2168 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
2169
2170 if( !aReporter )
2171 return retv;
2172 }
2173 }
2174
2175 for( const SCH_FIELD* aField : aFields )
2176 {
2177 const SCH_FIELD* bField = nullptr;
2178
2179 if( aField->IsMandatory() )
2180 bField = aRhs.GetField( aField->GetId() );
2181 else
2182 bField = aRhs.GetField( aField->GetName() );
2183
2184 if( !bField )
2185 {
2186 retv = 1;
2187 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
2188
2189 if( !aReporter )
2190 return retv;
2191 }
2192 else
2193 {
2194 int tmp = 0;
2195
2196 // For EQUALITY comparison, we need to compare field content directly
2197 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
2198 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
2199 {
2200 // Compare field text content
2201 tmp = aField->GetText().compare( bField->GetText() );
2202 }
2203
2204 if( tmp == 0 )
2205 {
2206 int fieldCompareFlags = aCompareFlags;
2207
2208 // SCH_FIELD::compare() injects SKIP_TST_POS for ERC, but it is bypassed
2209 // by the base-class call below, so mirror it here (issue 24657).
2210 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC )
2211 fieldCompareFlags |= SCH_ITEM::COMPARE_FLAGS::SKIP_TST_POS;
2212
2213 // Fall back to base class comparison for other properties
2214 tmp = aField->SCH_ITEM::compare( *bField, fieldCompareFlags );
2215 }
2216
2217 if( tmp != 0 )
2218 {
2219 retv = tmp;
2220 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
2221 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
2222
2223 if( !aReporter )
2224 return retv;
2225 }
2226 }
2227 }
2228
2229 for( const SCH_FIELD* bField : bFields )
2230 {
2231 const SCH_FIELD* aField = nullptr;
2232
2233 if( bField->IsMandatory() )
2234 aField = aRhs.GetField( bField->GetId() );
2235 else
2236 aField = aRhs.GetField( bField->GetName() );
2237
2238 if( !aField )
2239 {
2240 retv = 1;
2241 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
2242
2243 if( !aReporter )
2244 return retv;
2245 }
2246 }
2247
2248 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
2249 {
2250 retv = tmp;
2251 REPORT( _( "Footprint filter count differs." ) );
2252
2253 if( !aReporter )
2254 return retv;
2255 }
2256 else
2257 {
2258 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
2259 {
2260 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
2261 {
2262 retv = tmp2;
2263 REPORT( _( "Footprint filters differ." ) );
2264
2265 if( !aReporter )
2266 return retv;
2267 }
2268 }
2269 }
2270
2271 if( int tmp = static_cast<int>( m_pinMaps.GetAll().size() - aRhs.m_pinMaps.GetAll().size() ) )
2272 {
2273 retv = tmp;
2274 REPORT( _( "Pin map count differs." ) );
2275
2276 if( !aReporter )
2277 return retv;
2278 }
2279 else if( m_pinMaps != aRhs.m_pinMaps )
2280 {
2281 retv = 1;
2282 REPORT( _( "Pin maps differ." ) );
2283
2284 if( !aReporter )
2285 return retv;
2286 }
2287
2288 if( int tmp = static_cast<int>( m_associatedFootprints.size() - aRhs.m_associatedFootprints.size() ) )
2289 {
2290 retv = tmp;
2291 REPORT( _( "Associated footprint count differs." ) );
2292
2293 if( !aReporter )
2294 return retv;
2295 }
2297 {
2298 retv = 1;
2299 REPORT( _( "Associated footprints differ." ) );
2300
2301 if( !aReporter )
2302 return retv;
2303 }
2304
2305 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
2306 {
2307 retv = tmp;
2308 REPORT( _( "Symbol keywords differ." ) );
2309
2310 if( !aReporter )
2311 return retv;
2312 }
2313
2314 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
2315 {
2316 retv = tmp;
2317 REPORT( _( "Symbol pin name offsets differ." ) );
2318
2319 if( !aReporter )
2320 return retv;
2321 }
2322
2323 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2324 {
2325 if( m_showPinNames != aRhs.m_showPinNames )
2326 {
2327 retv = ( m_showPinNames ) ? 1 : -1;
2328 REPORT( _( "Show pin names settings differ." ) );
2329
2330 if( !aReporter )
2331 return retv;
2332 }
2333
2335 {
2336 retv = ( m_showPinNumbers ) ? 1 : -1;
2337 REPORT( _( "Show pin numbers settings differ." ) );
2338
2339 if( !aReporter )
2340 return retv;
2341 }
2342
2344 {
2345 retv = ( m_excludedFromSim ) ? -1 : 1;
2346 REPORT( _( "Exclude from simulation settings differ." ) );
2347
2348 if( !aReporter )
2349 return retv;
2350 }
2351
2353 {
2354 retv = ( m_excludedFromBOM ) ? -1 : 1;
2355 REPORT( _( "Exclude from bill of materials settings differ." ) );
2356
2357 if( !aReporter )
2358 return retv;
2359 }
2360
2362 {
2363 retv = ( m_excludedFromBoard ) ? -1 : 1;
2364 REPORT( _( "Exclude from board settings differ." ) );
2365
2366 if( !aReporter )
2367 return retv;
2368 }
2369
2371 {
2372 retv = ( m_excludedFromPosFiles ) ? -1 : 1;
2373 REPORT( _( "Exclude from position files settings differ." ) );
2374
2375 if( !aReporter )
2376 return retv;
2377 }
2378 }
2379
2380 if( !aReporter )
2381 {
2382 if( m_unitsLocked != aRhs.m_unitsLocked )
2383 return ( m_unitsLocked ) ? 1 : -1;
2384
2385 // Compare unit display names...
2387 return -1;
2388 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
2389 return 1;
2390
2391 // ... and body style names.
2393 return -1;
2394 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
2395 return 1;
2396 }
2397
2398 return retv;
2399}
2400
2401
2402int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2403{
2404 if( Type() != aOther.Type() )
2405 return Type() - aOther.Type();
2406
2407 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
2408
2409 return Compare( *tmp, aCompareFlags );
2410}
2411
2412
2413double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2414{
2415 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
2416
2417 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
2418 double similarity = 0.0;
2419 int totalItems = 0;
2420
2421 if( m_Uuid == aOther.m_Uuid )
2422 return 1.0;
2423
2424 for( const SCH_ITEM& item : m_drawings )
2425 {
2426 totalItems += 1;
2427 double max_similarity = 0.0;
2428
2429 for( const SCH_ITEM& otherItem : other.m_drawings )
2430 {
2431 double temp_similarity = item.Similarity( otherItem );
2432 max_similarity = std::max( max_similarity, temp_similarity );
2433
2434 if( max_similarity == 1.0 )
2435 break;
2436 }
2437
2438 similarity += max_similarity;
2439 }
2440
2441 for( const SCH_PIN* pin : GetGraphicalPins( 0, 0 ) )
2442 {
2443 totalItems += 1;
2444 double max_similarity = 0.0;
2445
2446 for( const SCH_PIN* otherPin : other.GetGraphicalPins( 0, 0 ) )
2447 {
2448 double temp_similarity = pin->Similarity( *otherPin );
2449 max_similarity = std::max( max_similarity, temp_similarity );
2450
2451 if( max_similarity == 1.0 )
2452 break;
2453 }
2454
2455 similarity += max_similarity;
2456 }
2457
2458 if( totalItems == 0 )
2459 similarity = 0.0;
2460 else
2461 similarity /= totalItems;
2462
2464 similarity *= 0.9;
2465
2467 similarity *= 0.9;
2468
2470 similarity *= 0.9;
2471
2473 similarity *= 0.9;
2474
2475 if( m_flags != other.m_flags )
2476 similarity *= 0.9;
2477
2478 if( m_unitCount != other.m_unitCount )
2479 similarity *= 0.5;
2480
2481 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
2482 similarity *= 0.5;
2483 else if( m_bodyStyleNames != other.m_bodyStyleNames )
2484 similarity *= 0.9;
2485
2486 if( m_pinNameOffset != other.m_pinNameOffset )
2487 similarity *= 0.9;
2488
2489 if( m_showPinNames != other.m_showPinNames )
2490 similarity *= 0.9;
2491
2492 if( m_showPinNumbers != other.m_showPinNumbers )
2493 similarity *= 0.9;
2494
2495 return similarity;
2496}
2497
2498
2500{
2501 return static_cast<EMBEDDED_FILES*>( this );
2502}
2503
2504
2506{
2507 return static_cast<const EMBEDDED_FILES*>( this );
2508}
2509
2510
2511void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2512{
2513 std::set<const LIB_SYMBOL*> visited;
2514 visited.insert( this );
2515
2516 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2517
2518 while( parent )
2519 {
2520 // Cycle detected - parent chain points back to an already visited symbol
2521 if( visited.count( parent.get() ) )
2522 {
2523 wxLogTrace( traceSymbolInheritance,
2524 wxT( "AppendParentEmbeddedFiles: Circular inheritance detected in "
2525 "symbol '%s' (lib: %s)" ),
2526 m_name, m_libId.GetLibNickname().wx_str() );
2527 break;
2528 }
2529
2530 visited.insert( parent.get() );
2531 aStack.push_back( parent->GetEmbeddedFiles() );
2532 parent = parent->GetParent().lock();
2533 }
2534}
2535
2536
2537std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2538{
2539 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2540
2541 std::set<KIFONT::OUTLINE_FONT*> fonts;
2542
2543 for( const SCH_ITEM& item : m_drawings )
2544 {
2545 if( item.Type() == SCH_TEXT_T )
2546 {
2547 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2548
2549 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2550 {
2551 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2552 auto permission = outline->GetEmbeddingPermission();
2553
2554 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2555 {
2556 fonts.insert( outline );
2557 }
2558 }
2559 }
2560 }
2561
2562 return fonts;
2563}
2564
2565
2567{
2568 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2569
2570 for( KIFONT::OUTLINE_FONT* font : fonts )
2571 {
2572 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2574 }
2575}
2576
2577
2578std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2579{
2580 for( const std::set<wxString>& group : m_jumperPinGroups )
2581 {
2582 if( group.contains( aPinNumber ) )
2583 return group;
2584 }
2585
2586 return std::nullopt;
2587}
2588
2589static struct LIB_SYMBOL_DESC
2590{
2592 {
2596
2597 const wxString groupFields = _HKI( "Fields" );
2598
2601 groupFields );
2604 groupFields );
2607 groupFields );
2610 groupFields );
2613 groupFields );
2614
2615 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2616
2617 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2620 groupSymbolDef );
2621 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2624 groupSymbolDef );
2625
2626 const wxString groupPinDisplay = _HKI( "Pin Display" );
2627
2628 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2630 groupPinDisplay );
2631 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2633 groupPinDisplay );
2634 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2637 groupPinDisplay );
2638 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2640 groupPinDisplay );
2641
2642 const wxString groupAttributes = _HKI( "Attributes" );
2643
2644 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2647 groupAttributes );
2648 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
2651 groupAttributes );
2652 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2655 groupAttributes );
2656 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
2659 groupAttributes );
2660
2661 const wxString groupUnits = _HKI( "Units and Body Styles" );
2662
2663 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2665 groupUnits );
2666 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2669 groupUnits );
2670
2671 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2672 {
2673 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2674 return symbol->IsMultiBodyStyle();
2675
2676 return false;
2677 };
2678
2681 groupUnits )
2682 .SetAvailableFunc( multiBodyStyle )
2684 []( INSPECTABLE* aItem )
2685 {
2686 wxPGChoices choices;
2687
2688 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2689 {
2690 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2691 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2692 }
2693
2694 return choices;
2695 } );
2696 }
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 bool IsVisible() const
Definition eda_text.h:208
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:80
LIB_ITEMS_CONTAINER m_drawings
Definition lib_symbol.h:951
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:394
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:149
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:176
void SetGlobalPower()
std::weak_ptr< LIB_SYMBOL > & GetParent()
Definition lib_symbol.h:111
wxString GetBodyStyleProp() const override
Definition lib_symbol.h:524
LIBRENTRYOPTIONS m_options
Special symbol features such as POWER or NORMAL.
Definition lib_symbol.h:949
wxString GetRefProp() const
Definition lib_symbol.h:413
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:514
wxString m_shownDescriptionCache
Definition lib_symbol.h:982
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:256
SCH_FIELD & GetDatasheetField()
Return reference to the datasheet field.
Definition lib_symbol.h:390
void RefreshLibraryTreeCaches()
std::weak_ptr< LIB_SYMBOL > m_parent
Use for inherited symbols.
Definition lib_symbol.h:933
void SetExcludedFromBoardProp(bool aExclude)
Definition lib_symbol.h:560
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
Definition lib_symbol.h:974
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 (...
Definition lib_symbol.h:968
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
void SetKeywordsProp(const wxString &aKeywords)
Definition lib_symbol.h:458
bool IsDerived() const
Definition lib_symbol.h:197
std::map< int, wxString > & GetUnitDisplayNames()
Definition lib_symbol.h:797
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:945
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:566
void SetLib(LEGACY_SYMBOL_LIB *aLibrary)
bool GetPowerSymbolProp() const
Definition lib_symbol.h:463
bool IsMultiBodyStyle() const override
Definition lib_symbol.h:821
int GetMaxPinNumber() const
std::vector< SEARCH_TERM > m_searchTermsCache
Definition lib_symbol.h:980
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:386
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
Definition lib_symbol.h:954
void SetUnitsInterchangeableProp(bool aInterchangeable)
Definition lib_symbol.h:519
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
LEGACY_SYMBOL_LIB * m_library
Definition lib_symbol.h:953
bool GetExcludedFromPosFilesProp() const
Definition lib_symbol.h:565
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
wxString m_keyWords
Search keywords.
Definition lib_symbol.h:955
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:443
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:418
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:142
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:932
wxString GetValueProp() const
Definition lib_symbol.h:423
bool GetExcludedFromBOMProp() const
Definition lib_symbol.h:545
void SetKeyWords(const wxString &aKeyWords)
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:378
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:504
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:89
bool GetPinNamesInsideProp() const
Definition lib_symbol.h:491
const std::vector< wxString > & GetBodyStyleNames() const
Definition lib_symbol.h:834
void SetBodyStyleProp(const wxString &aBodyStyle) override
Definition lib_symbol.h:529
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:939
void SetExcludedFromSimProp(bool aExclude)
Definition lib_symbol.h:540
bool GetExcludedFromBoardProp() const
Definition lib_symbol.h:555
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:937
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:155
void SetFootprintProp(const wxString &aFootprint)
Definition lib_symbol.h:438
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:831
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:942
wxArrayString m_fpFilters
List of suitable footprint names for the symbol (wild card names accepted).
Definition lib_symbol.h:956
void Move(const VECTOR2I &aOffset) override
Move the symbol aOffset.
const PIN_MAP_SET & GetEffectivePinMaps() const
Definition lib_symbol.h:241
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:535
int GetBodyStyleCount() const override
Definition lib_symbol.h:823
void SetDatasheetProp(const wxString &aDatasheet)
Definition lib_symbol.h:448
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:468
void SetExcludedFromBOMProp(bool aExclude)
Definition lib_symbol.h:550
int m_unitCount
Number of units (parts) per package.
Definition lib_symbol.h:941
wxString GetShownDescription(int aDepth=0) const override
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).
Definition lib_symbol.h:960
wxString GetKeywordsProp() const
Definition lib_symbol.h:453
std::vector< wxString > m_bodyStyleNames
Definition lib_symbol.h:975
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:300
void SetValueProp(const wxString &aValue)
Definition lib_symbol.h:428
int GetPinCount() override
std::map< wxString, wxString > m_chooserFieldsCache
Definition lib_symbol.h:983
void SetLibId(const LIB_ID &aLibId)
void cacheSearchTerms()
void AddField(SCH_FIELD *aField)
Add a field.
void ClearEditFlags() override
int m_pinCountCache
Definition lib_symbol.h:981
bool GetLocalPowerSymbolProp() const
Definition lib_symbol.h:476
void deleteAllFields()
LIB_ID GetLIB_ID() const override
Definition lib_symbol.h:144
std::vector< ASSOCIATED_FOOTPRINT > m_associatedFootprints
Footprints associated with this symbol, each tied to a named pin map.
Definition lib_symbol.h:964
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...
Definition lib_symbol.h:972
void SetUnitProp(int aUnits)
Definition lib_symbol.h:509
wxString GetFootprintProp() const
Definition lib_symbol.h:433
void SetPinNamesInsideProp(bool aInside)
Definition lib_symbol.h:496
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:935
void EmbedFonts() override
void SetLocalPowerSymbolProp(bool aIsLocalPower)
Definition lib_symbol.h:481
virtual void SetName(const wxString &aName)
void SetNormal()
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:382
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:71
bool IsMandatory() const
wxString GetFullText(int unit=1) const
Return the text of a field.
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).
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:464
@ LAYER_FIELDS
Definition layer_ids.h:460
#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:56
@ ENTRY_LOCAL_POWER
Definition lib_symbol.h:58
@ ENTRY_GLOBAL_POWER
Definition lib_symbol.h:57
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
Definition lib_symbol.h:50
#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
Logical pins: Return expanded logical pins based on stacked-pin notation.
Definition lib_symbol.h:635
std::vector< wxString > m_pinNumbers
Definition lib_symbol.h:649
int m_bodyStyle
The alternate body style of the unit.
Definition lib_symbol.h:68
std::vector< SCH_ITEM * > m_items
The items unique to this unit and alternate body style.
Definition lib_symbol.h:69
int m_unit
The unit number.
Definition lib_symbol.h:67
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...
@ 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
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