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 if( GetBodyStyleCount() == aCount )
1916 return;
1917
1918 // Duplicate items to create the converted shape
1919 if( GetBodyStyleCount() < aCount )
1920 {
1921 if( aDuplicateDrawItems || aDuplicatePins )
1922 {
1923 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1924
1925 for( SCH_ITEM& item : m_drawings )
1926 {
1927 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
1928 continue;
1929
1930 if( item.m_bodyStyle == 1 )
1931 {
1932 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1933 newItem->m_bodyStyle = 2;
1934 tmp.push_back( newItem );
1935 }
1936 }
1937
1938 // Transfer the new pins to the LIB_SYMBOL.
1939 for( SCH_ITEM* item : tmp )
1940 m_drawings.push_back( item );
1941 }
1942 }
1943 else
1944 {
1945 // Delete converted shape items because the converted shape does not exist
1947
1948 while( i != m_drawings.end() )
1949 {
1950 if( i->m_bodyStyle > 1 )
1951 i = m_drawings.erase( i );
1952 else
1953 ++i;
1954 }
1955 }
1956
1957 m_drawings.sort();
1958}
1959
1960
1961std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1962{
1963 std::vector<SCH_ITEM*> unitItems;
1964
1965 for( SCH_ITEM& item : m_drawings )
1966 {
1967 if( item.Type() == SCH_FIELD_T )
1968 continue;
1969
1970 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1971 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1972 {
1973 unitItems.push_back( &item );
1974 }
1975 }
1976
1977 return unitItems;
1978}
1979
1980
1981std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
1982{
1983 std::vector<LIB_SYMBOL_UNIT> units;
1984
1985 for( SCH_ITEM& item : m_drawings )
1986 {
1987 if( item.Type() == SCH_FIELD_T )
1988 continue;
1989
1990 int unit = item.GetUnit();
1991 int bodyStyle = item.GetBodyStyle();
1992
1993 auto it = std::find_if( units.begin(), units.end(),
1994 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
1995 {
1996 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
1997 } );
1998
1999 if( it == units.end() )
2000 {
2001 LIB_SYMBOL_UNIT newUnit;
2002 newUnit.m_unit = item.GetUnit();
2003 newUnit.m_bodyStyle = item.GetBodyStyle();
2004 newUnit.m_items.push_back( &item );
2005 units.emplace_back( newUnit );
2006 }
2007 else
2008 {
2009 it->m_items.push_back( &item );
2010 }
2011 }
2012
2013 return units;
2014}
2015
2016
2017#define REPORT( msg ) \
2018 { \
2019 if( aReporter ) \
2020 aReporter->Report( msg ); \
2021 }
2022#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
2023
2024int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
2025{
2026 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
2027
2028 if( m_me == aRhs.m_me )
2029 return 0;
2030
2031 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2032 {
2033 if( int tmp = m_name.Cmp( aRhs.m_name ) )
2034 return tmp;
2035
2036 if( int tmp = m_libId.compare( aRhs.m_libId ) )
2037 return tmp;
2038
2039 if( m_parent.lock() < aRhs.m_parent.lock() )
2040 return -1;
2041
2042 if( m_parent.lock() > aRhs.m_parent.lock() )
2043 return 1;
2044 }
2045
2046 int retv = 0;
2047
2048 if( m_options != aRhs.m_options )
2049 {
2050 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
2051 REPORT( _( "Power flag differs." ) );
2052
2053 if( !aReporter )
2054 return retv;
2055 }
2056
2057 if( int tmp = m_unitCount - aRhs.m_unitCount )
2058 {
2059 retv = tmp;
2060 REPORT( _( "Unit count differs." ) );
2061
2062 if( !aReporter )
2063 return retv;
2064 }
2065
2066 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
2067
2068 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
2069 std::set<const SCH_FIELD*> aFields;
2070 std::set<const SCH_PIN*> aPins;
2071
2072 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
2073 {
2074 if( it->Type() == SCH_SHAPE_T )
2075 aShapes.insert( &( *it ) );
2076 else if( it->Type() == SCH_FIELD_T )
2077 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2078 else if( it->Type() == SCH_PIN_T )
2079 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2080 }
2081
2082 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
2083 std::set<const SCH_FIELD*> bFields;
2084 std::set<const SCH_PIN*> bPins;
2085
2086 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
2087 {
2088 if( it->Type() == SCH_SHAPE_T )
2089 bShapes.insert( &( *it ) );
2090 else if( it->Type() == SCH_FIELD_T )
2091 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2092 else if( it->Type() == SCH_PIN_T )
2093 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2094 }
2095
2096 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
2097 {
2098 retv = tmp;
2099 REPORT( _( "Graphic item count differs." ) );
2100
2101 if( !aReporter )
2102 return retv;
2103 }
2104 else
2105 {
2106 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
2107 {
2108 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
2109 {
2110 retv = tmp2;
2111 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
2112 ITEM_DESC( *bIt ) ) );
2113
2114 if( !aReporter )
2115 return retv;
2116 }
2117 }
2118 }
2119
2120 for( const SCH_PIN* aPin : aPins )
2121 {
2122 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
2123
2124 if( !bPin )
2125 {
2126 retv = 1;
2127 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
2128
2129 if( !aReporter )
2130 return retv;
2131 }
2132 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
2133 {
2134 retv = tmp;
2135 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
2136 ITEM_DESC( bPin ) ) );
2137
2138 if( !aReporter )
2139 return retv;
2140 }
2141 }
2142
2143 for( const SCH_PIN* bPin : bPins )
2144 {
2145 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
2146
2147 if( !aPin )
2148 {
2149 retv = 1;
2150 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
2151
2152 if( !aReporter )
2153 return retv;
2154 }
2155 }
2156
2157 for( const SCH_FIELD* aField : aFields )
2158 {
2159 const SCH_FIELD* bField = nullptr;
2160
2161 if( aField->IsMandatory() )
2162 bField = aRhs.GetField( aField->GetId() );
2163 else
2164 bField = aRhs.GetField( aField->GetName() );
2165
2166 if( !bField )
2167 {
2168 retv = 1;
2169 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
2170
2171 if( !aReporter )
2172 return retv;
2173 }
2174 else
2175 {
2176 int tmp = 0;
2177
2178 // For EQUALITY comparison, we need to compare field content directly
2179 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
2180 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
2181 {
2182 // Compare field text content
2183 tmp = aField->GetText().compare( bField->GetText() );
2184 }
2185
2186 if( tmp == 0 )
2187 {
2188 // Fall back to base class comparison for other properties
2189 tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags );
2190 }
2191
2192 if( tmp != 0 )
2193 {
2194 retv = tmp;
2195 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
2196 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
2197
2198 if( !aReporter )
2199 return retv;
2200 }
2201 }
2202 }
2203
2204 for( const SCH_FIELD* bField : bFields )
2205 {
2206 const SCH_FIELD* aField = nullptr;
2207
2208 if( bField->IsMandatory() )
2209 aField = aRhs.GetField( bField->GetId() );
2210 else
2211 aField = aRhs.GetField( bField->GetName() );
2212
2213 if( !aField )
2214 {
2215 retv = 1;
2216 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
2217
2218 if( !aReporter )
2219 return retv;
2220 }
2221 }
2222
2223 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
2224 {
2225 retv = tmp;
2226 REPORT( _( "Footprint filter count differs." ) );
2227
2228 if( !aReporter )
2229 return retv;
2230 }
2231 else
2232 {
2233 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
2234 {
2235 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
2236 {
2237 retv = tmp2;
2238 REPORT( _( "Footprint filters differ." ) );
2239
2240 if( !aReporter )
2241 return retv;
2242 }
2243 }
2244 }
2245
2246 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
2247 {
2248 retv = tmp;
2249 REPORT( _( "Symbol keywords differ." ) );
2250
2251 if( !aReporter )
2252 return retv;
2253 }
2254
2255 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
2256 {
2257 retv = tmp;
2258 REPORT( _( "Symbol pin name offsets differ." ) );
2259
2260 if( !aReporter )
2261 return retv;
2262 }
2263
2264 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2265 {
2266 if( m_showPinNames != aRhs.m_showPinNames )
2267 {
2268 retv = ( m_showPinNames ) ? 1 : -1;
2269 REPORT( _( "Show pin names settings differ." ) );
2270
2271 if( !aReporter )
2272 return retv;
2273 }
2274
2276 {
2277 retv = ( m_showPinNumbers ) ? 1 : -1;
2278 REPORT( _( "Show pin numbers settings differ." ) );
2279
2280 if( !aReporter )
2281 return retv;
2282 }
2283
2285 {
2286 retv = ( m_excludedFromSim ) ? -1 : 1;
2287 REPORT( _( "Exclude from simulation settings differ." ) );
2288
2289 if( !aReporter )
2290 return retv;
2291 }
2292
2294 {
2295 retv = ( m_excludedFromBOM ) ? -1 : 1;
2296 REPORT( _( "Exclude from bill of materials settings differ." ) );
2297
2298 if( !aReporter )
2299 return retv;
2300 }
2301
2303 {
2304 retv = ( m_excludedFromBoard ) ? -1 : 1;
2305 REPORT( _( "Exclude from board settings differ." ) );
2306
2307 if( !aReporter )
2308 return retv;
2309 }
2310
2312 {
2313 retv = ( m_excludedFromPosFiles ) ? -1 : 1;
2314 REPORT( _( "Exclude from position files settings differ." ) );
2315
2316 if( !aReporter )
2317 return retv;
2318 }
2319 }
2320
2321 if( !aReporter )
2322 {
2323 if( m_unitsLocked != aRhs.m_unitsLocked )
2324 return ( m_unitsLocked ) ? 1 : -1;
2325
2326 // Compare unit display names...
2328 return -1;
2329 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
2330 return 1;
2331
2332 // ... and body style names.
2334 return -1;
2335 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
2336 return 1;
2337 }
2338
2339 return retv;
2340}
2341
2342
2343int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2344{
2345 if( Type() != aOther.Type() )
2346 return Type() - aOther.Type();
2347
2348 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
2349
2350 return Compare( *tmp, aCompareFlags );
2351}
2352
2353
2354double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2355{
2356 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
2357
2358 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
2359 double similarity = 0.0;
2360 int totalItems = 0;
2361
2362 if( m_Uuid == aOther.m_Uuid )
2363 return 1.0;
2364
2365 for( const SCH_ITEM& item : m_drawings )
2366 {
2367 totalItems += 1;
2368 double max_similarity = 0.0;
2369
2370 for( const SCH_ITEM& otherItem : other.m_drawings )
2371 {
2372 double temp_similarity = item.Similarity( otherItem );
2373 max_similarity = std::max( max_similarity, temp_similarity );
2374
2375 if( max_similarity == 1.0 )
2376 break;
2377 }
2378
2379 similarity += max_similarity;
2380 }
2381
2382 for( const SCH_PIN* pin : GetGraphicalPins( 0, 0 ) )
2383 {
2384 totalItems += 1;
2385 double max_similarity = 0.0;
2386
2387 for( const SCH_PIN* otherPin : other.GetGraphicalPins( 0, 0 ) )
2388 {
2389 double temp_similarity = pin->Similarity( *otherPin );
2390 max_similarity = std::max( max_similarity, temp_similarity );
2391
2392 if( max_similarity == 1.0 )
2393 break;
2394 }
2395
2396 similarity += max_similarity;
2397 }
2398
2399 if( totalItems == 0 )
2400 similarity = 0.0;
2401 else
2402 similarity /= totalItems;
2403
2405 similarity *= 0.9;
2406
2408 similarity *= 0.9;
2409
2411 similarity *= 0.9;
2412
2414 similarity *= 0.9;
2415
2416 if( m_flags != other.m_flags )
2417 similarity *= 0.9;
2418
2419 if( m_unitCount != other.m_unitCount )
2420 similarity *= 0.5;
2421
2422 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
2423 similarity *= 0.5;
2424 else if( m_bodyStyleNames != other.m_bodyStyleNames )
2425 similarity *= 0.9;
2426
2427 if( m_pinNameOffset != other.m_pinNameOffset )
2428 similarity *= 0.9;
2429
2430 if( m_showPinNames != other.m_showPinNames )
2431 similarity *= 0.9;
2432
2433 if( m_showPinNumbers != other.m_showPinNumbers )
2434 similarity *= 0.9;
2435
2436 return similarity;
2437}
2438
2439
2441{
2442 return static_cast<EMBEDDED_FILES*>( this );
2443}
2444
2445
2447{
2448 return static_cast<const EMBEDDED_FILES*>( this );
2449}
2450
2451
2452void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2453{
2454 std::set<const LIB_SYMBOL*> visited;
2455 visited.insert( this );
2456
2457 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2458
2459 while( parent )
2460 {
2461 // Cycle detected - parent chain points back to an already visited symbol
2462 if( visited.count( parent.get() ) )
2463 {
2464 wxLogTrace( traceSymbolInheritance,
2465 wxT( "AppendParentEmbeddedFiles: Circular inheritance detected in "
2466 "symbol '%s' (lib: %s)" ),
2467 m_name, m_libId.GetLibNickname().wx_str() );
2468 break;
2469 }
2470
2471 visited.insert( parent.get() );
2472 aStack.push_back( parent->GetEmbeddedFiles() );
2473 parent = parent->GetParent().lock();
2474 }
2475}
2476
2477
2478std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2479{
2480 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2481
2482 std::set<KIFONT::OUTLINE_FONT*> fonts;
2483
2484 for( const SCH_ITEM& item : m_drawings )
2485 {
2486 if( item.Type() == SCH_TEXT_T )
2487 {
2488 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2489
2490 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2491 {
2492 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2493 auto permission = outline->GetEmbeddingPermission();
2494
2495 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2496 {
2497 fonts.insert( outline );
2498 }
2499 }
2500 }
2501 }
2502
2503 return fonts;
2504}
2505
2506
2508{
2509 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2510
2511 for( KIFONT::OUTLINE_FONT* font : fonts )
2512 {
2513 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2515 }
2516}
2517
2518
2519std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2520{
2521 for( const std::set<wxString>& group : m_jumperPinGroups )
2522 {
2523 if( group.contains( aPinNumber ) )
2524 return group;
2525 }
2526
2527 return std::nullopt;
2528}
2529
2530static struct LIB_SYMBOL_DESC
2531{
2533 {
2537
2538 const wxString groupFields = _HKI( "Fields" );
2539
2542 groupFields );
2545 groupFields );
2548 groupFields );
2551 groupFields );
2554 groupFields );
2555
2556 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2557
2558 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2561 groupSymbolDef );
2562 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2565 groupSymbolDef );
2566
2567 const wxString groupPinDisplay = _HKI( "Pin Display" );
2568
2569 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2571 groupPinDisplay );
2572 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2574 groupPinDisplay );
2575 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2578 groupPinDisplay );
2579 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2581 groupPinDisplay );
2582
2583 const wxString groupAttributes = _HKI( "Attributes" );
2584
2585 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2588 groupAttributes );
2589 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
2592 groupAttributes );
2593 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2596 groupAttributes );
2597 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
2600 groupAttributes );
2601
2602 const wxString groupUnits = _HKI( "Units and Body Styles" );
2603
2604 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2606 groupUnits );
2607 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2610 groupUnits );
2611
2612 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2613 {
2614 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2615 return symbol->IsMultiBodyStyle();
2616
2617 return false;
2618 };
2619
2622 groupUnits )
2623 .SetAvailableFunc( multiBodyStyle )
2625 []( INSPECTABLE* aItem )
2626 {
2627 wxPGChoices choices;
2628
2629 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2630 {
2631 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2632 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2633 }
2634
2635 return choices;
2636 } );
2637 }
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:163
const KIID m_Uuid
Definition eda_item.h:528
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
void ClearSelected()
Definition eda_item.h:144
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:539
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:128
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
EDA_ITEM_FLAGS GetFlags() const
Definition eda_item.h:152
virtual void ClearTempFlags()
Definition eda_item.h:176
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:126
FIELD_T GetId() const
Definition sch_field.h:130
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:237
void SetText(const wxString &aText) override
int m_unit
Definition sch_item.h:782
int m_bodyStyle
Definition sch_item.h:783
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:730
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:272
friend class LIB_SYMBOL
Definition sch_item.h:803
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