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