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