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