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