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