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