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 }
694
695 retv->m_parent.reset();
696 }
697 else
698 {
699 retv = std::make_unique<LIB_SYMBOL>( *this );
700 }
701
702 return retv;
703}
704
705
707{
708 m_library = aLibrary;
709
710 if( m_searchTermsCache.empty() )
712
714}
715
716
717const wxString LIB_SYMBOL::GetLibraryName() const
718{
719 if( m_library )
720 return m_library->GetName();
721
722 return m_libId.GetLibNickname();
723}
724
725
727{
728 if( IsDerived() )
729 {
730 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
731
732 if( root.get() != this )
733 return root->IsLocalPower();
734 }
735
737}
738
739
741{
742 if( IsDerived() )
743 {
744 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
745
746 if( root.get() != this )
747 {
748 root->SetLocalPower();
749 return;
750 }
751 }
752
754}
755
756
758{
759 if( IsDerived() )
760 {
761 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
762
763 if( root.get() != this )
764 return root->IsGlobalPower();
765 }
766
768}
769
770
772{
773 return IsLocalPower() || IsGlobalPower();
774}
775
776
778{
779 if( IsDerived() )
780 {
781 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
782
783 if( root.get() != this )
784 {
785 root->SetGlobalPower();
786 return;
787 }
788 }
789
791}
792
793
795{
796 if( IsDerived() )
797 {
798 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
799
800 if( root.get() != this )
801 return root->IsNormal();
802 }
803
804 return m_options == ENTRY_NORMAL;
805}
806
807
809{
810 if( IsDerived() )
811 {
812 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
813
814 if( root.get() != this )
815 {
816 root->SetNormal();
817 return;
818 }
819 }
820
822}
823
824
825wxString LIB_SYMBOL::LetterSubReference( int aUnit, wxChar aInitialLetter )
826{
827 // use letters as notation. To allow more than 26 units, the sub ref
828 // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
829 // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
830 int u;
831 wxString suffix;
832
833 do
834 {
835 u = ( aUnit - 1 ) % 26;
836 suffix = wxChar( aInitialLetter + u ) + suffix;
837 aUnit = ( aUnit - u ) / 26;
838 } while( aUnit > 0 );
839
840 return suffix;
841}
842
843
844bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const
845{
846 wxString footprint;
847
848 for( const SCH_ITEM& item : m_drawings )
849 {
850 if( item.Type() == SCH_FIELD_T )
851 {
852 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
853
854 if( field.GetId() == FIELD_T::FOOTPRINT )
855 footprint = field.GetShownText( nullptr, false, aDepth + 1 );
856
857 if( token->IsSameAs( field.GetCanonicalName().Upper() ) || token->IsSameAs( field.GetName(), false ) )
858 {
859 *token = field.GetShownText( nullptr, false, aDepth + 1 );
860 return true;
861 }
862 }
863 }
864
865 // Consider missing simulation fields as empty, not un-resolved
866 if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) || token->IsSameAs( wxT( "SIM.TYPE" ) )
867 || token->IsSameAs( wxT( "SIM.PINS" ) ) || token->IsSameAs( wxT( "SIM.PARAMS" ) )
868 || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) || token->IsSameAs( wxT( "SIM.NAME" ) ) )
869 {
870 *token = wxEmptyString;
871 return true;
872 }
873
874 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
875 {
876 wxArrayString parts = wxSplit( footprint, ':' );
877
878 if( parts.Count() > 0 )
879 *token = parts[0];
880 else
881 *token = wxEmptyString;
882
883 return true;
884 }
885 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
886 {
887 wxArrayString parts = wxSplit( footprint, ':' );
888
889 if( parts.Count() > 1 )
890 *token = parts[std::min( 1, (int) parts.size() - 1 )];
891 else
892 *token = wxEmptyString;
893
894 return true;
895 }
896 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
897 {
898 *token = m_libId.GetUniStringLibNickname();
899 return true;
900 }
901 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
902 {
903 *token = m_libId.GetUniStringLibItemName();
904 return true;
905 }
906 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
907 {
908 *token = GetShownDescription( aDepth + 1 );
909 return true;
910 }
911 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
912 {
913 *token = GetShownKeyWords( aDepth + 1 );
914 return true;
915 }
916 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
917 {
918 *token = this->GetExcludedFromBOM() ? _( "Excluded from BOM" ) : wxString( "" );
919 return true;
920 }
921 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
922 {
923 *token = this->GetExcludedFromBoard() ? _( "Excluded from board" ) : wxString( "" );
924 return true;
925 }
926 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
927 {
928 *token = this->GetExcludedFromSim() ? _( "Excluded from simulation" ) : wxString( "" );
929 return true;
930 }
931 else if( token->IsSameAs( wxT( "DNP" ) ) )
932 {
933 *token = this->GetDNP() ? _( "DNP" ) : wxString( "" );
934 return true;
935 }
936
937 return false;
938}
939
940
941void LIB_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle,
942 const VECTOR2I& aOffset, bool aDimmed )
943{
944 wxASSERT( aPlotter != nullptr );
945
946 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
947 COLOR4D color = renderSettings->GetLayerColor( LAYER_DEVICE );
948 COLOR4D bg = renderSettings->GetBackgroundColor();
949
950 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
951 bg = COLOR4D::WHITE;
952
953 if( color.m_text && Schematic() )
954 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
955
956 if( aDimmed )
957 {
958 color.Desaturate();
959 color = color.Mix( bg, 0.5f );
960 }
961
962 aPlotter->SetColor( color );
963
964 for( SCH_ITEM& item : m_drawings )
965 {
966 // Do not plot private items
967 if( item.IsPrivate() )
968 continue;
969
970 // LIB_FIELDs are not plotted here, because this plot function is used to plot schematic
971 // items which have their own SCH_FIELDs
972 if( item.Type() == SCH_FIELD_T )
973 continue;
974
975 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
976 continue;
977
978 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
979 continue;
980
981 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
982 }
983}
984
985
986void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
987 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
988{
989 wxASSERT( aPlotter != nullptr );
990
991 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
992 COLOR4D color = renderSettings->GetLayerColor( LAYER_FIELDS );
993 COLOR4D bg = renderSettings->GetBackgroundColor();
994
995 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
996 bg = COLOR4D::WHITE;
997
998 if( aDimmed )
999 {
1000 color.Desaturate();
1001 color = color.Mix( bg, 0.5f );
1002 }
1003
1004 aPlotter->SetColor( color );
1005
1006 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1007 {
1008 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1009
1010 if( !renderSettings->m_ShowHiddenFields && !field.IsVisible() )
1011 continue;
1012
1013 // The reference is a special case: we should change the basic text
1014 // to add '?' and the part id
1015 wxString tmp = field.GetText();
1016
1017 field.SetText( field.GetFullText( aUnit ) );
1018 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1019
1020 field.SetText( tmp );
1021 }
1022}
1023
1024
1026{
1027 std::vector<SCH_SHAPE*> potential_top_items;
1028 std::vector<SCH_ITEM*> bottom_items;
1029
1030 for( SCH_ITEM& item : m_drawings )
1031 {
1032 if( item.Type() == SCH_SHAPE_T )
1033 {
1034 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
1035
1036 if( shape.GetFillMode() == FILL_T::FILLED_WITH_COLOR )
1037 potential_top_items.push_back( &shape );
1038 else
1039 bottom_items.push_back( &item );
1040 }
1041 else
1042 {
1043 bottom_items.push_back( &item );
1044 }
1045 }
1046
1047 std::sort( potential_top_items.begin(), potential_top_items.end(),
1048 []( SCH_ITEM* a, SCH_ITEM* b )
1049 {
1050 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
1051 } );
1052
1053 for( SCH_SHAPE* item : potential_top_items )
1054 {
1055 for( SCH_ITEM* bottom_item : bottom_items )
1056 {
1057 if( item->GetBoundingBox().Contains( bottom_item->GetBoundingBox() ) )
1058 {
1059 item->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1060 break;
1061 }
1062 }
1063 }
1064}
1065
1066
1068{
1069 wxASSERT( aItem != nullptr );
1070
1071 // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
1072 // omitted when saving to disk.
1073 if( aItem->Type() == SCH_FIELD_T )
1074 {
1075 if( static_cast<SCH_FIELD*>( aItem )->IsMandatory() )
1076 return;
1077 }
1078
1079 LIB_ITEMS& items = m_drawings[aItem->Type()];
1080
1081 for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
1082 {
1083 if( &*i == aItem )
1084 {
1085 items.erase( i );
1086 cachePinCount();
1088 break;
1089 }
1090 }
1091}
1092
1093
1094void LIB_SYMBOL::AddDrawItem( SCH_ITEM* aItem, bool aSort )
1095{
1096 if( aItem )
1097 {
1098 aItem->SetParent( this );
1099
1100 m_drawings.push_back( aItem );
1101
1102 if( aSort )
1103 m_drawings.sort();
1104
1105 cachePinCount();
1107 }
1108}
1109
1110
1111std::vector<const SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle ) const
1112{
1113 if( IsDerived() )
1114 {
1115 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1116
1117 if( root.get() != this )
1118 return const_cast<const LIB_SYMBOL*>( root.get() )->GetGraphicalPins( aUnit, aBodyStyle );
1119 }
1120
1121 std::vector<const SCH_PIN*> pins;
1122
1123 /* Notes:
1124 * when aUnit == 0: no unit filtering
1125 * when aBodyStyle == 0: no body style filtering
1126 * when m_unit == 0, the item is common to all units
1127 * when m_bodyStyle == 0, the item is common to all body styles
1128 */
1129
1130 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1131 {
1132 // Unit filtering:
1133 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1134 continue;
1135
1136 // Body style filtering:
1137 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1138 continue;
1139
1140 pins.push_back( static_cast<const SCH_PIN*>( &item ) );
1141 }
1142
1143 return pins;
1144}
1145
1146
1147std::vector<SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle )
1148{
1149 if( IsDerived() )
1150 {
1151 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1152
1153 if( root.get() != this )
1154 return root->GetGraphicalPins( aUnit, aBodyStyle );
1155 }
1156
1157 std::vector<SCH_PIN*> pins;
1158
1159 /* Notes:
1160 * when aUnit == 0: no unit filtering
1161 * when aBodyStyle == 0: no body style filtering
1162 * when m_unit == 0, the item is common to all units
1163 * when m_bodyStyle == 0, the item is common to all body styles
1164 */
1165
1166 for( SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1167 {
1168 // Unit filtering:
1169 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1170 continue;
1171
1172 // Body style filtering:
1173 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1174 continue;
1175
1176 pins.push_back( static_cast<SCH_PIN*>( &item ) );
1177 }
1178
1179 return pins;
1180}
1181
1182
1183std::vector<LIB_SYMBOL::UNIT_PIN_INFO> LIB_SYMBOL::GetUnitPinInfo() const
1184{
1185 std::vector<UNIT_PIN_INFO> units;
1186
1187 int unitCount = std::max( GetUnitCount(), 1 );
1188
1189 auto compareByPosition =
1190 []( const SCH_PIN* a, const SCH_PIN* b )
1191 {
1192 VECTOR2I positionA = a->GetPosition();
1193 VECTOR2I positionB = b->GetPosition();
1194
1195 if( positionA.x != positionB.x )
1196 return positionA.x < positionB.x;
1197
1198 return positionA.y < positionB.y;
1199 };
1200
1201 for( int unitIdx = 1; unitIdx <= unitCount; ++unitIdx )
1202 {
1203 UNIT_PIN_INFO unitInfo;
1204 unitInfo.m_unitName = GetUnitDisplayName( unitIdx, false );
1205
1206 std::vector<const SCH_PIN*> pinList = GetGraphicalPins( unitIdx, 0 );
1207
1208 std::sort( pinList.begin(), pinList.end(), compareByPosition );
1209
1210 std::unordered_set<wxString> seenNumbers;
1211
1212 for( const SCH_PIN* basePin : pinList )
1213 {
1214 bool stackedValid = false;
1215 std::vector<wxString> expandedNumbers = basePin->GetStackedPinNumbers( &stackedValid );
1216
1217 if( stackedValid && !expandedNumbers.empty() )
1218 {
1219 for( const wxString& number : expandedNumbers )
1220 {
1221 if( seenNumbers.insert( number ).second )
1222 unitInfo.m_pinNumbers.push_back( number );
1223 }
1224
1225 continue;
1226 }
1227
1228 const wxString& number = basePin->GetNumber();
1229
1230 if( !number.IsEmpty() && seenNumbers.insert( number ).second )
1231 unitInfo.m_pinNumbers.push_back( number );
1232 }
1233
1234 units.push_back( std::move( unitInfo ) );
1235 }
1236
1237 return units;
1238}
1239
1240
1241std::vector<LIB_SYMBOL::LOGICAL_PIN> LIB_SYMBOL::GetLogicalPins( int aUnit, int aBodyStyle ) const
1242{
1243 std::vector<LOGICAL_PIN> out;
1244
1245 for( const SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1246 {
1247 bool valid = false;
1248 std::vector<wxString> expanded = pin->GetStackedPinNumbers( &valid );
1249
1250 if( valid && !expanded.empty() )
1251 {
1252 for( const wxString& num : expanded )
1253 {
1254 out.push_back( LOGICAL_PIN{ pin, num } );
1255 wxLogTrace( traceStackedPins, "GetLogicalPins: base='%s' -> '%s'", pin->GetShownNumber(), num );
1256 }
1257 }
1258 else
1259 {
1260 out.push_back( LOGICAL_PIN{ pin, pin->GetShownNumber() } );
1261 wxLogTrace( traceStackedPins, "GetLogicalPins: base='%s' (no expansion)", pin->GetShownNumber() );
1262 }
1263 }
1264
1265 return out;
1266}
1267
1268
1270{
1271 return m_pinCountCache;
1272}
1273
1274
1276{
1277 m_pinCountCache = 0;
1278
1279 for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) )
1280 {
1281 int pinCount = pin->GetStackedPinCount();
1282 m_pinCountCache += pinCount;
1283 }
1284}
1285
1286
1287const SCH_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aBodyStyle ) const
1288{
1289 for( const SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1290 {
1291 if( aNumber == pin->GetNumber() )
1292 return pin;
1293 }
1294
1295 return nullptr;
1296}
1297
1298
1299std::vector<SCH_PIN*> LIB_SYMBOL::GetPinsByNumber( const wxString& aNumber, int aUnit, int aBodyStyle )
1300{
1301 std::vector<SCH_PIN*> pins;
1302
1303 for( SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
1304 {
1305 if( aNumber == pin->GetNumber() )
1306 pins.push_back( pin );
1307 }
1308
1309 return pins;
1310}
1311
1312
1313bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames, bool aTestType,
1314 bool aTestOrientation, bool aTestLength ) const
1315{
1316 for( const SCH_PIN* pin : GetGraphicalPins() )
1317 {
1318 wxASSERT( pin );
1319 bool foundMatch = false;
1320
1321 for( const SCH_PIN* otherPin : aOtherPart.GetGraphicalPins() )
1322 {
1323 wxASSERT( otherPin );
1324
1325 // Same unit?
1326 if( pin->GetUnit() != otherPin->GetUnit() )
1327 continue;
1328
1329 // Same body stype?
1330 if( pin->GetBodyStyle() != otherPin->GetBodyStyle() )
1331 continue;
1332
1333 // Same position?
1334 if( pin->GetPosition() != otherPin->GetPosition() )
1335 continue;
1336
1337 // Same number?
1338 if( aTestNums && ( pin->GetNumber() != otherPin->GetNumber() ) )
1339 continue;
1340
1341 // Same name?
1342 if( aTestNames && ( pin->GetName() != otherPin->GetName() ) )
1343 continue;
1344
1345 // Same electrical type?
1346 if( aTestType && ( pin->GetType() != otherPin->GetType() ) )
1347 continue;
1348
1349 // Same orientation?
1350 if( aTestOrientation && ( pin->GetOrientation() != otherPin->GetOrientation() ) )
1351 continue;
1352
1353 // Same length?
1354 if( aTestLength && ( pin->GetLength() != otherPin->GetLength() ) )
1355 continue;
1356
1357 foundMatch = true;
1358 break; // Match found so search is complete.
1359 }
1360
1361 if( !foundMatch )
1362 {
1363 // This means there was not an identical (according to the arguments)
1364 // pin at the same position in the other symbol.
1365 return true;
1366 }
1367 }
1368
1369 // The loop never gave up, so no conflicts were found.
1370 return false;
1371}
1372
1373std::vector<SCH_PIN*> LIB_SYMBOL::GetPins() const
1374{
1375 // Back-compat shim: return graphical pins for all units/body styles, violating const
1376 return const_cast<LIB_SYMBOL*>( this )->GetGraphicalPins( 0, 0 );
1377}
1378
1379
1380const BOX2I LIB_SYMBOL::GetUnitBoundingBox( int aUnit, int aBodyStyle, bool aIgnoreHiddenFields,
1381 bool aIgnoreLabelsOnInvisiblePins ) const
1382{
1383 BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works
1384
1385 if( IsDerived() )
1386 {
1387 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1388
1389 if( root.get() != this )
1390 bBox = root->GetUnitBoundingBox( aUnit, aBodyStyle, aIgnoreHiddenFields, aIgnoreLabelsOnInvisiblePins );
1391 }
1392
1393 for( const SCH_ITEM& item : m_drawings )
1394 {
1395 if( item.m_unit > 0 && m_unitCount > 1 && aUnit > 0 && aUnit != item.m_unit )
1396 continue;
1397
1398 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1399 continue;
1400
1401 if( aIgnoreHiddenFields && item.Type() == SCH_FIELD_T )
1402 {
1403 if( !static_cast<const SCH_FIELD&>( item ).IsVisible() )
1404 continue;
1405 }
1406
1407 if( item.Type() == SCH_PIN_T && !aIgnoreLabelsOnInvisiblePins )
1408 {
1409 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1410 bBox.Merge( pin.GetBoundingBox( true, true, false ) );
1411 }
1412 else
1413 {
1414 bBox.Merge( item.GetBoundingBox() );
1415 }
1416 }
1417
1418 return bBox;
1419}
1420
1421
1422const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aIncludePins,
1423 bool aIncludePrivateItems ) const
1424{
1425 BOX2I bbox;
1426
1427 for( const SCH_ITEM& item : m_drawings )
1428 {
1429 if( item.m_unit > 0 && aUnit > 0 && aUnit != item.m_unit )
1430 continue;
1431
1432 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1433 continue;
1434
1435 if( item.IsPrivate() && !aIncludePrivateItems )
1436 continue;
1437
1438 if( item.Type() == SCH_FIELD_T )
1439 continue;
1440
1441 if( item.Type() == SCH_PIN_T )
1442 {
1443 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1444
1445 if( pin.IsVisible() )
1446 {
1447 // Note: the roots of the pins are always included for symbols that don't have
1448 // a well-defined body.
1449
1450 if( aIncludePins )
1451 bbox.Merge( pin.GetBoundingBox( false, false, false ) );
1452 else
1453 bbox.Merge( pin.GetPinRoot() );
1454 }
1455 }
1456 else
1457 {
1458 bbox.Merge( item.GetBoundingBox() );
1459 }
1460 }
1461
1462 return bbox;
1463}
1464
1465
1472
1473
1475{
1476 AddDrawItem( aField );
1477}
1478
1479
1480void LIB_SYMBOL::SetFields( const std::vector<SCH_FIELD>& aFieldsList )
1481{
1483
1484 for( const SCH_FIELD& src : aFieldsList )
1485 {
1486 // drawings is a ptr_vector, new and copy an object on the heap.
1487 SCH_FIELD* field = new SCH_FIELD( src );
1488
1489 field->SetParent( this );
1490 m_drawings.push_back( field );
1491 }
1492
1493 m_drawings.sort();
1496}
1497
1498
1499void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aList, bool aVisibleOnly ) const
1500{
1501 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1502 {
1503 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1504
1505 if( aVisibleOnly )
1506 {
1507 if( !field->IsVisible() || field->GetText().IsEmpty() )
1508 continue;
1509 }
1510
1511 aList.push_back( const_cast<SCH_FIELD*>( field ) );
1512 }
1513
1514 std::sort( aList.begin(), aList.end(),
1515 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1516 {
1517 return lhs->GetOrdinal() < rhs->GetOrdinal();
1518 } );
1519}
1520
1521
1522void LIB_SYMBOL::CopyFields( std::vector<SCH_FIELD>& aList )
1523{
1524 std::vector<SCH_FIELD*> orderedFields;
1525
1526 GetFields( orderedFields );
1527
1528 for( SCH_FIELD* field : orderedFields )
1529 aList.emplace_back( *field );
1530}
1531
1532
1534{
1535 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id
1536
1537 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1538 ordinal = std::max( ordinal, static_cast<const SCH_FIELD*>( &item )->GetOrdinal() + 1 );
1539
1540 return ordinal;
1541}
1542
1543
1544const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const
1545{
1546 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1547 {
1548 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1549
1550 if( field->GetId() == aFieldType )
1551 return field;
1552 }
1553
1554 return nullptr;
1555}
1556
1557
1559{
1560 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1561 {
1562 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1563
1564 if( field->GetId() == aFieldType )
1565 return field;
1566 }
1567
1568 return nullptr;
1569}
1570
1571
1572const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const
1573{
1574 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1575 {
1576 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1577
1578 if( field.GetName() == aFieldName )
1579 return &field;
1580 }
1581
1582 return nullptr;
1583}
1584
1585
1586SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName )
1587{
1588 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1589 {
1590 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1591
1592 if( field.GetName() == aFieldName )
1593 return &field;
1594 }
1595
1596 return nullptr;
1597}
1598
1599
1601{
1602 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1603 {
1604 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1605
1606 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1607 return &field;
1608 }
1609
1610 return nullptr;
1611}
1612
1613
1615{
1616 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
1617 wxASSERT( field != nullptr );
1618 return *field;
1619}
1620
1621
1623{
1624 const SCH_FIELD* field = GetField( FIELD_T::REFERENCE );
1625 wxASSERT( field != nullptr );
1626 return *field;
1627}
1628
1629
1631{
1632 const SCH_FIELD* field = GetField( FIELD_T::FOOTPRINT );
1633 wxASSERT( field != nullptr );
1634 return *field;
1635}
1636
1637
1639{
1640 const SCH_FIELD* field = GetField( FIELD_T::DATASHEET );
1641 wxASSERT( field != nullptr );
1642 return *field;
1643}
1644
1645
1647{
1648 const SCH_FIELD* field = GetField( FIELD_T::DESCRIPTION );
1649 wxASSERT( field != nullptr );
1650 return *field;
1651}
1652
1653
1655{
1656 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
1657
1658 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1659
1660 wxString prefix = refDesignator;
1661
1662 while( prefix.Length() )
1663 {
1664 wxUniCharRef last = prefix.Last();
1665
1666 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1667 prefix.RemoveLast();
1668 else
1669 break;
1670 }
1671
1672 // Avoid a prefix containing trailing/leading spaces
1673 prefix.Trim( true );
1674 prefix.Trim( false );
1675
1676 return prefix;
1677}
1678
1679
1680void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1681{
1682 for( SCH_ITEM& item : m_drawings )
1683 aFunction( &item );
1684}
1685
1686
1687void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1688{
1689 for( SCH_ITEM& item : m_drawings )
1690 item.Move( aOffset );
1691}
1692
1693
1694// Before V10 we didn't store the number of body styles in a symbol -- we just looked through all
1695// its drawings each time we wanted to know. This is now only used to set the count when a legacy
1696// symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count
1697// is always 1 or 2, and when 2 it is always a De Morgan pair.)
1699{
1700 for( const SCH_ITEM& item : m_drawings )
1701 {
1702 if( item.m_bodyStyle > BODY_STYLE::BASE )
1703 return true;
1704 }
1705
1706 if( IsDerived() )
1707 {
1708 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1709
1710 if( root.get() != this )
1711 return root->HasLegacyAlternateBodyStyle();
1712 }
1713
1714 return false;
1715}
1716
1717
1719{
1720 if( IsDerived() )
1721 {
1722 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1723
1724 if( root.get() != this )
1725 return root->GetMaxPinNumber();
1726 }
1727
1728 int maxPinNumber = 0;
1729
1730 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1731 {
1732 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1733 long currentPinNumber = 0;
1734
1735 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1736 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1737 }
1738
1739 return maxPinNumber;
1740}
1741
1742
1744{
1746
1747 for( SCH_ITEM& item : m_drawings )
1748 item.ClearTempFlags();
1749}
1750
1751
1753{
1755
1756 for( SCH_ITEM& item : m_drawings )
1757 item.ClearEditFlags();
1758}
1759
1760
1761SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint )
1762{
1763 for( SCH_ITEM& item : m_drawings )
1764 {
1765 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1766 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1767 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1768 {
1769 continue;
1770 }
1771
1772 if( item.HitTest( aPoint ) )
1773 return &item;
1774 }
1775
1776 return nullptr;
1777}
1778
1779
1780SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint,
1781 const TRANSFORM& aTransform )
1782{
1783 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1784 * VECTOR2I& pt ) to search items.
1785 * because this function uses DefaultTransform as orient/mirror matrix
1786 * we temporary copy aTransform in DefaultTransform
1787 */
1788 TRANSFORM transform = DefaultTransform;
1789 DefaultTransform = aTransform;
1790
1791 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1792
1793 // Restore matrix
1794 DefaultTransform = transform;
1795
1796 return item;
1797}
1798
1799
1800INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
1801{
1802 // The part itself is never inspected, only its children
1803 for( SCH_ITEM& item : m_drawings )
1804 {
1805 if( item.IsType( aScanTypes ) )
1806 {
1807 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1808 return INSPECT_RESULT::QUIT;
1809 }
1810 }
1811
1813}
1814
1815
1816void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1817{
1818 if( m_unitCount == aCount )
1819 return;
1820
1821 if( aCount < m_unitCount )
1822 {
1823 // Iterate each drawing-type bucket and erase items that belong to units > aCount.
1824 for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
1825 {
1826 auto it = m_drawings.begin( type );
1827
1828 while( it != m_drawings.end( type ) )
1829 {
1830 if( it->m_unit > aCount )
1831 it = m_drawings.erase( it ); // returns next iterator
1832 else
1833 ++it;
1834 }
1835 }
1836 }
1837 else if( aDuplicateDrawItems )
1838 {
1839 int prevCount = m_unitCount;
1840
1841 // Temporary storage for new items, as adding new items directly to
1842 // m_drawings may cause the buffer reallocation which invalidates the
1843 // iterators
1844 std::vector<SCH_ITEM*> tmp;
1845
1846 for( SCH_ITEM& item : m_drawings )
1847 {
1848 if( item.m_unit != 1 )
1849 continue;
1850
1851 for( int j = prevCount + 1; j <= aCount; j++ )
1852 {
1853 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1854 newItem->m_unit = j;
1855 tmp.push_back( newItem );
1856 }
1857 }
1858
1859 for( SCH_ITEM* item : tmp )
1860 m_drawings.push_back( item );
1861 }
1862
1863 m_drawings.sort();
1864 m_unitCount = aCount;
1865}
1866
1867
1869{
1870 if( IsDerived() )
1871 {
1872 std::shared_ptr<LIB_SYMBOL> root = GetSafeRootSymbol( this, __FUNCTION__ );
1873
1874 if( root.get() != this )
1875 return root->GetUnitCount();
1876 }
1877
1878 return m_unitCount;
1879}
1880
1881
1882void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins )
1883{
1884 if( GetBodyStyleCount() == aCount )
1885 return;
1886
1887 // Duplicate items to create the converted shape
1888 if( GetBodyStyleCount() < aCount )
1889 {
1890 if( aDuplicateDrawItems || aDuplicatePins )
1891 {
1892 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1893
1894 for( SCH_ITEM& item : m_drawings )
1895 {
1896 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
1897 continue;
1898
1899 if( item.m_bodyStyle == 1 )
1900 {
1901 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1902 newItem->m_bodyStyle = 2;
1903 tmp.push_back( newItem );
1904 }
1905 }
1906
1907 // Transfer the new pins to the LIB_SYMBOL.
1908 for( SCH_ITEM* item : tmp )
1909 m_drawings.push_back( item );
1910 }
1911 }
1912 else
1913 {
1914 // Delete converted shape items because the converted shape does not exist
1916
1917 while( i != m_drawings.end() )
1918 {
1919 if( i->m_bodyStyle > 1 )
1920 i = m_drawings.erase( i );
1921 else
1922 ++i;
1923 }
1924 }
1925
1926 m_drawings.sort();
1927}
1928
1929
1930std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1931{
1932 std::vector<SCH_ITEM*> unitItems;
1933
1934 for( SCH_ITEM& item : m_drawings )
1935 {
1936 if( item.Type() == SCH_FIELD_T )
1937 continue;
1938
1939 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1940 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1941 {
1942 unitItems.push_back( &item );
1943 }
1944 }
1945
1946 return unitItems;
1947}
1948
1949
1950std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
1951{
1952 std::vector<LIB_SYMBOL_UNIT> units;
1953
1954 for( SCH_ITEM& item : m_drawings )
1955 {
1956 if( item.Type() == SCH_FIELD_T )
1957 continue;
1958
1959 int unit = item.GetUnit();
1960 int bodyStyle = item.GetBodyStyle();
1961
1962 auto it = std::find_if( units.begin(), units.end(),
1963 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
1964 {
1965 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
1966 } );
1967
1968 if( it == units.end() )
1969 {
1970 LIB_SYMBOL_UNIT newUnit;
1971 newUnit.m_unit = item.GetUnit();
1972 newUnit.m_bodyStyle = item.GetBodyStyle();
1973 newUnit.m_items.push_back( &item );
1974 units.emplace_back( newUnit );
1975 }
1976 else
1977 {
1978 it->m_items.push_back( &item );
1979 }
1980 }
1981
1982 return units;
1983}
1984
1985
1986#define REPORT( msg ) \
1987 { \
1988 if( aReporter ) \
1989 aReporter->Report( msg ); \
1990 }
1991#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
1992
1993int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
1994{
1995 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
1996
1997 if( m_me == aRhs.m_me )
1998 return 0;
1999
2000 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2001 {
2002 if( int tmp = m_name.Cmp( aRhs.m_name ) )
2003 return tmp;
2004
2005 if( int tmp = m_libId.compare( aRhs.m_libId ) )
2006 return tmp;
2007
2008 if( m_parent.lock() < aRhs.m_parent.lock() )
2009 return -1;
2010
2011 if( m_parent.lock() > aRhs.m_parent.lock() )
2012 return 1;
2013 }
2014
2015 int retv = 0;
2016
2017 if( m_options != aRhs.m_options )
2018 {
2019 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
2020 REPORT( _( "Power flag differs." ) );
2021
2022 if( !aReporter )
2023 return retv;
2024 }
2025
2026 if( int tmp = m_unitCount - aRhs.m_unitCount )
2027 {
2028 retv = tmp;
2029 REPORT( _( "Unit count differs." ) );
2030
2031 if( !aReporter )
2032 return retv;
2033 }
2034
2035 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
2036
2037 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
2038 std::set<const SCH_FIELD*> aFields;
2039 std::set<const SCH_PIN*> aPins;
2040
2041 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
2042 {
2043 if( it->Type() == SCH_SHAPE_T )
2044 aShapes.insert( &( *it ) );
2045 else if( it->Type() == SCH_FIELD_T )
2046 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2047 else if( it->Type() == SCH_PIN_T )
2048 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2049 }
2050
2051 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
2052 std::set<const SCH_FIELD*> bFields;
2053 std::set<const SCH_PIN*> bPins;
2054
2055 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
2056 {
2057 if( it->Type() == SCH_SHAPE_T )
2058 bShapes.insert( &( *it ) );
2059 else if( it->Type() == SCH_FIELD_T )
2060 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
2061 else if( it->Type() == SCH_PIN_T )
2062 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
2063 }
2064
2065 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
2066 {
2067 retv = tmp;
2068 REPORT( _( "Graphic item count differs." ) );
2069
2070 if( !aReporter )
2071 return retv;
2072 }
2073 else
2074 {
2075 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
2076 {
2077 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
2078 {
2079 retv = tmp2;
2080 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
2081 ITEM_DESC( *bIt ) ) );
2082
2083 if( !aReporter )
2084 return retv;
2085 }
2086 }
2087 }
2088
2089 for( const SCH_PIN* aPin : aPins )
2090 {
2091 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
2092
2093 if( !bPin )
2094 {
2095 retv = 1;
2096 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
2097
2098 if( !aReporter )
2099 return retv;
2100 }
2101 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
2102 {
2103 retv = tmp;
2104 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
2105 ITEM_DESC( bPin ) ) );
2106
2107 if( !aReporter )
2108 return retv;
2109 }
2110 }
2111
2112 for( const SCH_PIN* bPin : bPins )
2113 {
2114 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
2115
2116 if( !aPin )
2117 {
2118 retv = 1;
2119 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
2120
2121 if( !aReporter )
2122 return retv;
2123 }
2124 }
2125
2126 for( const SCH_FIELD* aField : aFields )
2127 {
2128 const SCH_FIELD* bField = nullptr;
2129
2130 if( aField->IsMandatory() )
2131 bField = aRhs.GetField( aField->GetId() );
2132 else
2133 bField = aRhs.GetField( aField->GetName() );
2134
2135 if( !bField )
2136 {
2137 retv = 1;
2138 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
2139
2140 if( !aReporter )
2141 return retv;
2142 }
2143 else
2144 {
2145 int tmp = 0;
2146
2147 // For EQUALITY comparison, we need to compare field content directly
2148 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
2149 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
2150 {
2151 // Compare field text content
2152 tmp = aField->GetText().compare( bField->GetText() );
2153 }
2154
2155 if( tmp == 0 )
2156 {
2157 // Fall back to base class comparison for other properties
2158 tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags );
2159 }
2160
2161 if( tmp != 0 )
2162 {
2163 retv = tmp;
2164 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
2165 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
2166
2167 if( !aReporter )
2168 return retv;
2169 }
2170 }
2171 }
2172
2173 for( const SCH_FIELD* bField : bFields )
2174 {
2175 const SCH_FIELD* aField = nullptr;
2176
2177 if( bField->IsMandatory() )
2178 aField = aRhs.GetField( bField->GetId() );
2179 else
2180 aField = aRhs.GetField( bField->GetName() );
2181
2182 if( !aField )
2183 {
2184 retv = 1;
2185 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
2186
2187 if( !aReporter )
2188 return retv;
2189 }
2190 }
2191
2192 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
2193 {
2194 retv = tmp;
2195 REPORT( _( "Footprint filter count differs." ) );
2196
2197 if( !aReporter )
2198 return retv;
2199 }
2200 else
2201 {
2202 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
2203 {
2204 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
2205 {
2206 retv = tmp2;
2207 REPORT( _( "Footprint filters differ." ) );
2208
2209 if( !aReporter )
2210 return retv;
2211 }
2212 }
2213 }
2214
2215 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
2216 {
2217 retv = tmp;
2218 REPORT( _( "Symbol keywords differ." ) );
2219
2220 if( !aReporter )
2221 return retv;
2222 }
2223
2224 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
2225 {
2226 retv = tmp;
2227 REPORT( _( "Symbol pin name offsets differ." ) );
2228
2229 if( !aReporter )
2230 return retv;
2231 }
2232
2233 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
2234 {
2235 if( m_showPinNames != aRhs.m_showPinNames )
2236 {
2237 retv = ( m_showPinNames ) ? 1 : -1;
2238 REPORT( _( "Show pin names settings differ." ) );
2239
2240 if( !aReporter )
2241 return retv;
2242 }
2243
2245 {
2246 retv = ( m_showPinNumbers ) ? 1 : -1;
2247 REPORT( _( "Show pin numbers settings differ." ) );
2248
2249 if( !aReporter )
2250 return retv;
2251 }
2252
2254 {
2255 retv = ( m_excludedFromSim ) ? -1 : 1;
2256 REPORT( _( "Exclude from simulation settings differ." ) );
2257
2258 if( !aReporter )
2259 return retv;
2260 }
2261
2263 {
2264 retv = ( m_excludedFromBOM ) ? -1 : 1;
2265 REPORT( _( "Exclude from bill of materials settings differ." ) );
2266
2267 if( !aReporter )
2268 return retv;
2269 }
2270
2272 {
2273 retv = ( m_excludedFromBoard ) ? -1 : 1;
2274 REPORT( _( "Exclude from board settings differ." ) );
2275
2276 if( !aReporter )
2277 return retv;
2278 }
2279
2281 {
2282 retv = ( m_excludedFromPosFiles ) ? -1 : 1;
2283 REPORT( _( "Exclude from position files settings differ." ) );
2284
2285 if( !aReporter )
2286 return retv;
2287 }
2288 }
2289
2290 if( !aReporter )
2291 {
2292 if( m_unitsLocked != aRhs.m_unitsLocked )
2293 return ( m_unitsLocked ) ? 1 : -1;
2294
2295 // Compare unit display names...
2297 return -1;
2298 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
2299 return 1;
2300
2301 // ... and body style names.
2303 return -1;
2304 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
2305 return 1;
2306 }
2307
2308 return retv;
2309}
2310
2311
2312int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
2313{
2314 if( Type() != aOther.Type() )
2315 return Type() - aOther.Type();
2316
2317 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
2318
2319 return Compare( *tmp, aCompareFlags );
2320}
2321
2322
2323double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2324{
2325 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
2326
2327 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
2328 double similarity = 0.0;
2329 int totalItems = 0;
2330
2331 if( m_Uuid == aOther.m_Uuid )
2332 return 1.0;
2333
2334 for( const SCH_ITEM& item : m_drawings )
2335 {
2336 totalItems += 1;
2337 double max_similarity = 0.0;
2338
2339 for( const SCH_ITEM& otherItem : other.m_drawings )
2340 {
2341 double temp_similarity = item.Similarity( otherItem );
2342 max_similarity = std::max( max_similarity, temp_similarity );
2343
2344 if( max_similarity == 1.0 )
2345 break;
2346 }
2347
2348 similarity += max_similarity;
2349 }
2350
2351 for( const SCH_PIN* pin : GetGraphicalPins( 0, 0 ) )
2352 {
2353 totalItems += 1;
2354 double max_similarity = 0.0;
2355
2356 for( const SCH_PIN* otherPin : other.GetGraphicalPins( 0, 0 ) )
2357 {
2358 double temp_similarity = pin->Similarity( *otherPin );
2359 max_similarity = std::max( max_similarity, temp_similarity );
2360
2361 if( max_similarity == 1.0 )
2362 break;
2363 }
2364
2365 similarity += max_similarity;
2366 }
2367
2368 if( totalItems == 0 )
2369 similarity = 0.0;
2370 else
2371 similarity /= totalItems;
2372
2374 similarity *= 0.9;
2375
2377 similarity *= 0.9;
2378
2380 similarity *= 0.9;
2381
2383 similarity *= 0.9;
2384
2385 if( m_flags != other.m_flags )
2386 similarity *= 0.9;
2387
2388 if( m_unitCount != other.m_unitCount )
2389 similarity *= 0.5;
2390
2391 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
2392 similarity *= 0.5;
2393 else if( m_bodyStyleNames != other.m_bodyStyleNames )
2394 similarity *= 0.9;
2395
2396 if( m_pinNameOffset != other.m_pinNameOffset )
2397 similarity *= 0.9;
2398
2399 if( m_showPinNames != other.m_showPinNames )
2400 similarity *= 0.9;
2401
2402 if( m_showPinNumbers != other.m_showPinNumbers )
2403 similarity *= 0.9;
2404
2405 return similarity;
2406}
2407
2408
2410{
2411 return static_cast<EMBEDDED_FILES*>( this );
2412}
2413
2414
2416{
2417 return static_cast<const EMBEDDED_FILES*>( this );
2418}
2419
2420
2421void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2422{
2423 std::set<const LIB_SYMBOL*> visited;
2424 visited.insert( this );
2425
2426 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2427
2428 while( parent )
2429 {
2430 // Cycle detected - parent chain points back to an already visited symbol
2431 if( visited.count( parent.get() ) )
2432 {
2433 wxLogTrace( traceSymbolInheritance,
2434 wxT( "AppendParentEmbeddedFiles: Circular inheritance detected in "
2435 "symbol '%s' (lib: %s)" ),
2436 m_name, m_libId.GetLibNickname().wx_str() );
2437 break;
2438 }
2439
2440 visited.insert( parent.get() );
2441 aStack.push_back( parent->GetEmbeddedFiles() );
2442 parent = parent->GetParent().lock();
2443 }
2444}
2445
2446
2447std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2448{
2449 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2450
2451 std::set<KIFONT::OUTLINE_FONT*> fonts;
2452
2453 for( const SCH_ITEM& item : m_drawings )
2454 {
2455 if( item.Type() == SCH_TEXT_T )
2456 {
2457 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2458
2459 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2460 {
2461 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2462 auto permission = outline->GetEmbeddingPermission();
2463
2464 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2465 {
2466 fonts.insert( outline );
2467 }
2468 }
2469 }
2470 }
2471
2472 return fonts;
2473}
2474
2475
2477{
2478 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2479
2480 for( KIFONT::OUTLINE_FONT* font : fonts )
2481 {
2482 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2484 }
2485}
2486
2487
2488std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2489{
2490 for( const std::set<wxString>& group : m_jumperPinGroups )
2491 {
2492 if( group.contains( aPinNumber ) )
2493 return group;
2494 }
2495
2496 return std::nullopt;
2497}
2498
2499static struct LIB_SYMBOL_DESC
2500{
2502 {
2506
2507 const wxString groupFields = _HKI( "Fields" );
2508
2511 groupFields );
2514 groupFields );
2517 groupFields );
2520 groupFields );
2523 groupFields );
2524
2525 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2526
2527 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2530 groupSymbolDef );
2531 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2534 groupSymbolDef );
2535
2536 const wxString groupPinDisplay = _HKI( "Pin Display" );
2537
2538 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2540 groupPinDisplay );
2541 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2543 groupPinDisplay );
2544 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2547 groupPinDisplay );
2548 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2550 groupPinDisplay );
2551
2552 const wxString groupAttributes = _HKI( "Attributes" );
2553
2554 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2557 groupAttributes );
2558 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Board" ),
2561 groupAttributes );
2562 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2565 groupAttributes );
2566 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Position Files" ),
2569 groupAttributes );
2570
2571 const wxString groupUnits = _HKI( "Units and Body Styles" );
2572
2573 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2575 groupUnits );
2576 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2579 groupUnits );
2580
2581 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2582 {
2583 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2584 return symbol->IsMultiBodyStyle();
2585
2586 return false;
2587 };
2588
2591 groupUnits )
2592 .SetAvailableFunc( multiBodyStyle )
2594 []( INSPECTABLE* aItem )
2595 {
2596 wxPGChoices choices;
2597
2598 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2599 {
2600 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2601 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2602 }
2603
2604 return choices;
2605 } );
2606 }
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
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:162
const KIID m_Uuid
Definition eda_item.h:527
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
void ClearSelected()
Definition eda_item.h:143
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:538
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:151
virtual void ClearTempFlags()
Definition eda_item.h:175
FILL_T GetFillMode() const
Definition eda_shape.h:142
virtual bool IsVisible() const
Definition eda_text.h:187
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:400
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:898
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:348
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:478
LIBRENTRYOPTIONS m_options
Special symbol features such as POWER or NORMAL.
Definition lib_symbol.h:896
wxString GetRefProp() const
Definition lib_symbol.h:367
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:468
wxString m_shownDescriptionCache
Definition lib_symbol.h:922
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:344
std::weak_ptr< LIB_SYMBOL > m_parent
Use for inherited symbols.
Definition lib_symbol.h:880
void SetExcludedFromBoardProp(bool aExclude)
Definition lib_symbol.h:514
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:914
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:908
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
void SetKeywordsProp(const wxString &aKeywords)
Definition lib_symbol.h:412
bool IsDerived() const
Definition lib_symbol.h:200
std::map< int, wxString > & GetUnitDisplayNames()
Definition lib_symbol.h:750
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:892
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:520
void SetLib(LEGACY_SYMBOL_LIB *aLibrary)
bool GetPowerSymbolProp() const
Definition lib_symbol.h:417
bool IsMultiBodyStyle() const override
Definition lib_symbol.h:774
int GetMaxPinNumber() const
std::vector< SEARCH_TERM > m_searchTermsCache
Definition lib_symbol.h:920
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:340
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:901
void SetUnitsInterchangeableProp(bool aInterchangeable)
Definition lib_symbol.h:473
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
LEGACY_SYMBOL_LIB * m_library
Definition lib_symbol.h:900
bool GetExcludedFromPosFilesProp() const
Definition lib_symbol.h:519
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
wxString m_keyWords
Search keywords.
Definition lib_symbol.h:902
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:397
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:372
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:879
wxString GetValueProp() const
Definition lib_symbol.h:377
bool GetExcludedFromBOMProp() const
Definition lib_symbol.h:499
void SetKeyWords(const wxString &aKeyWords)
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:332
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:458
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:445
const std::vector< wxString > & GetBodyStyleNames() const
Definition lib_symbol.h:787
void SetBodyStyleProp(const wxString &aBodyStyle) override
Definition lib_symbol.h:483
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:886
void SetExcludedFromSimProp(bool aExclude)
Definition lib_symbol.h:494
bool GetExcludedFromBoardProp() const
Definition lib_symbol.h:509
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:884
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:392
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:784
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:889
wxArrayString m_fpFilters
List of suitable footprint names for the symbol (wild card names accepted).
Definition lib_symbol.h:903
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:489
int GetBodyStyleCount() const override
Definition lib_symbol.h:776
void SetDatasheetProp(const wxString &aDatasheet)
Definition lib_symbol.h:402
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:422
void SetExcludedFromBOMProp(bool aExclude)
Definition lib_symbol.h:504
int m_unitCount
Number of units (parts) per package.
Definition lib_symbol.h:888
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:407
std::vector< wxString > m_bodyStyleNames
Definition lib_symbol.h:915
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:382
int GetPinCount() override
std::map< wxString, wxString > m_chooserFieldsCache
Definition lib_symbol.h:923
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:921
bool GetLocalPowerSymbolProp() const
Definition lib_symbol.h:430
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:912
void SetUnitProp(int aUnits)
Definition lib_symbol.h:463
wxString GetFootprintProp() const
Definition lib_symbol.h:387
void SetPinNamesInsideProp(bool aInside)
Definition lib_symbol.h:450
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:435
virtual void SetName(const wxString &aName)
void SetNormal()
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:336
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:136
bool GetColorMode() const
Definition plotter.h:164
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:73
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:116
FIELD_T GetId() const
Definition sch_field.h:120
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:227
void SetText(const wxString &aText) override
int m_unit
Definition sch_item.h:779
int m_bodyStyle
Definition sch_item.h:780
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:727
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:254
friend class LIB_SYMBOL
Definition sch_item.h:798
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:363
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:258
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:296
The common library.
#define DEFAULT_PIN_NAME_OFFSET
The intersheets references prefix string.
#define _(s)
RECURSE_MODE
Definition eda_item.h:51
INSPECT_RESULT
Definition eda_item.h:45
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:92
#define IGNORE_PARENT_GROUP
Definition eda_item.h:56
#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:46
@ FILLED_WITH_COLOR
Definition eda_shape.h:60
@ FILLED_WITH_BG_BODYCOLOR
Definition eda_shape.h:59
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:466
@ LAYER_FIELDS
Definition layer_ids.h:462
#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:589
std::vector< wxString > m_pinNumbers
Definition lib_symbol.h:603
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:78
@ LIB_SYMBOL_T
Definition typeinfo.h:152
@ TYPE_NOT_INIT
Definition typeinfo.h:81
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ SCH_TEXT_T
Definition typeinfo.h:155
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695