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