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