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_set>
42#include <advanced_config.h>
43#include <properties/property.h>
45
46
54static std::shared_ptr<LIB_SYMBOL> GetSafeRootSymbol( const LIB_SYMBOL* aSymbol, const char* aCallerName )
55{
56 std::set<const LIB_SYMBOL*> visited;
57 visited.insert( aSymbol );
58
59 std::shared_ptr<LIB_SYMBOL> current = aSymbol->SharedPtr();
60 std::shared_ptr<LIB_SYMBOL> parent = aSymbol->GetParent().lock();
61
62 while( parent )
63 {
64 if( visited.count( parent.get() ) )
65 {
66 // Build chain description for logging
67 wxString chain = aSymbol->GetName();
68
69 for( const LIB_SYMBOL* sym : visited )
70 {
71 if( sym != aSymbol )
72 chain += wxT( " -> " ) + sym->GetName();
73 }
74
75 chain += wxT( " -> " ) + parent->GetName() + wxT( " (CYCLE)" );
76
77 wxLogTrace( traceSymbolInheritance,
78 wxT( "%s: Circular inheritance detected in symbol '%s' (lib: %s). Chain: %s" ),
79 aCallerName,
80 aSymbol->GetName(),
81 aSymbol->GetLibId().GetLibNickname().wx_str(),
82 chain );
83
84 // Return current (last valid symbol before cycle)
85 return current;
86 }
87
88 visited.insert( parent.get() );
89 current = parent;
90 parent = parent->GetParent().lock();
91 }
92
93 return current;
94}
95
96
97wxString LIB_SYMBOL::GetShownDescription( int aDepth ) const
98{
100}
101
103{
104 wxString shownText = GetDescriptionField().GetShownText( false, 0 );
105
106 if( shownText.IsEmpty() && IsDerived() )
107 {
108 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
109
110 if( root.get() != this )
111 shownText = root->GetDescriptionField().GetShownText( false, 0 );
112 }
113
114 m_shownDescriptionCache = shownText;
115}
116
117
118void LIB_SYMBOL::SetDescription( const wxString& aDescription )
119{
120 GetDescriptionField().SetText( aDescription );
123}
124
125
126void LIB_SYMBOL::SetKeyWords( const wxString& aKeyWords )
127{
128 m_keyWords = aKeyWords;
130}
131
132
133wxString LIB_SYMBOL::GetShownKeyWords( int aDepth ) const
134{
135 wxString text = GetKeyWords();
136
137 std::function<bool( wxString* )> libSymbolResolver = [&]( wxString* token ) -> bool
138 {
139 return ResolveTextVar( token, aDepth + 1 );
140 };
141
142 text = ResolveTextVars( text, &libSymbolResolver, aDepth );
143
144 return text;
145}
146
147
154
155
157{
158 m_searchTermsCache.clear();
159 m_searchTermsCache.reserve( 6 );
160
161 // Order matters, see SEARCH_TERM_CACHE_INDEX
162 m_searchTermsCache.emplace_back( SEARCH_TERM( GetLibNickname(), 4 ) );
163 m_searchTermsCache.emplace_back( SEARCH_TERM( GetName(), 8 ) );
164 m_searchTermsCache.emplace_back( SEARCH_TERM( GetLIB_ID().Format(), 16 ) );
165
166 wxStringTokenizer keywordTokenizer( GetShownKeyWords(), " \t\r\n", wxTOKEN_STRTOK );
167
168 while( keywordTokenizer.HasMoreTokens() )
169 m_searchTermsCache.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) );
170
171 // Also include keywords as one long string, just in case
172 m_searchTermsCache.emplace_back( SEARCH_TERM( GetShownKeyWords(), 1 ) );
173 m_searchTermsCache.emplace_back( SEARCH_TERM( GetShownDescription(), 1 ) );
174
175 wxString footprint = GetFootprint();
176
177 if( !footprint.IsEmpty() )
178 m_searchTermsCache.emplace_back( SEARCH_TERM( footprint, 1 ) );
179}
180
181
182void LIB_SYMBOL::GetChooserFields( std::map<wxString, wxString>& aColumnMap )
183{
184 aColumnMap = m_chooserFieldsCache;
185}
186
187
189{
190 m_chooserFieldsCache.clear();
191
192 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
193 {
194 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
195
196 if( field->ShowInChooser() )
197 m_chooserFieldsCache[field->GetName()] = field->EDA_TEXT::GetShownText( false );
198 }
199
200 // If the user has a field named "Keywords", then prefer that. Otherwise add the KiCad
201 // keywords.
202 const wxString localizedKeywords = _( "Keywords" );
203
204 if( !m_chooserFieldsCache.contains( localizedKeywords ) )
205 m_chooserFieldsCache[localizedKeywords] = GetShownKeyWords();
206}
207
208
209bool operator<( const LIB_SYMBOL& aItem1, const LIB_SYMBOL& aItem2 )
210{
211 return aItem1.GetName() < aItem2.GetName();
212}
213
214
217{
218 void operator()( void const* ) const {}
219};
220
221
222LIB_SYMBOL::LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent, LEGACY_SYMBOL_LIB* aLibrary ) :
224 m_me( this, null_deleter() )
225{
226 m_lastModDate = 0;
227 m_unitCount = 1;
228 m_demorgan = false;
231 m_unitsLocked = false;
233 m_library = nullptr;
234
235 auto addField = [&]( FIELD_T id, bool visible )
236 {
237 SCH_FIELD* field = new SCH_FIELD( this, id );
238 field->SetVisible( visible );
239 m_drawings[SCH_FIELD_T].push_back( field );
240 };
241
242 // construct only the mandatory fields
243 addField( FIELD_T::REFERENCE, true );
244 addField( FIELD_T::VALUE, true );
245 addField( FIELD_T::FOOTPRINT, false );
246 addField( FIELD_T::DATASHEET, false );
247 addField( FIELD_T::DESCRIPTION, false );
248
249 SetName( aName );
250 SetParent( aParent );
251 SetLib( aLibrary );
256}
257
258
259LIB_SYMBOL::LIB_SYMBOL( const LIB_SYMBOL& aSymbol, LEGACY_SYMBOL_LIB* aLibrary, bool aCopyEmbeddedFiles ) :
260 SYMBOL( aSymbol ),
261 EMBEDDED_FILES( aSymbol, aCopyEmbeddedFiles ),
262 m_me( this, null_deleter() )
263{
264 m_library = aLibrary;
265 m_name = aSymbol.m_name;
266 m_fpFilters = wxArrayString( aSymbol.m_fpFilters );
267 m_unitCount = aSymbol.m_unitCount;
268 m_demorgan = aSymbol.m_demorgan;
271 m_options = aSymbol.m_options;
272 m_libId = aSymbol.m_libId;
273 m_keyWords = aSymbol.m_keyWords;
274
277
280
282
283 for( const SCH_ITEM& oldItem : aSymbol.m_drawings )
284 {
285 if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
286 continue;
287
288 try
289 {
290 SCH_ITEM* newItem = (SCH_ITEM*) oldItem.Clone();
291 newItem->ClearSelected();
292 newItem->SetParent( this );
293 m_drawings.push_back( newItem );
294 }
295 catch( ... )
296 {
297 wxFAIL_MSG( "Failed to clone SCH_ITEM." );
298 return;
299 }
300 }
301
302 SetParent( aSymbol.m_parent.lock().get() );
307}
308
309
311{
312 if( &aSymbol == this )
313 return aSymbol;
314
315 SYMBOL::operator=( aSymbol );
316
317 m_library = aSymbol.m_library;
318 m_name = aSymbol.m_name;
319 m_fpFilters = wxArrayString( aSymbol.m_fpFilters );
320 m_unitCount = aSymbol.m_unitCount;
321 m_demorgan = aSymbol.m_demorgan;
324 m_options = aSymbol.m_options;
325 m_libId = aSymbol.m_libId;
326 m_keyWords = aSymbol.m_keyWords;
327
330
333
334 m_drawings.clear();
335
336 for( const SCH_ITEM& oldItem : aSymbol.m_drawings )
337 {
338 if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
339 continue;
340
341 SCH_ITEM* newItem = (SCH_ITEM*) oldItem.Clone();
342 newItem->SetParent( this );
343 m_drawings.push_back( newItem );
344 }
345
346 m_drawings.sort();
347
348 SetParent( aSymbol.m_parent.lock().get() );
349
350 EMBEDDED_FILES::operator=( aSymbol );
351
356
357 return *this;
358}
359
360
367{
368 static LIB_SYMBOL* symbol;
369
370 if( !symbol )
371 {
372 symbol = new LIB_SYMBOL( wxEmptyString );
373
375
376 square->SetPosition( VECTOR2I( schIUScale.MilsToIU( -200 ), schIUScale.MilsToIU( 200 ) ) );
377 square->SetEnd( VECTOR2I( schIUScale.MilsToIU( 200 ), schIUScale.MilsToIU( -200 ) ) );
378 symbol->AddDrawItem( square );
379
380 SCH_TEXT* text = new SCH_TEXT( { 0, 0 }, wxT( "??" ), LAYER_DEVICE );
381
382 text->SetTextSize( VECTOR2I( schIUScale.MilsToIU( 150 ), schIUScale.MilsToIU( 150 ) ) );
383 symbol->AddDrawItem( text );
384 }
385
386 return symbol;
387}
388
389
391{
392 unsigned depth = 0;
393 std::set<const LIB_SYMBOL*> visited;
394 visited.insert( this );
395
396 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
397
398 while( parent )
399 {
400 // Cycle detected - parent chain points back to an already visited symbol
401 if( visited.count( parent.get() ) )
402 {
403 wxLogTrace( traceSymbolInheritance,
404 wxT( "GetInheritanceDepth: Circular inheritance detected in symbol '%s' "
405 "(lib: %s)" ),
406 m_name, m_libId.GetLibNickname().wx_str() );
407 break;
408 }
409
410 visited.insert( parent.get() );
411 depth++;
412 parent = parent->m_parent.lock();
413 }
414
415 return depth;
416}
417
418
419std::shared_ptr<LIB_SYMBOL> LIB_SYMBOL::GetRootSymbol() const
420{
421 std::set<const LIB_SYMBOL*> visited;
422 visited.insert( this );
423
424 std::shared_ptr<LIB_SYMBOL> current = m_me;
425 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
426
427 while( parent )
428 {
429 // Cycle detected - parent chain points back to an already visited symbol
430 if( visited.count( parent.get() ) )
431 {
432 wxLogTrace( traceSymbolInheritance,
433 wxT( "GetRootSymbol: Circular inheritance detected in symbol '%s' "
434 "(lib: %s)" ),
435 m_name, m_libId.GetLibNickname().wx_str() );
436 break;
437 }
438
439 visited.insert( parent.get() );
440 current = parent;
441 parent = parent->m_parent.lock();
442 }
443
444 return current;
445}
446
447
448wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
449{
450 if( m_unitDisplayNames.contains( aUnit ) )
451 return m_unitDisplayNames.at( aUnit );
452 else if( aLabel )
453 return wxString::Format( _( "Unit %s" ), LIB_SYMBOL::LetterSubReference( aUnit, 'A' ) );
454 else
455 return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
456}
457
458
459wxString LIB_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
460{
462 {
463 if( aBodyStyle == BODY_STYLE::DEMORGAN )
464 return aLabel ? _( "Alternate" ) : wxString( _HKI( "Alternate" ) );
465 else if( aBodyStyle == BODY_STYLE::BASE )
466 return aLabel ? _( "Standard" ) : wxString( _HKI( "Standard" ) );
467 }
468 else if( IsMultiBodyStyle() )
469 {
470 if( aBodyStyle <= (int) m_bodyStyleNames.size() )
471 return m_bodyStyleNames[aBodyStyle - 1];
472 }
473
474 return wxT( "?" );
475}
476
477
478void LIB_SYMBOL::SetName( const wxString& aName )
479{
480 m_name = aName;
481 m_libId.SetLibItemName( aName );
482
483 if( m_searchTermsCache.empty() )
485
488}
489
490
491void LIB_SYMBOL::SetLibId( const LIB_ID& aLibId )
492{
493 m_libId = aLibId;
494
495 if( m_searchTermsCache.empty() )
497
499}
500
501
503{
504 if( aParent )
505 {
506 // Prevent circular inheritance by checking if aParent is derived from this symbol
507 std::set<const LIB_SYMBOL*> visited;
508 visited.insert( this );
509
510 std::shared_ptr<LIB_SYMBOL> ancestor = aParent->SharedPtr();
511
512 while( ancestor )
513 {
514 if( visited.count( ancestor.get() ) )
515 {
516 wxLogTrace( traceSymbolInheritance,
517 wxT( "SetParent: Rejecting parent '%s' for symbol '%s' - would create "
518 "circular inheritance (lib: %s)" ),
519 aParent->GetName(), m_name, m_libId.GetLibNickname().wx_str() );
520
521 // Don't set the parent - it would create circular inheritance
522 return;
523 }
524
525 visited.insert( ancestor.get() );
526 ancestor = ancestor->m_parent.lock();
527 }
528
529 m_parent = aParent->SharedPtr();
530
531 // Keep the recorded parent name in sync so serialization never has to dereference the live
532 // parent pointer (which can dangle, see SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol).
533 m_parentName = aParent->GetName();
534 }
535 else
536 {
537 // Only drop the live pointer. The recorded parent name is left untouched so a derived
538 // symbol whose live parent has been lost can still be serialized by name.
539 m_parent.reset();
540 }
541}
542
543
545{
547 return wxEmptyString;
548
549 return GetFootprintField().GetShownText( false );
550}
551
552
553std::unique_ptr<LIB_SYMBOL> LIB_SYMBOL::Flatten() const
554{
555 std::unique_ptr<LIB_SYMBOL> retv;
556
557 if( IsDerived() )
558 {
559 // Build parent chain with cycle detection - collect from this symbol up to root
560 std::vector<const LIB_SYMBOL*> parentChain;
561 std::set<const LIB_SYMBOL*> visited;
562 visited.insert( this );
563
564 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
565
566 wxCHECK_MSG( parent, retv, wxString::Format( "Parent of derived symbol '%s' undefined", m_name ) );
567
568 while( parent )
569 {
570 // Cycle detected - parent chain points back to an already visited symbol
571 if( visited.count( parent.get() ) )
572 {
573 wxLogTrace( traceSymbolInheritance,
574 wxT( "Flatten: Circular inheritance detected in symbol '%s' (lib: %s)" ),
575 m_name, m_libId.GetLibNickname().wx_str() );
576 break;
577 }
578
579 visited.insert( parent.get() );
580 parentChain.push_back( parent.get() );
581 parent = parent->m_parent.lock();
582 }
583
584 // Start with the root (last in chain) and work down
585 if( !parentChain.empty() )
586 {
587 retv = std::make_unique<LIB_SYMBOL>( *parentChain.back() );
588
589 // Apply each derived symbol's overrides from root down (skip the root itself)
590 for( int i = static_cast<int>( parentChain.size() ) - 2; i >= 0; --i )
591 {
592 const LIB_SYMBOL* derived = parentChain[i];
593
594 // Overwrite parent's mandatory fields for fields which are defined in derived.
595 for( FIELD_T fieldId : MANDATORY_FIELDS )
596 {
597 if( !derived->GetField( fieldId )->GetText().IsEmpty() )
598 *retv->GetField( fieldId ) = *derived->GetField( fieldId );
599 }
600
601 // Grab all the rest of derived symbol fields.
602 for( const SCH_ITEM& item : derived->m_drawings[SCH_FIELD_T] )
603 {
604 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
605
606 if( field->IsMandatory() )
607 continue;
608
609 SCH_FIELD* newField = new SCH_FIELD( *field );
610 newField->SetParent( retv.get() );
611
612 SCH_FIELD* parentField = retv->GetField( field->GetName() );
613
614 if( !parentField )
615 {
616 retv->AddDrawItem( newField );
617 }
618 else
619 {
620 retv->RemoveDrawItem( parentField );
621 retv->AddDrawItem( newField );
622 }
623 }
624
625 if( !derived->m_keyWords.IsEmpty() )
626 retv->SetKeyWords( derived->m_keyWords );
627
628 if( !derived->m_fpFilters.IsEmpty() )
629 retv->SetFPFilters( derived->m_fpFilters );
630 }
631 }
632 else
633 {
634 // Cycle detected at immediate parent level - just copy this symbol
635 retv = std::make_unique<LIB_SYMBOL>( *this );
636 retv->m_parent.reset();
637 return retv;
638 }
639
640 // Now apply this symbol's overrides (the original "this" symbol)
641 retv->m_name = m_name;
642 retv->SetLibId( m_libId );
643
644 // Overwrite parent's mandatory fields for fields which are defined in this.
645 for( FIELD_T fieldId : MANDATORY_FIELDS )
646 {
647 if( !GetField( fieldId )->GetText().IsEmpty() )
648 *retv->GetField( fieldId ) = *GetField( fieldId );
649 }
650
651 // Grab all the rest of derived symbol fields.
652 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
653 {
654 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
655
656 // Mandatory fields were already resolved.
657 if( field->IsMandatory() )
658 continue;
659
660 SCH_FIELD* newField = new SCH_FIELD( *field );
661 newField->SetParent( retv.get() );
662
663 SCH_FIELD* parentField = retv->GetField( field->GetName() );
664
665 if( !parentField ) // Derived symbol field does not exist in parent symbol.
666 {
667 retv->AddDrawItem( newField );
668 }
669 else // Derived symbol field overrides the parent symbol field.
670 {
671 retv->RemoveDrawItem( parentField );
672 retv->AddDrawItem( newField );
673 }
674 }
675
676 // Use this symbol's keywords/filters if set, otherwise keep inherited ones
677 if( !m_keyWords.IsEmpty() )
678 retv->SetKeyWords( m_keyWords );
679
680 if( !m_fpFilters.IsEmpty() )
681 retv->SetFPFilters( m_fpFilters );
682
683 for( const auto& file : EmbeddedFileMap() )
684 {
686 retv->AddFile( newFile );
687 }
688
689 // Get excluded flags from the immediate parent (first in chain)
690 if( !parentChain.empty() )
691 {
692 retv->SetExcludedFromSim( parentChain.front()->GetExcludedFromSim() );
693 retv->SetExcludedFromBOM( parentChain.front()->GetExcludedFromBOM() );
694 retv->SetExcludedFromBoard( parentChain.front()->GetExcludedFromBoard() );
695 retv->SetExcludedFromPosFiles( parentChain.front()->GetExcludedFromPosFiles() );
696 }
697
698 retv->m_parent.reset();
699 }
700 else
701 {
702 retv = std::make_unique<LIB_SYMBOL>( *this );
703 }
704
705 return retv;
706}
707
708
710{
711 m_library = aLibrary;
712
713 if( m_searchTermsCache.empty() )
715
717}
718
719
720const wxString LIB_SYMBOL::GetLibraryName() const
721{
722 if( m_library )
723 return m_library->GetName();
724
725 return m_libId.GetLibNickname();
726}
727
728
730{
731 if( IsDerived() )
732 {
733 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
734
735 if( root.get() != this )
736 return root->IsLocalPower();
737 }
738
740}
741
742
744{
745 if( IsDerived() )
746 {
747 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
748
749 if( root.get() != this )
750 {
751 root->SetLocalPower();
752 return;
753 }
754 }
755
757}
758
759
761{
762 if( IsDerived() )
763 {
764 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
765
766 if( root.get() != this )
767 return root->IsGlobalPower();
768 }
769
771}
772
773
775{
776 return IsLocalPower() || IsGlobalPower();
777}
778
779
781{
782 if( IsDerived() )
783 {
784 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
785
786 if( root.get() != this )
787 {
788 root->SetGlobalPower();
789 return;
790 }
791 }
792
794}
795
796
798{
799 if( IsDerived() )
800 {
801 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
802
803 if( root.get() != this )
804 return root->IsNormal();
805 }
806
807 return m_options == ENTRY_NORMAL;
808}
809
810
812{
813 if( IsDerived() )
814 {
815 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
816
817 if( root.get() != this )
818 {
819 root->SetNormal();
820 return;
821 }
822 }
823
825}
826
827
828wxString LIB_SYMBOL::LetterSubReference( int aUnit, wxChar aInitialLetter )
829{
830 // use letters as notation. To allow more than 26 units, the sub ref
831 // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
832 // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
833 int u;
834 wxString suffix;
835
836 do
837 {
838 u = ( aUnit - 1 ) % 26;
839 suffix = wxChar( aInitialLetter + u ) + suffix;
840 aUnit = ( aUnit - u ) / 26;
841 } while( aUnit > 0 );
842
843 return suffix;
844}
845
846
847bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const
848{
849 wxString footprint;
850
851 for( const SCH_ITEM& item : m_drawings )
852 {
853 if( item.Type() == SCH_FIELD_T )
854 {
855 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
856
857 if( field.GetId() == FIELD_T::FOOTPRINT )
858 footprint = field.GetShownText( nullptr, false, aDepth + 1 );
859
860 if( token->IsSameAs( field.GetCanonicalName().Upper() ) || token->IsSameAs( field.GetName(), false ) )
861 {
862 *token = field.GetShownText( nullptr, false, aDepth + 1 );
863 return true;
864 }
865 }
866 }
867
868 // Consider missing simulation fields as empty, not un-resolved
869 if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) || token->IsSameAs( wxT( "SIM.TYPE" ) )
870 || token->IsSameAs( wxT( "SIM.PINS" ) ) || token->IsSameAs( wxT( "SIM.PARAMS" ) )
871 || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) || token->IsSameAs( wxT( "SIM.NAME" ) ) )
872 {
873 *token = wxEmptyString;
874 return true;
875 }
876
877 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
878 {
879 wxArrayString parts = wxSplit( footprint, ':' );
880
881 if( parts.Count() > 0 )
882 *token = parts[0];
883 else
884 *token = wxEmptyString;
885
886 return true;
887 }
888 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
889 {
890 wxArrayString parts = wxSplit( footprint, ':' );
891
892 if( parts.Count() > 1 )
893 *token = parts[std::min( 1, (int) parts.size() - 1 )];
894 else
895 *token = wxEmptyString;
896
897 return true;
898 }
899 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
900 {
901 *token = m_libId.GetUniStringLibNickname();
902 return true;
903 }
904 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
905 {
906 *token = m_libId.GetUniStringLibItemName();
907 return true;
908 }
909 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
910 {
911 *token = GetShownDescription( aDepth + 1 );
912 return true;
913 }
914 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
915 {
916 *token = GetShownKeyWords( aDepth + 1 );
917 return true;
918 }
919 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
920 {
921 *token = this->GetExcludedFromBOM() ? _( "Excluded from BOM" ) : wxString( "" );
922 return true;
923 }
924 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
925 {
926 *token = this->GetExcludedFromBoard() ? _( "Excluded from board" ) : wxString( "" );
927 return true;
928 }
929 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
930 {
931 *token = this->GetExcludedFromSim() ? _( "Excluded from simulation" ) : wxString( "" );
932 return true;
933 }
934 else if( token->IsSameAs( wxT( "DNP" ) ) )
935 {
936 *token = this->GetDNP() ? _( "DNP" ) : wxString( "" );
937 return true;
938 }
939
940 return false;
941}
942
943
944void LIB_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle,
945 const VECTOR2I& aOffset, bool aDimmed )
946{
947 wxASSERT( aPlotter != nullptr );
948
949 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
950 COLOR4D color = renderSettings->GetLayerColor( LAYER_DEVICE );
951 COLOR4D bg = renderSettings->GetBackgroundColor();
952
953 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
954 bg = COLOR4D::WHITE;
955
956 if( color.m_text && Schematic() )
957 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
958
959 if( aDimmed )
960 {
961 color.Desaturate();
962 color = color.Mix( bg, 0.5f );
963 }
964
965 aPlotter->SetColor( color );
966
967 for( SCH_ITEM& item : m_drawings )
968 {
969 // Do not plot private items
970 if( item.IsPrivate() )
971 continue;
972
973 // LIB_FIELDs are not plotted here, because this plot function is used to plot schematic
974 // items which have their own SCH_FIELDs
975 if( item.Type() == SCH_FIELD_T )
976 continue;
977
978 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
979 continue;
980
981 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
982 continue;
983
984 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
985 }
986}
987
988
989void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
990 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
991{
992 wxASSERT( aPlotter != nullptr );
993
994 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
995 COLOR4D color = renderSettings->GetLayerColor( LAYER_FIELDS );
996 COLOR4D bg = renderSettings->GetBackgroundColor();
997
998 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
999 bg = COLOR4D::WHITE;
1000
1001 if( aDimmed )
1002 {
1003 color.Desaturate();
1004 color = color.Mix( bg, 0.5f );
1005 }
1006
1007 aPlotter->SetColor( color );
1008
1009 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1010 {
1011 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1012
1013 if( !renderSettings->m_ShowHiddenFields && !field.IsVisible() )
1014 continue;
1015
1016 // The reference is a special case: we should change the basic text
1017 // to add '?' and the part id
1018 wxString tmp = field.GetText();
1019
1020 field.SetText( field.GetFullText( aUnit ) );
1021 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1022
1023 field.SetText( tmp );
1024 }
1025}
1026
1027
1029{
1030 std::vector<SCH_SHAPE*> potential_top_items;
1031 std::vector<SCH_ITEM*> bottom_items;
1032
1033 for( SCH_ITEM& item : m_drawings )
1034 {
1035 if( item.Type() == SCH_SHAPE_T )
1036 {
1037 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
1038
1039 if( shape.GetFillMode() == FILL_T::FILLED_WITH_COLOR )
1040 potential_top_items.push_back( &shape );
1041 else
1042 bottom_items.push_back( &item );
1043 }
1044 else
1045 {
1046 bottom_items.push_back( &item );
1047 }
1048 }
1049
1050 std::sort( potential_top_items.begin(), potential_top_items.end(),
1051 []( SCH_ITEM* a, SCH_ITEM* b )
1052 {
1053 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
1054 } );
1055
1056 for( SCH_SHAPE* item : potential_top_items )
1057 {
1058 for( SCH_ITEM* bottom_item : bottom_items )
1059 {
1060 if( item->GetBoundingBox().Contains( bottom_item->GetBoundingBox() ) )
1061 {
1062 item->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1063 break;
1064 }
1065 }
1066 }
1067}
1068
1069
1071{
1072 wxASSERT( aItem != nullptr );
1073
1074 // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
1075 // omitted when saving to disk.
1076 if( aItem->Type() == SCH_FIELD_T )
1077 {
1078 if( static_cast<SCH_FIELD*>( aItem )->IsMandatory() )
1079 return;
1080 }
1081
1082 LIB_ITEMS& items = m_drawings[aItem->Type()];
1083
1084 for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
1085 {
1086 if( &*i == aItem )
1087 {
1088 items.erase( i );
1089 cachePinCount();
1091 break;
1092 }
1093 }
1094}
1095
1096
1097void LIB_SYMBOL::AddDrawItem( SCH_ITEM* aItem, bool aSort )
1098{
1099 if( aItem )
1100 {
1101 aItem->SetParent( this );
1102
1103 m_drawings.push_back( aItem );
1104
1105 if( aSort )
1106 m_drawings.sort();
1107
1108 cachePinCount();
1110 }
1111}
1112
1113
1114std::vector<const SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle ) const
1115{
1116 if( IsDerived() )
1117 {
1118 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1119
1120 if( root.get() != this )
1121 return const_cast<const LIB_SYMBOL*>( root.get() )->GetGraphicalPins( aUnit, aBodyStyle );
1122 }
1123
1124 std::vector<const SCH_PIN*> pins;
1125
1126 /* Notes:
1127 * when aUnit == 0: no unit filtering
1128 * when aBodyStyle == 0: no body style filtering
1129 * when m_unit == 0, the item is common to all units
1130 * when m_bodyStyle == 0, the item is common to all body styles
1131 */
1132
1133 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1134 {
1135 // Unit filtering:
1136 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1137 continue;
1138
1139 // Body style filtering:
1140 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1141 continue;
1142
1143 pins.push_back( static_cast<const SCH_PIN*>( &item ) );
1144 }
1145
1146 return pins;
1147}
1148
1149
1150std::vector<SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle )
1151{
1152 if( IsDerived() )
1153 {
1154 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1155
1156 if( root.get() != this )
1157 return root->GetGraphicalPins( aUnit, aBodyStyle );
1158 }
1159
1160 std::vector<SCH_PIN*> pins;
1161
1162 /* Notes:
1163 * when aUnit == 0: no unit filtering
1164 * when aBodyStyle == 0: no body style filtering
1165 * when m_unit == 0, the item is common to all units
1166 * when m_bodyStyle == 0, the item is common to all body styles
1167 */
1168
1169 for( SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1170 {
1171 // Unit filtering:
1172 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1173 continue;
1174
1175 // Body style filtering:
1176 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1177 continue;
1178
1179 pins.push_back( static_cast<SCH_PIN*>( &item ) );
1180 }
1181
1182 return pins;
1183}
1184
1185
1186std::vector<LIB_SYMBOL::UNIT_PIN_INFO> LIB_SYMBOL::GetUnitPinInfo() const
1187{
1188 std::vector<UNIT_PIN_INFO> units;
1189
1190 int unitCount = std::max( GetUnitCount(), 1 );
1191
1192 auto compareByPosition =
1193 []( const SCH_PIN* a, const SCH_PIN* b )
1194 {
1195 VECTOR2I positionA = a->GetPosition();
1196 VECTOR2I positionB = b->GetPosition();
1197
1198 if( positionA.x != positionB.x )
1199 return positionA.x < positionB.x;
1200
1201 return positionA.y < positionB.y;
1202 };
1203
1204 for( int unitIdx = 1; unitIdx <= unitCount; ++unitIdx )
1205 {
1206 UNIT_PIN_INFO unitInfo;
1207 unitInfo.m_unitName = GetUnitDisplayName( unitIdx, false );
1208
1209 std::vector<const SCH_PIN*> pinList = GetGraphicalPins( unitIdx, 0 );
1210
1211 std::sort( pinList.begin(), pinList.end(), compareByPosition );
1212
1213 std::unordered_set<wxString> seenNumbers;
1214
1215 for( const SCH_PIN* basePin : pinList )
1216 {
1217 bool stackedValid = false;
1218 std::vector<wxString> expandedNumbers = basePin->GetStackedPinNumbers( &stackedValid );
1219
1220 if( stackedValid && !expandedNumbers.empty() )
1221 {
1222 for( const wxString& number : expandedNumbers )
1223 {
1224 if( seenNumbers.insert( number ).second )
1225 unitInfo.m_pinNumbers.push_back( number );
1226 }
1227
1228 continue;
1229 }
1230
1231 const wxString& number = basePin->GetNumber();
1232
1233 if( !number.IsEmpty() && seenNumbers.insert( number ).second )
1234 unitInfo.m_pinNumbers.push_back( number );
1235 }
1236
1237 units.push_back( std::move( unitInfo ) );
1238 }
1239
1240 return units;
1241}
1242
1243
1244std::vector<LIB_SYMBOL::LOGICAL_PIN> LIB_SYMBOL::GetLogicalPins( int aUnit, int aBodyStyle ) const
1245{
1246 std::vector<LOGICAL_PIN> out;
1247
1248 for( const SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1249 {
1250 bool valid = false;
1251 std::vector<wxString> expanded = pin->GetStackedPinNumbers( &valid );
1252
1253 if( valid && !expanded.empty() )
1254 {
1255 for( const wxString& num : expanded )
1256 {
1257 out.push_back( LOGICAL_PIN{ pin, num } );
1258 wxLogTrace( traceStackedPins, "GetLogicalPins: base='%s' -> '%s'", pin->GetShownNumber(), num );
1259 }
1260 }
1261 else
1262 {
1263 out.push_back( LOGICAL_PIN{ pin, pin->GetShownNumber() } );
1264 wxLogTrace( traceStackedPins, "GetLogicalPins: base='%s' (no expansion)", pin->GetShownNumber() );
1265 }
1266 }
1267
1268 return out;
1269}
1270
1271
1273{
1274 return m_pinCountCache;
1275}
1276
1277
1279{
1280 m_pinCountCache = 0;
1281
1282 for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) )
1283 {
1284 int pinCount = pin->GetStackedPinCount();
1285 m_pinCountCache += pinCount;
1286 }
1287}
1288
1289
1290const SCH_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aBodyStyle ) const
1291{
1292 for( const SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1293 {
1294 if( aNumber == pin->GetNumber() )
1295 return pin;
1296 }
1297
1298 return nullptr;
1299}
1300
1301
1302std::vector<SCH_PIN*> LIB_SYMBOL::GetPinsByNumber( const wxString& aNumber, int aUnit, int aBodyStyle )
1303{
1304 std::vector<SCH_PIN*> pins;
1305
1306 for( SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1307 {
1308 if( aNumber == pin->GetNumber() )
1309 pins.push_back( pin );
1310 }
1311
1312 return pins;
1313}
1314
1315
1316bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames, bool aTestType,
1317 bool aTestOrientation, bool aTestLength ) const
1318{
1319 for( const SCH_PIN* pin : GetGraphicalPins() )
1320 {
1321 wxASSERT( pin );
1322 bool foundMatch = false;
1323
1324 for( const SCH_PIN* otherPin : aOtherPart.GetGraphicalPins() )
1325 {
1326 wxASSERT( otherPin );
1327
1328 // Same unit?
1329 if( pin->GetUnit() != otherPin->GetUnit() )
1330 continue;
1331
1332 // Same body stype?
1333 if( pin->GetBodyStyle() != otherPin->GetBodyStyle() )
1334 continue;
1335
1336 // Same position?
1337 if( pin->GetPosition() != otherPin->GetPosition() )
1338 continue;
1339
1340 // Same number?
1341 if( aTestNums && ( pin->GetNumber() != otherPin->GetNumber() ) )
1342 continue;
1343
1344 // Same name?
1345 if( aTestNames && ( pin->GetName() != otherPin->GetName() ) )
1346 continue;
1347
1348 // Same electrical type?
1349 if( aTestType && ( pin->GetType() != otherPin->GetType() ) )
1350 continue;
1351
1352 // Same orientation?
1353 if( aTestOrientation && ( pin->GetOrientation() != otherPin->GetOrientation() ) )
1354 continue;
1355
1356 // Same length?
1357 if( aTestLength && ( pin->GetLength() != otherPin->GetLength() ) )
1358 continue;
1359
1360 foundMatch = true;
1361 break; // Match found so search is complete.
1362 }
1363
1364 if( !foundMatch )
1365 {
1366 // This means there was not an identical (according to the arguments)
1367 // pin at the same position in the other symbol.
1368 return true;
1369 }
1370 }
1371
1372 // The loop never gave up, so no conflicts were found.
1373 return false;
1374}
1375
1376std::vector<SCH_PIN*> LIB_SYMBOL::GetPins() const
1377{
1378 // Back-compat shim: return graphical pins for all units/body styles, violating const
1379 return const_cast<LIB_SYMBOL*>( this )->GetGraphicalPins( 0, 0 );
1380}
1381
1382
1383const BOX2I LIB_SYMBOL::GetUnitBoundingBox( int aUnit, int aBodyStyle, bool aIgnoreHiddenFields,
1384 bool aIgnoreLabelsOnInvisiblePins ) const
1385{
1386 BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works
1387
1388 if( IsDerived() )
1389 {
1390 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1391
1392 if( root.get() != this )
1393 bBox = root->GetUnitBoundingBox( aUnit, aBodyStyle, aIgnoreHiddenFields, aIgnoreLabelsOnInvisiblePins );
1394 }
1395
1396 for( const SCH_ITEM& item : m_drawings )
1397 {
1398 if( item.m_unit > 0 && m_unitCount > 1 && aUnit > 0 && aUnit != item.m_unit )
1399 continue;
1400
1401 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1402 continue;
1403
1404 if( aIgnoreHiddenFields && item.Type() == SCH_FIELD_T )
1405 {
1406 if( !static_cast<const SCH_FIELD&>( item ).IsVisible() )
1407 continue;
1408 }
1409
1410 if( item.Type() == SCH_PIN_T && !aIgnoreLabelsOnInvisiblePins )
1411 {
1412 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1413 bBox.Merge( pin.GetBoundingBox( true, true, false ) );
1414 }
1415 else
1416 {
1417 bBox.Merge( item.GetBoundingBox() );
1418 }
1419 }
1420
1421 return bBox;
1422}
1423
1424
1425const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aIncludePins,
1426 bool aIncludePrivateItems ) const
1427{
1428 BOX2I bbox;
1429
1430 for( const SCH_ITEM& item : m_drawings )
1431 {
1432 if( item.m_unit > 0 && aUnit > 0 && aUnit != item.m_unit )
1433 continue;
1434
1435 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1436 continue;
1437
1438 if( item.IsPrivate() && !aIncludePrivateItems )
1439 continue;
1440
1441 if( item.Type() == SCH_FIELD_T )
1442 continue;
1443
1444 if( item.Type() == SCH_PIN_T )
1445 {
1446 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1447
1448 if( pin.IsVisible() )
1449 {
1450 // Note: the roots of the pins are always included for symbols that don't have
1451 // a well-defined body.
1452
1453 if( aIncludePins )
1454 bbox.Merge( pin.GetBoundingBox( false, false, false ) );
1455 else
1456 bbox.Merge( pin.GetPinRoot() );
1457 }
1458 }
1459 else
1460 {
1461 bbox.Merge( item.GetBoundingBox() );
1462 }
1463 }
1464
1465 return bbox;
1466}
1467
1468
1476
1477
1484
1485
1487{
1488 AddDrawItem( aField );
1489}
1490
1491
1492void LIB_SYMBOL::SetFields( const std::vector<SCH_FIELD>& aFieldsList )
1493{
1495
1496 for( const SCH_FIELD& src : aFieldsList )
1497 {
1498 // drawings is a ptr_vector, new and copy an object on the heap.
1499 SCH_FIELD* field = new SCH_FIELD( src );
1500
1501 field->SetParent( this );
1502 m_drawings.push_back( field );
1503 }
1504
1505 m_drawings.sort();
1509}
1510
1511
1512void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aList, bool aVisibleOnly ) const
1513{
1514 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1515 {
1516 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1517
1518 if( aVisibleOnly )
1519 {
1520 if( !field->IsVisible() || field->GetText().IsEmpty() )
1521 continue;
1522 }
1523
1524 aList.push_back( const_cast<SCH_FIELD*>( field ) );
1525 }
1526
1527 std::sort( aList.begin(), aList.end(),
1528 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1529 {
1530 return lhs->GetOrdinal() < rhs->GetOrdinal();
1531 } );
1532}
1533
1534
1535void LIB_SYMBOL::CopyFields( std::vector<SCH_FIELD>& aList )
1536{
1537 std::vector<SCH_FIELD*> orderedFields;
1538
1539 GetFields( orderedFields );
1540
1541 for( SCH_FIELD* field : orderedFields )
1542 aList.emplace_back( *field );
1543}
1544
1545
1547{
1548 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id
1549
1550 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1551 ordinal = std::max( ordinal, static_cast<const SCH_FIELD*>( &item )->GetOrdinal() + 1 );
1552
1553 return ordinal;
1554}
1555
1556
1557const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const
1558{
1559 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1560 {
1561 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1562
1563 if( field->GetId() == aFieldType )
1564 return field;
1565 }
1566
1567 return nullptr;
1568}
1569
1570
1572{
1573 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1574 {
1575 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1576
1577 if( field->GetId() == aFieldType )
1578 return field;
1579 }
1580
1581 return nullptr;
1582}
1583
1584
1585const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const
1586{
1587 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1588 {
1589 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1590
1591 if( field.GetName() == aFieldName )
1592 return &field;
1593 }
1594
1595 return nullptr;
1596}
1597
1598
1599SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName )
1600{
1601 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1602 {
1603 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1604
1605 if( field.GetName() == aFieldName )
1606 return &field;
1607 }
1608
1609 return nullptr;
1610}
1611
1612
1614{
1615 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1616 {
1617 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1618
1619 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1620 return &field;
1621 }
1622
1623 return nullptr;
1624}
1625
1626
1627const SCH_FIELD* LIB_SYMBOL::FindFieldCaseInsensitive( const wxString& aFieldName ) const
1628{
1629 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1630 {
1631 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1632
1633 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1634 return &field;
1635 }
1636
1637 return nullptr;
1638}
1639
1640
1642{
1643 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
1644 wxASSERT( field != nullptr );
1645 return *field;
1646}
1647
1648
1650{
1651 const SCH_FIELD* field = GetField( FIELD_T::REFERENCE );
1652 wxASSERT( field != nullptr );
1653 return *field;
1654}
1655
1656
1658{
1659 const SCH_FIELD* field = GetField( FIELD_T::FOOTPRINT );
1660 wxASSERT( field != nullptr );
1661 return *field;
1662}
1663
1664
1666{
1667 const SCH_FIELD* field = GetField( FIELD_T::DATASHEET );
1668 wxASSERT( field != nullptr );
1669 return *field;
1670}
1671
1672
1674{
1675 const SCH_FIELD* field = GetField( FIELD_T::DESCRIPTION );
1676 wxASSERT( field != nullptr );
1677 return *field;
1678}
1679
1680
1682{
1683 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
1684
1685 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1686
1687 wxString prefix = refDesignator;
1688
1689 while( prefix.Length() )
1690 {
1691 wxUniCharRef last = prefix.Last();
1692
1693 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1694 prefix.RemoveLast();
1695 else
1696 break;
1697 }
1698
1699 // Avoid a prefix containing trailing/leading spaces
1700 prefix.Trim( true );
1701 prefix.Trim( false );
1702
1703 return prefix;
1704}
1705
1706
1707void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1708{
1709 for( SCH_ITEM& item : m_drawings )
1710 aFunction( &item );
1711}
1712
1713
1714void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1715{
1716 for( SCH_ITEM& item : m_drawings )
1717 item.Move( aOffset );
1718}
1719
1720
1721// Before V10 we didn't store the number of body styles in a symbol -- we just looked through all
1722// its drawings each time we wanted to know. This is now only used to set the count when a legacy
1723// symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count
1724// is always 1 or 2, and when 2 it is always a De Morgan pair.)
1726{
1727 for( const SCH_ITEM& item : m_drawings )
1728 {
1729 if( item.m_bodyStyle > BODY_STYLE::BASE )
1730 return true;
1731 }
1732
1733 if( IsDerived() )
1734 {
1735 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1736
1737 if( root.get() != this )
1738 return root->HasLegacyAlternateBodyStyle();
1739 }
1740
1741 return false;
1742}
1743
1744
1746{
1747 if( IsDerived() )
1748 {
1749 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1750
1751 if( root.get() != this )
1752 return root->GetMaxPinNumber();
1753 }
1754
1755 int maxPinNumber = 0;
1756
1757 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1758 {
1759 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1760 long currentPinNumber = 0;
1761
1762 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1763 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1764 }
1765
1766 return maxPinNumber;
1767}
1768
1769
1771{
1773
1774 for( SCH_ITEM& item : m_drawings )
1775 item.ClearTempFlags();
1776}
1777
1778
1780{
1782
1783 for( SCH_ITEM& item : m_drawings )
1784 item.ClearEditFlags();
1785}
1786
1787
1788SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint )
1789{
1790 for( SCH_ITEM& item : m_drawings )
1791 {
1792 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1793 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1794 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1795 {
1796 continue;
1797 }
1798
1799 if( item.HitTest( aPoint ) )
1800 return &item;
1801 }
1802
1803 return nullptr;
1804}
1805
1806
1807SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint,
1808 const TRANSFORM& aTransform )
1809{
1810 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1811 * VECTOR2I& pt ) to search items.
1812 * because this function uses DefaultTransform as orient/mirror matrix
1813 * we temporary copy aTransform in DefaultTransform
1814 */
1815 TRANSFORM transform = DefaultTransform;
1816 DefaultTransform = aTransform;
1817
1818 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1819
1820 // Restore matrix
1821 DefaultTransform = transform;
1822
1823 return item;
1824}
1825
1826
1827INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
1828{
1829 // The part itself is never inspected, only its children
1830 for( SCH_ITEM& item : m_drawings )
1831 {
1832 if( item.IsType( aScanTypes ) )
1833 {
1834 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1835 return INSPECT_RESULT::QUIT;
1836 }
1837 }
1838
1840}
1841
1842
1843void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1844{
1845 // A LIB_SYMBOL must always have at least one unit. Passing a value less than 1 would
1846 // erase the mandatory fields (which all have m_unit == 0), leaving the symbol in a
1847 // broken state that crashes later when callers dereference GetReferenceField() etc.
1848 wxCHECK_RET( aCount >= 1,
1849 wxString::Format( wxT( "Invalid unit count %d, ignoring." ), aCount ) );
1850
1851 if( m_unitCount == aCount )
1852 return;
1853
1854 if( aCount < m_unitCount )
1855 {
1856 // Iterate each drawing-type bucket and erase items that belong to units > aCount.
1857 for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
1858 {
1859 auto it = m_drawings.begin( type );
1860
1861 while( it != m_drawings.end( type ) )
1862 {
1863 if( it->m_unit > aCount )
1864 it = m_drawings.erase( it ); // returns next iterator
1865 else
1866 ++it;
1867 }
1868 }
1869 }
1870 else if( aDuplicateDrawItems )
1871 {
1872 int prevCount = m_unitCount;
1873
1874 // Temporary storage for new items, as adding new items directly to
1875 // m_drawings may cause the buffer reallocation which invalidates the
1876 // iterators
1877 std::vector<SCH_ITEM*> tmp;
1878
1879 for( SCH_ITEM& item : m_drawings )
1880 {
1881 if( item.m_unit != 1 )
1882 continue;
1883
1884 for( int j = prevCount + 1; j <= aCount; j++ )
1885 {
1886 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1887 newItem->m_unit = j;
1888 tmp.push_back( newItem );
1889 }
1890 }
1891
1892 for( SCH_ITEM* item : tmp )
1893 m_drawings.push_back( item );
1894 }
1895
1896 m_drawings.sort();
1897 m_unitCount = aCount;
1898}
1899
1900
1902{
1903 if( IsDerived() )
1904 {
1905 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1906
1907 if( root.get() != this )
1908 return root->GetUnitCount();
1909 }
1910
1911 return m_unitCount;
1912}
1913
1914
1915void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins )
1916{
1917 int prevCount = GetBodyStyleCount();
1918
1919 if( prevCount == aCount )
1920 return;
1921
1922 // Duplicate items to create the converted shape
1923 if( prevCount < aCount )
1924 {
1925 if( aDuplicateDrawItems || aDuplicatePins )
1926 {
1927 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1928
1929 for( SCH_ITEM& item : m_drawings )
1930 {
1931 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
1932 continue;
1933
1934 if( item.m_bodyStyle == 1 )
1935 {
1936 for( int j = prevCount + 1; j <= aCount; j++ )
1937 {
1938 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1939 newItem->m_bodyStyle = j;
1940 tmp.push_back( newItem );
1941 }
1942 }
1943 }
1944
1945 // Transfer the new pins to the LIB_SYMBOL.
1946 for( SCH_ITEM* item : tmp )
1947 m_drawings.push_back( item );
1948 }
1949 }
1950 else
1951 {
1952 // Delete converted shape items because the converted shape does not exist
1954
1955 while( i != m_drawings.end() )
1956 {
1957 if( i->m_bodyStyle > aCount )
1958 i = m_drawings.erase( i );
1959 else
1960 ++i;
1961 }
1962 }
1963
1964 m_drawings.sort();
1965}
1966
1967
1968std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1969{
1970 std::vector<SCH_ITEM*> unitItems;
1971
1972 for( SCH_ITEM& item : m_drawings )
1973 {
1974 if( item.Type() == SCH_FIELD_T )
1975 continue;
1976
1977 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1978 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1979 {
1980 unitItems.push_back( &item );
1981 }
1982 }
1983
1984 return unitItems;
1985}
1986
1987
1988std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
1989{
1990 std::vector<LIB_SYMBOL_UNIT> units;
1991
1992 for( SCH_ITEM& item : m_drawings )
1993 {
1994 if( item.Type() == SCH_FIELD_T )
1995 continue;
1996
1997 int unit = item.GetUnit();
1998 int bodyStyle = item.GetBodyStyle();
1999
2000 auto it = std::find_if( units.begin(), units.end(),
2001 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
2002 {
2003 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
2004 } );
2005
2006 if( it == units.end() )
2007 {
2008 LIB_SYMBOL_UNIT newUnit;
2009 newUnit.m_unit = item.GetUnit();
2010 newUnit.m_bodyStyle = item.GetBodyStyle();
2011 newUnit.m_items.push_back( &item );
2012 units.emplace_back( newUnit );
2013 }
2014 else
2015 {
2016 it->m_items.push_back( &item );
2017 }
2018 }
2019
2020 return units;
2021}
2022
2023
2024#define REPORT( msg ) \
2025 { \
2026 if( aReporter ) \
2027 aReporter->Report( msg ); \
2028 }
2029#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
2030
2031int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
2032{
2033 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
2034
2035 if( m_me == aRhs.m_me )
2036 return 0;
2037
2038 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2039 {
2040 if( int tmp = m_name.Cmp( aRhs.m_name ) )
2041 return tmp;
2042
2043 if( int tmp = m_libId.compare( aRhs.m_libId ) )
2044 return tmp;
2045
2046 if( m_parent.lock() < aRhs.m_parent.lock() )
2047 return -1;
2048
2049 if( m_parent.lock() > aRhs.m_parent.lock() )
2050 return 1;
2051 }
2052
2053 int retv = 0;
2054
2055 if( m_options != aRhs.m_options )
2056 {
2057 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
2058 REPORT( _( "Power flag differs." ) );
2059
2060 if( !aReporter )
2061 return retv;
2062 }
2063
2064 if( int tmp = m_unitCount - aRhs.m_unitCount )
2065 {
2066 retv = tmp;
2067 REPORT( _( "Unit count differs." ) );
2068
2069 if( !aReporter )
2070 return retv;
2071 }
2072
2073 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
2074
2075 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
2076 std::set<const SCH_FIELD*> aFields;
2077 std::set<const SCH_PIN*> aPins;
2078
2079 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
2080 {
2081 if( it->Type() == SCH_SHAPE_T )
2082 aShapes.insert( &( *it ) );
2083 else if( it->Type() == SCH_FIELD_T )
2084 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2085 else if( it->Type() == SCH_PIN_T )
2086 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2087 }
2088
2089 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
2090 std::set<const SCH_FIELD*> bFields;
2091 std::set<const SCH_PIN*> bPins;
2092
2093 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
2094 {
2095 if( it->Type() == SCH_SHAPE_T )
2096 bShapes.insert( &( *it ) );
2097 else if( it->Type() == SCH_FIELD_T )
2098 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2099 else if( it->Type() == SCH_PIN_T )
2100 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2101 }
2102
2103 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
2104 {
2105 retv = tmp;
2106 REPORT( _( "Graphic item count differs." ) );
2107
2108 if( !aReporter )
2109 return retv;
2110 }
2111 else
2112 {
2113 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
2114 {
2115 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
2116 {
2117 retv = tmp2;
2118 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
2119 ITEM_DESC( *bIt ) ) );
2120
2121 if( !aReporter )
2122 return retv;
2123 }
2124 }
2125 }
2126
2127 for( const SCH_PIN* aPin : aPins )
2128 {
2129 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
2130
2131 if( !bPin )
2132 {
2133 retv = 1;
2134 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
2135
2136 if( !aReporter )
2137 return retv;
2138 }
2139 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
2140 {
2141 retv = tmp;
2142 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
2143 ITEM_DESC( bPin ) ) );
2144
2145 if( !aReporter )
2146 return retv;
2147 }
2148 }
2149
2150 for( const SCH_PIN* bPin : bPins )
2151 {
2152 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
2153
2154 if( !aPin )
2155 {
2156 retv = 1;
2157 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
2158
2159 if( !aReporter )
2160 return retv;
2161 }
2162 }
2163
2164 for( const SCH_FIELD* aField : aFields )
2165 {
2166 const SCH_FIELD* bField = nullptr;
2167
2168 if( aField->IsMandatory() )
2169 bField = aRhs.GetField( aField->GetId() );
2170 else
2171 bField = aRhs.GetField( aField->GetName() );
2172
2173 if( !bField )
2174 {
2175 retv = 1;
2176 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
2177
2178 if( !aReporter )
2179 return retv;
2180 }
2181 else
2182 {
2183 int tmp = 0;
2184
2185 // For EQUALITY comparison, we need to compare field content directly
2186 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
2187 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
2188 {
2189 // Compare field text content
2190 tmp = aField->GetText().compare( bField->GetText() );
2191 }
2192
2193 if( tmp == 0 )
2194 {
2195 // Fall back to base class comparison for other properties
2196 tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags );
2197 }
2198
2199 if( tmp != 0 )
2200 {
2201 retv = tmp;
2202 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
2203 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
2204
2205 if( !aReporter )
2206 return retv;
2207 }
2208 }
2209 }
2210
2211 for( const SCH_FIELD* bField : bFields )
2212 {
2213 const SCH_FIELD* aField = nullptr;
2214
2215 if( bField->IsMandatory() )
2216 aField = aRhs.GetField( bField->GetId() );
2217 else
2218 aField = aRhs.GetField( bField->GetName() );
2219
2220 if( !aField )
2221 {
2222 retv = 1;
2223 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
2224
2225 if( !aReporter )
2226 return retv;
2227 }
2228 }
2229
2230 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
2231 {
2232 retv = tmp;
2233 REPORT( _( "Footprint filter count differs." ) );
2234
2235 if( !aReporter )
2236 return retv;
2237 }
2238 else
2239 {
2240 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
2241 {
2242 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
2243 {
2244 retv = tmp2;
2245 REPORT( _( "Footprint filters differ." ) );
2246
2247 if( !aReporter )
2248 return retv;
2249 }
2250 }
2251 }
2252
2253 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
2254 {
2255 retv = tmp;
2256 REPORT( _( "Symbol keywords differ." ) );
2257
2258 if( !aReporter )
2259 return retv;
2260 }
2261
2262 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
2263 {
2264 retv = tmp;
2265 REPORT( _( "Symbol pin name offsets differ." ) );
2266
2267 if( !aReporter )
2268 return retv;
2269 }
2270
2271 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2272 {
2273 if( m_showPinNames != aRhs.m_showPinNames )
2274 {
2275 retv = ( m_showPinNames ) ? 1 : -1;
2276 REPORT( _( "Show pin names settings differ." ) );
2277
2278 if( !aReporter )
2279 return retv;
2280 }
2281
2283 {
2284 retv = ( m_showPinNumbers ) ? 1 : -1;
2285 REPORT( _( "Show pin numbers settings differ." ) );
2286
2287 if( !aReporter )
2288 return retv;
2289 }
2290
2292 {
2293 retv = ( m_excludedFromSim ) ? -1 : 1;
2294 REPORT( _( "Exclude from simulation settings differ." ) );
2295
2296 if( !aReporter )
2297 return retv;
2298 }
2299
2301 {
2302 retv = ( m_excludedFromBOM ) ? -1 : 1;
2303 REPORT( _( "Exclude from bill of materials settings differ." ) );
2304
2305 if( !aReporter )
2306 return retv;
2307 }
2308
2310 {
2311 retv = ( m_excludedFromBoard ) ? -1 : 1;
2312 REPORT( _( "Exclude from board settings differ." ) );
2313
2314 if( !aReporter )
2315 return retv;
2316 }
2317
2319 {
2320 retv = ( m_excludedFromPosFiles ) ? -1 : 1;
2321 REPORT( _( "Exclude from position files settings differ." ) );
2322
2323 if( !aReporter )
2324 return retv;
2325 }
2326 }
2327
2328 if( !aReporter )
2329 {
2330 if( m_unitsLocked != aRhs.m_unitsLocked )
2331 return ( m_unitsLocked ) ? 1 : -1;
2332
2333 // Compare unit display names...
2335 return -1;
2336 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
2337 return 1;
2338
2339 // ... and body style names.
2341 return -1;
2342 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
2343 return 1;
2344 }
2345
2346 return retv;
2347}
2348
2349
2350int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2351{
2352 if( Type() != aOther.Type() )
2353 return Type() - aOther.Type();
2354
2355 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
2356
2357 return Compare( *tmp, aCompareFlags );
2358}
2359
2360
2361double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2362{
2363 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
2364
2365 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
2366 double similarity = 0.0;
2367 int totalItems = 0;
2368
2369 if( m_Uuid == aOther.m_Uuid )
2370 return 1.0;
2371
2372 for( const SCH_ITEM& item : m_drawings )
2373 {
2374 totalItems += 1;
2375 double max_similarity = 0.0;
2376
2377 for( const SCH_ITEM& otherItem : other.m_drawings )
2378 {
2379 double temp_similarity = item.Similarity( otherItem );
2380 max_similarity = std::max( max_similarity, temp_similarity );
2381
2382 if( max_similarity == 1.0 )
2383 break;
2384 }
2385
2386 similarity += max_similarity;
2387 }
2388
2389 for( const SCH_PIN* pin : GetGraphicalPins( 0, 0 ) )
2390 {
2391 totalItems += 1;
2392 double max_similarity = 0.0;
2393
2394 for( const SCH_PIN* otherPin : other.GetGraphicalPins( 0, 0 ) )
2395 {
2396 double temp_similarity = pin->Similarity( *otherPin );
2397 max_similarity = std::max( max_similarity, temp_similarity );
2398
2399 if( max_similarity == 1.0 )
2400 break;
2401 }
2402
2403 similarity += max_similarity;
2404 }
2405
2406 if( totalItems == 0 )
2407 similarity = 0.0;
2408 else
2409 similarity /= totalItems;
2410
2412 similarity *= 0.9;
2413
2415 similarity *= 0.9;
2416
2418 similarity *= 0.9;
2419
2421 similarity *= 0.9;
2422
2423 if( m_flags != other.m_flags )
2424 similarity *= 0.9;
2425
2426 if( m_unitCount != other.m_unitCount )
2427 similarity *= 0.5;
2428
2429 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
2430 similarity *= 0.5;
2431 else if( m_bodyStyleNames != other.m_bodyStyleNames )
2432 similarity *= 0.9;
2433
2434 if( m_pinNameOffset != other.m_pinNameOffset )
2435 similarity *= 0.9;
2436
2437 if( m_showPinNames != other.m_showPinNames )
2438 similarity *= 0.9;
2439
2440 if( m_showPinNumbers != other.m_showPinNumbers )
2441 similarity *= 0.9;
2442
2443 return similarity;
2444}
2445
2446
2448{
2449 return static_cast<EMBEDDED_FILES*>( this );
2450}
2451
2452
2454{
2455 return static_cast<const EMBEDDED_FILES*>( this );
2456}
2457
2458
2459void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2460{
2461 std::set<const LIB_SYMBOL*> visited;
2462 visited.insert( this );
2463
2464 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2465
2466 while( parent )
2467 {
2468 // Cycle detected - parent chain points back to an already visited symbol
2469 if( visited.count( parent.get() ) )
2470 {
2471 wxLogTrace( traceSymbolInheritance,
2472 wxT( "AppendParentEmbeddedFiles: Circular inheritance detected in "
2473 "symbol '%s' (lib: %s)" ),
2474 m_name, m_libId.GetLibNickname().wx_str() );
2475 break;
2476 }
2477
2478 visited.insert( parent.get() );
2479 aStack.push_back( parent->GetEmbeddedFiles() );
2480 parent = parent->GetParent().lock();
2481 }
2482}
2483
2484
2485std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2486{
2487 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2488
2489 std::set<KIFONT::OUTLINE_FONT*> fonts;
2490
2491 for( const SCH_ITEM& item : m_drawings )
2492 {
2493 if( item.Type() == SCH_TEXT_T )
2494 {
2495 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2496
2497 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2498 {
2499 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2500 auto permission = outline->GetEmbeddingPermission();
2501
2502 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2503 {
2504 fonts.insert( outline );
2505 }
2506 }
2507 }
2508 }
2509
2510 return fonts;
2511}
2512
2513
2515{
2516 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2517
2518 for( KIFONT::OUTLINE_FONT* font : fonts )
2519 {
2520 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2522 }
2523}
2524
2525
2526std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2527{
2528 for( const std::set<wxString>& group : m_jumperPinGroups )
2529 {
2530 if( group.contains( aPinNumber ) )
2531 return group;
2532 }
2533
2534 return std::nullopt;
2535}
2536
2537static struct LIB_SYMBOL_DESC
2538{
2540 {
2544
2545 const wxString groupFields = _HKI( "Fields" );
2546
2549 groupFields );
2552 groupFields );
2555 groupFields );
2558 groupFields );
2561 groupFields );
2562
2563 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2564
2565 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2568 groupSymbolDef );
2569 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2572 groupSymbolDef );
2573
2574 const wxString groupPinDisplay = _HKI( "Pin Display" );
2575
2576 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2578 groupPinDisplay );
2579 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2581 groupPinDisplay );
2582 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2585 groupPinDisplay );
2586 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2588 groupPinDisplay );
2589
2590 const wxString groupAttributes = _HKI( "Attributes" );
2591
2592 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2595 groupAttributes );
2596 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
2599 groupAttributes );
2600 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2603 groupAttributes );
2604 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
2607 groupAttributes );
2608
2609 const wxString groupUnits = _HKI( "Units and Body Styles" );
2610
2611 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2613 groupUnits );
2614 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2617 groupUnits );
2618
2619 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2620 {
2621 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2622 return symbol->IsMultiBodyStyle();
2623
2624 return false;
2625 };
2626
2629 groupUnits )
2630 .SetAvailableFunc( multiBodyStyle )
2632 []( INSPECTABLE* aItem )
2633 {
2634 wxPGChoices choices;
2635
2636 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2637 {
2638 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2639 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2640 }
2641
2642 return choices;
2643 } );
2644 }
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.
EMBEDDED_FILES()=default
const std::map< wxString, EMBEDDED_FILE * > & EmbeddedFileMap() const
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:115
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:79
LIB_ITEMS_CONTAINER m_drawings
Definition lib_symbol.h:897
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:345
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:148
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:175
void SetGlobalPower()
std::weak_ptr< LIB_SYMBOL > & GetParent()
Definition lib_symbol.h:110
wxString GetBodyStyleProp() const override
Definition lib_symbol.h:475
LIBRENTRYOPTIONS m_options
Special symbol features such as POWER or NORMAL.
Definition lib_symbol.h:895
wxString GetRefProp() const
Definition lib_symbol.h:364
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:465
wxString m_shownDescriptionCache
Definition lib_symbol.h:921
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
SCH_FIELD & GetDatasheetField()
Return reference to the datasheet field.
Definition lib_symbol.h:341
void RefreshLibraryTreeCaches()
std::weak_ptr< LIB_SYMBOL > m_parent
Use for inherited symbols.
Definition lib_symbol.h:879
void SetExcludedFromBoardProp(bool aExclude)
Definition lib_symbol.h:511
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:913
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:907
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
void SetKeywordsProp(const wxString &aKeywords)
Definition lib_symbol.h:409
bool IsDerived() const
Definition lib_symbol.h:196
std::map< int, wxString > & GetUnitDisplayNames()
Definition lib_symbol.h:747
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:891
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:517
void SetLib(LEGACY_SYMBOL_LIB *aLibrary)
bool GetPowerSymbolProp() const
Definition lib_symbol.h:414
bool IsMultiBodyStyle() const override
Definition lib_symbol.h:771
int GetMaxPinNumber() const
std::vector< SEARCH_TERM > m_searchTermsCache
Definition lib_symbol.h:919
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:337
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:900
void SetUnitsInterchangeableProp(bool aInterchangeable)
Definition lib_symbol.h:470
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
LEGACY_SYMBOL_LIB * m_library
Definition lib_symbol.h:899
bool GetExcludedFromPosFilesProp() const
Definition lib_symbol.h:516
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
wxString m_keyWords
Search keywords.
Definition lib_symbol.h:901
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:394
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:369
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:141
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:878
wxString GetValueProp() const
Definition lib_symbol.h:374
bool GetExcludedFromBOMProp() const
Definition lib_symbol.h:496
void SetKeyWords(const wxString &aKeyWords)
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:329
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:455
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:88
bool GetPinNamesInsideProp() const
Definition lib_symbol.h:442
const std::vector< wxString > & GetBodyStyleNames() const
Definition lib_symbol.h:784
void SetBodyStyleProp(const wxString &aBodyStyle) override
Definition lib_symbol.h:480
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:885
void SetExcludedFromSimProp(bool aExclude)
Definition lib_symbol.h:491
bool GetExcludedFromBoardProp() const
Definition lib_symbol.h:506
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:883
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:154
void SetFootprintProp(const wxString &aFootprint)
Definition lib_symbol.h:389
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:781
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:888
wxArrayString m_fpFilters
List of suitable footprint names for the symbol (wild card names accepted).
Definition lib_symbol.h:902
void Move(const VECTOR2I &aOffset) override
Move the symbol aOffset.
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:486
int GetBodyStyleCount() const override
Definition lib_symbol.h:773
void SetDatasheetProp(const wxString &aDatasheet)
Definition lib_symbol.h:399
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:419
void SetExcludedFromBOMProp(bool aExclude)
Definition lib_symbol.h:501
int m_unitCount
Number of units (parts) per package.
Definition lib_symbol.h:887
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
wxString GetKeywordsProp() const
Definition lib_symbol.h:404
std::vector< wxString > m_bodyStyleNames
Definition lib_symbol.h:914
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:251
void SetValueProp(const wxString &aValue)
Definition lib_symbol.h:379
int GetPinCount() override
std::map< wxString, wxString > m_chooserFieldsCache
Definition lib_symbol.h:922
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:920
bool GetLocalPowerSymbolProp() const
Definition lib_symbol.h:427
void deleteAllFields()
LIB_ID GetLIB_ID() const override
Definition lib_symbol.h:143
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:911
void SetUnitProp(int aUnits)
Definition lib_symbol.h:460
wxString GetFootprintProp() const
Definition lib_symbol.h:384
void SetPinNamesInsideProp(bool aInside)
Definition lib_symbol.h:447
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:881
void EmbedFonts() override
void SetLocalPowerSymbolProp(bool aIsLocalPower)
Definition lib_symbol.h:432
virtual void SetName(const wxString &aName)
void SetNormal()
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:333
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)
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
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:332
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:296
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:55
@ ENTRY_LOCAL_POWER
Definition lib_symbol.h:57
@ ENTRY_GLOBAL_POWER
Definition lib_symbol.h:56
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
Definition lib_symbol.h:49
#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:586
std::vector< wxString > m_pinNumbers
Definition lib_symbol.h:600
int m_bodyStyle
The alternate body style of the unit.
Definition lib_symbol.h:67
std::vector< SCH_ITEM * > m_items
The items unique to this unit and alternate body style.
Definition lib_symbol.h:68
int m_unit
The unit number.
Definition lib_symbol.h:66
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