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