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
1470{
1471 // cacheSearchTerms() reads the shown-description cache, so refresh it first.
1474 cachePinCount();
1476}
1477
1478
1485
1486
1488{
1489 AddDrawItem( aField );
1490}
1491
1492
1493void LIB_SYMBOL::SetFields( const std::vector<SCH_FIELD>& aFieldsList )
1494{
1496
1497 for( const SCH_FIELD& src : aFieldsList )
1498 {
1499 // drawings is a ptr_vector, new and copy an object on the heap.
1500 SCH_FIELD* field = new SCH_FIELD( src );
1501
1502 field->SetParent( this );
1503 m_drawings.push_back( field );
1504 }
1505
1506 m_drawings.sort();
1510}
1511
1512
1513void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aList, bool aVisibleOnly ) const
1514{
1515 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1516 {
1517 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1518
1519 if( aVisibleOnly )
1520 {
1521 if( !field->IsVisible() || field->GetText().IsEmpty() )
1522 continue;
1523 }
1524
1525 aList.push_back( const_cast<SCH_FIELD*>( field ) );
1526 }
1527
1528 std::sort( aList.begin(), aList.end(),
1529 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1530 {
1531 return lhs->GetOrdinal() < rhs->GetOrdinal();
1532 } );
1533}
1534
1535
1536void LIB_SYMBOL::CopyFields( std::vector<SCH_FIELD>& aList )
1537{
1538 std::vector<SCH_FIELD*> orderedFields;
1539
1540 GetFields( orderedFields );
1541
1542 for( SCH_FIELD* field : orderedFields )
1543 aList.emplace_back( *field );
1544}
1545
1546
1548{
1549 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id
1550
1551 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1552 ordinal = std::max( ordinal, static_cast<const SCH_FIELD*>( &item )->GetOrdinal() + 1 );
1553
1554 return ordinal;
1555}
1556
1557
1558const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const
1559{
1560 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1561 {
1562 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1563
1564 if( field->GetId() == aFieldType )
1565 return field;
1566 }
1567
1568 return nullptr;
1569}
1570
1571
1573{
1574 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1575 {
1576 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1577
1578 if( field->GetId() == aFieldType )
1579 return field;
1580 }
1581
1582 return nullptr;
1583}
1584
1585
1586const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const
1587{
1588 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1589 {
1590 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1591
1592 if( field.GetName() == aFieldName )
1593 return &field;
1594 }
1595
1596 return nullptr;
1597}
1598
1599
1600SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName )
1601{
1602 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1603 {
1604 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1605
1606 if( field.GetName() == aFieldName )
1607 return &field;
1608 }
1609
1610 return nullptr;
1611}
1612
1613
1615{
1616 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1617 {
1618 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1619
1620 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1621 return &field;
1622 }
1623
1624 return nullptr;
1625}
1626
1627
1628const SCH_FIELD* LIB_SYMBOL::FindFieldCaseInsensitive( const wxString& aFieldName ) const
1629{
1630 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1631 {
1632 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1633
1634 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1635 return &field;
1636 }
1637
1638 return nullptr;
1639}
1640
1641
1643{
1644 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
1645 wxASSERT( field != nullptr );
1646 return *field;
1647}
1648
1649
1651{
1652 const SCH_FIELD* field = GetField( FIELD_T::REFERENCE );
1653 wxASSERT( field != nullptr );
1654 return *field;
1655}
1656
1657
1659{
1660 const SCH_FIELD* field = GetField( FIELD_T::FOOTPRINT );
1661 wxASSERT( field != nullptr );
1662 return *field;
1663}
1664
1665
1667{
1668 const SCH_FIELD* field = GetField( FIELD_T::DATASHEET );
1669 wxASSERT( field != nullptr );
1670 return *field;
1671}
1672
1673
1675{
1676 const SCH_FIELD* field = GetField( FIELD_T::DESCRIPTION );
1677 wxASSERT( field != nullptr );
1678 return *field;
1679}
1680
1681
1683{
1684 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
1685
1686 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1687
1688 wxString prefix = refDesignator;
1689
1690 while( prefix.Length() )
1691 {
1692 wxUniCharRef last = prefix.Last();
1693
1694 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1695 prefix.RemoveLast();
1696 else
1697 break;
1698 }
1699
1700 // Avoid a prefix containing trailing/leading spaces
1701 prefix.Trim( true );
1702 prefix.Trim( false );
1703
1704 return prefix;
1705}
1706
1707
1708void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1709{
1710 for( SCH_ITEM& item : m_drawings )
1711 aFunction( &item );
1712}
1713
1714
1715void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1716{
1717 for( SCH_ITEM& item : m_drawings )
1718 item.Move( aOffset );
1719}
1720
1721
1722// Before V10 we didn't store the number of body styles in a symbol -- we just looked through all
1723// its drawings each time we wanted to know. This is now only used to set the count when a legacy
1724// symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count
1725// is always 1 or 2, and when 2 it is always a De Morgan pair.)
1727{
1728 for( const SCH_ITEM& item : m_drawings )
1729 {
1730 if( item.m_bodyStyle > BODY_STYLE::BASE )
1731 return true;
1732 }
1733
1734 if( IsDerived() )
1735 {
1736 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1737
1738 if( root.get() != this )
1739 return root->HasLegacyAlternateBodyStyle();
1740 }
1741
1742 return false;
1743}
1744
1745
1747{
1748 if( IsDerived() )
1749 {
1750 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1751
1752 if( root.get() != this )
1753 return root->GetMaxPinNumber();
1754 }
1755
1756 int maxPinNumber = 0;
1757
1758 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1759 {
1760 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1761 long currentPinNumber = 0;
1762
1763 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1764 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1765 }
1766
1767 return maxPinNumber;
1768}
1769
1770
1772{
1774
1775 for( SCH_ITEM& item : m_drawings )
1776 item.ClearTempFlags();
1777}
1778
1779
1781{
1783
1784 for( SCH_ITEM& item : m_drawings )
1785 item.ClearEditFlags();
1786}
1787
1788
1789SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint )
1790{
1791 for( SCH_ITEM& item : m_drawings )
1792 {
1793 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1794 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1795 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1796 {
1797 continue;
1798 }
1799
1800 if( item.HitTest( aPoint ) )
1801 return &item;
1802 }
1803
1804 return nullptr;
1805}
1806
1807
1808SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint,
1809 const TRANSFORM& aTransform )
1810{
1811 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1812 * VECTOR2I& pt ) to search items.
1813 * because this function uses DefaultTransform as orient/mirror matrix
1814 * we temporary copy aTransform in DefaultTransform
1815 */
1816 TRANSFORM transform = DefaultTransform;
1817 DefaultTransform = aTransform;
1818
1819 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1820
1821 // Restore matrix
1822 DefaultTransform = transform;
1823
1824 return item;
1825}
1826
1827
1828INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
1829{
1830 // The part itself is never inspected, only its children
1831 for( SCH_ITEM& item : m_drawings )
1832 {
1833 if( item.IsType( aScanTypes ) )
1834 {
1835 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1836 return INSPECT_RESULT::QUIT;
1837 }
1838 }
1839
1841}
1842
1843
1844void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1845{
1846 // A LIB_SYMBOL must always have at least one unit. Passing a value less than 1 would
1847 // erase the mandatory fields (which all have m_unit == 0), leaving the symbol in a
1848 // broken state that crashes later when callers dereference GetReferenceField() etc.
1849 wxCHECK_RET( aCount >= 1,
1850 wxString::Format( wxT( "Invalid unit count %d, ignoring." ), aCount ) );
1851
1852 if( m_unitCount == aCount )
1853 return;
1854
1855 if( aCount < m_unitCount )
1856 {
1857 // Iterate each drawing-type bucket and erase items that belong to units > aCount.
1858 for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
1859 {
1860 auto it = m_drawings.begin( type );
1861
1862 while( it != m_drawings.end( type ) )
1863 {
1864 if( it->m_unit > aCount )
1865 it = m_drawings.erase( it ); // returns next iterator
1866 else
1867 ++it;
1868 }
1869 }
1870 }
1871 else if( aDuplicateDrawItems )
1872 {
1873 int prevCount = m_unitCount;
1874
1875 // Temporary storage for new items, as adding new items directly to
1876 // m_drawings may cause the buffer reallocation which invalidates the
1877 // iterators
1878 std::vector<SCH_ITEM*> tmp;
1879
1880 for( SCH_ITEM& item : m_drawings )
1881 {
1882 if( item.m_unit != 1 )
1883 continue;
1884
1885 for( int j = prevCount + 1; j <= aCount; j++ )
1886 {
1887 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1888 newItem->m_unit = j;
1889 tmp.push_back( newItem );
1890 }
1891 }
1892
1893 for( SCH_ITEM* item : tmp )
1894 m_drawings.push_back( item );
1895 }
1896
1897 m_drawings.sort();
1898 m_unitCount = aCount;
1899}
1900
1901
1903{
1904 if( IsDerived() )
1905 {
1906 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1907
1908 if( root.get() != this )
1909 return root->GetUnitCount();
1910 }
1911
1912 return m_unitCount;
1913}
1914
1915
1916void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins )
1917{
1918 int prevCount = GetBodyStyleCount();
1919
1920 if( prevCount == aCount )
1921 return;
1922
1923 // Duplicate items to create the converted shape
1924 if( prevCount < aCount )
1925 {
1926 if( aDuplicateDrawItems || aDuplicatePins )
1927 {
1928 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1929
1930 for( SCH_ITEM& item : m_drawings )
1931 {
1932 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
1933 continue;
1934
1935 if( item.m_bodyStyle == 1 )
1936 {
1937 for( int j = prevCount + 1; j <= aCount; j++ )
1938 {
1939 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1940 newItem->m_bodyStyle = j;
1941 tmp.push_back( newItem );
1942 }
1943 }
1944 }
1945
1946 // Transfer the new pins to the LIB_SYMBOL.
1947 for( SCH_ITEM* item : tmp )
1948 m_drawings.push_back( item );
1949 }
1950 }
1951 else
1952 {
1953 // Delete converted shape items because the converted shape does not exist
1955
1956 while( i != m_drawings.end() )
1957 {
1958 if( i->m_bodyStyle > aCount )
1959 i = m_drawings.erase( i );
1960 else
1961 ++i;
1962 }
1963 }
1964
1965 m_drawings.sort();
1966}
1967
1968
1969std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1970{
1971 std::vector<SCH_ITEM*> unitItems;
1972
1973 for( SCH_ITEM& item : m_drawings )
1974 {
1975 if( item.Type() == SCH_FIELD_T )
1976 continue;
1977
1978 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1979 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1980 {
1981 unitItems.push_back( &item );
1982 }
1983 }
1984
1985 return unitItems;
1986}
1987
1988
1989std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
1990{
1991 std::vector<LIB_SYMBOL_UNIT> units;
1992
1993 for( SCH_ITEM& item : m_drawings )
1994 {
1995 if( item.Type() == SCH_FIELD_T )
1996 continue;
1997
1998 int unit = item.GetUnit();
1999 int bodyStyle = item.GetBodyStyle();
2000
2001 auto it = std::find_if( units.begin(), units.end(),
2002 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
2003 {
2004 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
2005 } );
2006
2007 if( it == units.end() )
2008 {
2009 LIB_SYMBOL_UNIT newUnit;
2010 newUnit.m_unit = item.GetUnit();
2011 newUnit.m_bodyStyle = item.GetBodyStyle();
2012 newUnit.m_items.push_back( &item );
2013 units.emplace_back( newUnit );
2014 }
2015 else
2016 {
2017 it->m_items.push_back( &item );
2018 }
2019 }
2020
2021 return units;
2022}
2023
2024
2025#define REPORT( msg ) \
2026 { \
2027 if( aReporter ) \
2028 aReporter->Report( msg ); \
2029 }
2030#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
2031
2032int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
2033{
2034 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
2035
2036 if( m_me == aRhs.m_me )
2037 return 0;
2038
2039 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2040 {
2041 if( int tmp = m_name.Cmp( aRhs.m_name ) )
2042 return tmp;
2043
2044 if( int tmp = m_libId.compare( aRhs.m_libId ) )
2045 return tmp;
2046
2047 if( m_parent.lock() < aRhs.m_parent.lock() )
2048 return -1;
2049
2050 if( m_parent.lock() > aRhs.m_parent.lock() )
2051 return 1;
2052 }
2053
2054 int retv = 0;
2055
2056 if( m_options != aRhs.m_options )
2057 {
2058 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
2059 REPORT( _( "Power flag differs." ) );
2060
2061 if( !aReporter )
2062 return retv;
2063 }
2064
2065 if( int tmp = m_unitCount - aRhs.m_unitCount )
2066 {
2067 retv = tmp;
2068 REPORT( _( "Unit count differs." ) );
2069
2070 if( !aReporter )
2071 return retv;
2072 }
2073
2074 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
2075
2076 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
2077 std::set<const SCH_FIELD*> aFields;
2078 std::set<const SCH_PIN*> aPins;
2079
2080 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
2081 {
2082 if( it->Type() == SCH_SHAPE_T )
2083 aShapes.insert( &( *it ) );
2084 else if( it->Type() == SCH_FIELD_T )
2085 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2086 else if( it->Type() == SCH_PIN_T )
2087 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2088 }
2089
2090 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
2091 std::set<const SCH_FIELD*> bFields;
2092 std::set<const SCH_PIN*> bPins;
2093
2094 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
2095 {
2096 if( it->Type() == SCH_SHAPE_T )
2097 bShapes.insert( &( *it ) );
2098 else if( it->Type() == SCH_FIELD_T )
2099 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2100 else if( it->Type() == SCH_PIN_T )
2101 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2102 }
2103
2104 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
2105 {
2106 retv = tmp;
2107 REPORT( _( "Graphic item count differs." ) );
2108
2109 if( !aReporter )
2110 return retv;
2111 }
2112 else
2113 {
2114 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
2115 {
2116 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
2117 {
2118 retv = tmp2;
2119 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
2120 ITEM_DESC( *bIt ) ) );
2121
2122 if( !aReporter )
2123 return retv;
2124 }
2125 }
2126 }
2127
2128 for( const SCH_PIN* aPin : aPins )
2129 {
2130 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
2131
2132 if( !bPin )
2133 {
2134 retv = 1;
2135 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
2136
2137 if( !aReporter )
2138 return retv;
2139 }
2140 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
2141 {
2142 retv = tmp;
2143 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
2144 ITEM_DESC( bPin ) ) );
2145
2146 if( !aReporter )
2147 return retv;
2148 }
2149 }
2150
2151 for( const SCH_PIN* bPin : bPins )
2152 {
2153 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
2154
2155 if( !aPin )
2156 {
2157 retv = 1;
2158 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
2159
2160 if( !aReporter )
2161 return retv;
2162 }
2163 }
2164
2165 for( const SCH_FIELD* aField : aFields )
2166 {
2167 const SCH_FIELD* bField = nullptr;
2168
2169 if( aField->IsMandatory() )
2170 bField = aRhs.GetField( aField->GetId() );
2171 else
2172 bField = aRhs.GetField( aField->GetName() );
2173
2174 if( !bField )
2175 {
2176 retv = 1;
2177 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
2178
2179 if( !aReporter )
2180 return retv;
2181 }
2182 else
2183 {
2184 int tmp = 0;
2185
2186 // For EQUALITY comparison, we need to compare field content directly
2187 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
2188 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
2189 {
2190 // Compare field text content
2191 tmp = aField->GetText().compare( bField->GetText() );
2192 }
2193
2194 if( tmp == 0 )
2195 {
2196 int fieldCompareFlags = aCompareFlags;
2197
2198 // SCH_FIELD::compare() injects SKIP_TST_POS for ERC, but it is bypassed
2199 // by the base-class call below, so mirror it here (issue 24657).
2200 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC )
2201 fieldCompareFlags |= SCH_ITEM::COMPARE_FLAGS::SKIP_TST_POS;
2202
2203 // Fall back to base class comparison for other properties
2204 tmp = aField->SCH_ITEM::compare( *bField, fieldCompareFlags );
2205 }
2206
2207 if( tmp != 0 )
2208 {
2209 retv = tmp;
2210 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
2211 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
2212
2213 if( !aReporter )
2214 return retv;
2215 }
2216 }
2217 }
2218
2219 for( const SCH_FIELD* bField : bFields )
2220 {
2221 const SCH_FIELD* aField = nullptr;
2222
2223 if( bField->IsMandatory() )
2224 aField = aRhs.GetField( bField->GetId() );
2225 else
2226 aField = aRhs.GetField( bField->GetName() );
2227
2228 if( !aField )
2229 {
2230 retv = 1;
2231 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
2232
2233 if( !aReporter )
2234 return retv;
2235 }
2236 }
2237
2238 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
2239 {
2240 retv = tmp;
2241 REPORT( _( "Footprint filter count differs." ) );
2242
2243 if( !aReporter )
2244 return retv;
2245 }
2246 else
2247 {
2248 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
2249 {
2250 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
2251 {
2252 retv = tmp2;
2253 REPORT( _( "Footprint filters differ." ) );
2254
2255 if( !aReporter )
2256 return retv;
2257 }
2258 }
2259 }
2260
2261 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
2262 {
2263 retv = tmp;
2264 REPORT( _( "Symbol keywords differ." ) );
2265
2266 if( !aReporter )
2267 return retv;
2268 }
2269
2270 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
2271 {
2272 retv = tmp;
2273 REPORT( _( "Symbol pin name offsets differ." ) );
2274
2275 if( !aReporter )
2276 return retv;
2277 }
2278
2279 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2280 {
2281 if( m_showPinNames != aRhs.m_showPinNames )
2282 {
2283 retv = ( m_showPinNames ) ? 1 : -1;
2284 REPORT( _( "Show pin names settings differ." ) );
2285
2286 if( !aReporter )
2287 return retv;
2288 }
2289
2291 {
2292 retv = ( m_showPinNumbers ) ? 1 : -1;
2293 REPORT( _( "Show pin numbers settings differ." ) );
2294
2295 if( !aReporter )
2296 return retv;
2297 }
2298
2300 {
2301 retv = ( m_excludedFromSim ) ? -1 : 1;
2302 REPORT( _( "Exclude from simulation settings differ." ) );
2303
2304 if( !aReporter )
2305 return retv;
2306 }
2307
2309 {
2310 retv = ( m_excludedFromBOM ) ? -1 : 1;
2311 REPORT( _( "Exclude from bill of materials settings differ." ) );
2312
2313 if( !aReporter )
2314 return retv;
2315 }
2316
2318 {
2319 retv = ( m_excludedFromBoard ) ? -1 : 1;
2320 REPORT( _( "Exclude from board settings differ." ) );
2321
2322 if( !aReporter )
2323 return retv;
2324 }
2325
2327 {
2328 retv = ( m_excludedFromPosFiles ) ? -1 : 1;
2329 REPORT( _( "Exclude from position files settings differ." ) );
2330
2331 if( !aReporter )
2332 return retv;
2333 }
2334 }
2335
2336 if( !aReporter )
2337 {
2338 if( m_unitsLocked != aRhs.m_unitsLocked )
2339 return ( m_unitsLocked ) ? 1 : -1;
2340
2341 // Compare unit display names...
2343 return -1;
2344 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
2345 return 1;
2346
2347 // ... and body style names.
2349 return -1;
2350 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
2351 return 1;
2352 }
2353
2354 return retv;
2355}
2356
2357
2358int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2359{
2360 if( Type() != aOther.Type() )
2361 return Type() - aOther.Type();
2362
2363 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
2364
2365 return Compare( *tmp, aCompareFlags );
2366}
2367
2368
2369double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2370{
2371 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
2372
2373 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
2374 double similarity = 0.0;
2375 int totalItems = 0;
2376
2377 if( m_Uuid == aOther.m_Uuid )
2378 return 1.0;
2379
2380 for( const SCH_ITEM& item : m_drawings )
2381 {
2382 totalItems += 1;
2383 double max_similarity = 0.0;
2384
2385 for( const SCH_ITEM& otherItem : other.m_drawings )
2386 {
2387 double temp_similarity = item.Similarity( otherItem );
2388 max_similarity = std::max( max_similarity, temp_similarity );
2389
2390 if( max_similarity == 1.0 )
2391 break;
2392 }
2393
2394 similarity += max_similarity;
2395 }
2396
2397 for( const SCH_PIN* pin : GetGraphicalPins( 0, 0 ) )
2398 {
2399 totalItems += 1;
2400 double max_similarity = 0.0;
2401
2402 for( const SCH_PIN* otherPin : other.GetGraphicalPins( 0, 0 ) )
2403 {
2404 double temp_similarity = pin->Similarity( *otherPin );
2405 max_similarity = std::max( max_similarity, temp_similarity );
2406
2407 if( max_similarity == 1.0 )
2408 break;
2409 }
2410
2411 similarity += max_similarity;
2412 }
2413
2414 if( totalItems == 0 )
2415 similarity = 0.0;
2416 else
2417 similarity /= totalItems;
2418
2420 similarity *= 0.9;
2421
2423 similarity *= 0.9;
2424
2426 similarity *= 0.9;
2427
2429 similarity *= 0.9;
2430
2431 if( m_flags != other.m_flags )
2432 similarity *= 0.9;
2433
2434 if( m_unitCount != other.m_unitCount )
2435 similarity *= 0.5;
2436
2437 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
2438 similarity *= 0.5;
2439 else if( m_bodyStyleNames != other.m_bodyStyleNames )
2440 similarity *= 0.9;
2441
2442 if( m_pinNameOffset != other.m_pinNameOffset )
2443 similarity *= 0.9;
2444
2445 if( m_showPinNames != other.m_showPinNames )
2446 similarity *= 0.9;
2447
2448 if( m_showPinNumbers != other.m_showPinNumbers )
2449 similarity *= 0.9;
2450
2451 return similarity;
2452}
2453
2454
2456{
2457 return static_cast<EMBEDDED_FILES*>( this );
2458}
2459
2460
2462{
2463 return static_cast<const EMBEDDED_FILES*>( this );
2464}
2465
2466
2467void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2468{
2469 std::set<const LIB_SYMBOL*> visited;
2470 visited.insert( this );
2471
2472 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2473
2474 while( parent )
2475 {
2476 // Cycle detected - parent chain points back to an already visited symbol
2477 if( visited.count( parent.get() ) )
2478 {
2479 wxLogTrace( traceSymbolInheritance,
2480 wxT( "AppendParentEmbeddedFiles: Circular inheritance detected in "
2481 "symbol '%s' (lib: %s)" ),
2482 m_name, m_libId.GetLibNickname().wx_str() );
2483 break;
2484 }
2485
2486 visited.insert( parent.get() );
2487 aStack.push_back( parent->GetEmbeddedFiles() );
2488 parent = parent->GetParent().lock();
2489 }
2490}
2491
2492
2493std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2494{
2495 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2496
2497 std::set<KIFONT::OUTLINE_FONT*> fonts;
2498
2499 for( const SCH_ITEM& item : m_drawings )
2500 {
2501 if( item.Type() == SCH_TEXT_T )
2502 {
2503 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2504
2505 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2506 {
2507 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2508 auto permission = outline->GetEmbeddingPermission();
2509
2510 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2511 {
2512 fonts.insert( outline );
2513 }
2514 }
2515 }
2516 }
2517
2518 return fonts;
2519}
2520
2521
2523{
2524 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2525
2526 for( KIFONT::OUTLINE_FONT* font : fonts )
2527 {
2528 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2530 }
2531}
2532
2533
2534std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2535{
2536 for( const std::set<wxString>& group : m_jumperPinGroups )
2537 {
2538 if( group.contains( aPinNumber ) )
2539 return group;
2540 }
2541
2542 return std::nullopt;
2543}
2544
2545static struct LIB_SYMBOL_DESC
2546{
2548 {
2552
2553 const wxString groupFields = _HKI( "Fields" );
2554
2557 groupFields );
2560 groupFields );
2563 groupFields );
2566 groupFields );
2569 groupFields );
2570
2571 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2572
2573 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2576 groupSymbolDef );
2577 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2580 groupSymbolDef );
2581
2582 const wxString groupPinDisplay = _HKI( "Pin Display" );
2583
2584 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2586 groupPinDisplay );
2587 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2589 groupPinDisplay );
2590 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2593 groupPinDisplay );
2594 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2596 groupPinDisplay );
2597
2598 const wxString groupAttributes = _HKI( "Attributes" );
2599
2600 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2603 groupAttributes );
2604 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
2607 groupAttributes );
2608 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2611 groupAttributes );
2612 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
2615 groupAttributes );
2616
2617 const wxString groupUnits = _HKI( "Units and Body Styles" );
2618
2619 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2621 groupUnits );
2622 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2625 groupUnits );
2626
2627 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2628 {
2629 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2630 return symbol->IsMultiBodyStyle();
2631
2632 return false;
2633 };
2634
2637 groupUnits )
2638 .SetAvailableFunc( multiBodyStyle )
2640 []( INSPECTABLE* aItem )
2641 {
2642 wxPGChoices choices;
2643
2644 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2645 {
2646 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2647 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2648 }
2649
2650 return choices;
2651 } );
2652 }
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
@ 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:345
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