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( aDimmed )
629 {
630 color.Desaturate();
631 color = color.Mix( bg, 0.5f );
632 }
633
634 aPlotter->SetColor( color );
635
636 for( SCH_ITEM& item : m_drawings )
637 {
638 // Do not plot private items
639 if( item.IsPrivate() )
640 continue;
641
642 // LIB_FIELDs are not plotted here, because this plot function is used to plot schematic
643 // items which have their own SCH_FIELDs
644 if( item.Type() == SCH_FIELD_T )
645 continue;
646
647 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
648 continue;
649
650 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
651 continue;
652
653 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
654 }
655}
656
657
658void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
659 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
660{
661 wxASSERT( aPlotter != nullptr );
662
663 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
664 COLOR4D color = renderSettings->GetLayerColor( LAYER_FIELDS );
665 COLOR4D bg = renderSettings->GetBackgroundColor();
666
667 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
668 bg = COLOR4D::WHITE;
669
670 if( aDimmed )
671 {
672 color.Desaturate();
673 color = color.Mix( bg, 0.5f );
674 }
675
676 aPlotter->SetColor( color );
677
678 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
679 {
680 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
681
682 if( !renderSettings->m_ShowHiddenFields && !field.IsVisible() )
683 continue;
684
685 // The reference is a special case: we should change the basic text
686 // to add '?' and the part id
687 wxString tmp = field.GetText();
688
689 field.SetText( field.GetFullText( aUnit ) );
690 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
691
692 field.SetText( tmp );
693 }
694}
695
696
698{
699 std::vector<SCH_SHAPE*> potential_top_items;
700 std::vector<SCH_ITEM*> bottom_items;
701
702 for( SCH_ITEM& item : m_drawings )
703 {
704 if( item.Type() == SCH_SHAPE_T )
705 {
706 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
707
709 potential_top_items.push_back( &shape );
710 else
711 bottom_items.push_back( &item );
712 }
713 else
714 {
715 bottom_items.push_back( &item );
716 }
717 }
718
719 std::sort( potential_top_items.begin(), potential_top_items.end(),
720 []( SCH_ITEM* a, SCH_ITEM* b )
721 {
722 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
723 } );
724
725 for( SCH_SHAPE* item : potential_top_items )
726 {
727 for( SCH_ITEM* bottom_item : bottom_items )
728 {
729 if( item->GetBoundingBox().Contains( bottom_item->GetBoundingBox() ) )
730 {
731 item->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
732 break;
733 }
734 }
735 }
736}
737
738
740{
741 wxASSERT( aItem != nullptr );
742
743 // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
744 // omitted when saving to disk.
745 if( aItem->Type() == SCH_FIELD_T )
746 {
747 if( static_cast<SCH_FIELD*>( aItem )->IsMandatory() )
748 return;
749 }
750
751 LIB_ITEMS& items = m_drawings[aItem->Type()];
752
753 for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
754 {
755 if( &*i == aItem )
756 {
757 items.erase( i );
758 break;
759 }
760 }
761}
762
763
764void LIB_SYMBOL::AddDrawItem( SCH_ITEM* aItem, bool aSort )
765{
766 if( aItem )
767 {
768 aItem->SetParent( this );
769
770 m_drawings.push_back( aItem );
771
772 if( aSort )
773 m_drawings.sort();
774 }
775}
776
777
778std::vector<SCH_PIN*> LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle ) const
779{
780 if( std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock() )
781 return parent->GetGraphicalPins( aUnit, aBodyStyle );
782
783 std::vector<SCH_PIN*> pins;
784
785 /* Notes:
786 * when aUnit == 0: no unit filtering
787 * when aBodyStyle == 0: no body style filtering
788 * when m_unit == 0, the item is common to all units
789 * when m_bodyStyle == 0, the item is common to all body styles
790 */
791
792 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
793 {
794 // Unit filtering:
795 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
796 continue;
797
798 // De Morgan variant filtering:
799 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
800 continue;
801
802 // TODO: get rid of const_cast. (It used to be a C-style cast so was less noticeable.)
803 SCH_PIN* pin = const_cast<SCH_PIN*>( static_cast<const SCH_PIN*>( &item ) );
804 wxLogTrace(
806 wxString::Format(
807 "GetGraphicalPins: lib='%s' unit=%d body=%d -> include pin name='%s' number='%s' shownNum='%s'",
808 GetLibId().Format().wx_str(), aUnit, aBodyStyle, pin->GetName(), pin->GetNumber(),
809 pin->GetShownNumber() ) );
810 pins.push_back( pin );
811 }
812
813 return pins;
814}
815
816
817std::vector<LIB_SYMBOL::UNIT_PIN_INFO> LIB_SYMBOL::GetUnitPinInfo() const
818{
819 std::vector<UNIT_PIN_INFO> units;
820
821 int unitCount = std::max( GetUnitCount(), 1 );
822
823 auto compareByPosition = []( SCH_PIN* a, SCH_PIN* b )
824 {
825 VECTOR2I positionA = a->GetPosition();
826 VECTOR2I positionB = b->GetPosition();
827
828 if( positionA.x != positionB.x )
829 return positionA.x < positionB.x;
830
831 return positionA.y < positionB.y;
832 };
833
834 for( int unitIdx = 1; unitIdx <= unitCount; ++unitIdx )
835 {
836 UNIT_PIN_INFO unitInfo;
837 unitInfo.m_unitName = GetUnitDisplayName( unitIdx, false );
838
839 std::vector<SCH_PIN*> pinList = GetGraphicalPins( unitIdx, 0 );
840
841 std::sort( pinList.begin(), pinList.end(), compareByPosition );
842
843 std::unordered_set<wxString> seenNumbers;
844
845 for( SCH_PIN* basePin : pinList )
846 {
847 bool stackedValid = false;
848 std::vector<wxString> expandedNumbers = basePin->GetStackedPinNumbers( &stackedValid );
849
850 if( stackedValid && !expandedNumbers.empty() )
851 {
852 for( const wxString& number : expandedNumbers )
853 {
854 if( seenNumbers.insert( number ).second )
855 unitInfo.m_pinNumbers.push_back( number );
856 }
857
858 continue;
859 }
860
861 const wxString& number = basePin->GetNumber();
862
863 if( !number.IsEmpty() && seenNumbers.insert( number ).second )
864 unitInfo.m_pinNumbers.push_back( number );
865 }
866
867 units.push_back( std::move( unitInfo ) );
868 }
869
870 return units;
871}
872
873
874std::vector<LIB_SYMBOL::LOGICAL_PIN> LIB_SYMBOL::GetLogicalPins( int aUnit, int aBodyStyle ) const
875{
876 std::vector<LOGICAL_PIN> out;
877
878 for( SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
879 {
880 bool valid = false;
881 std::vector<wxString> expanded = pin->GetStackedPinNumbers( &valid );
882
883 if( valid && !expanded.empty() )
884 {
885 for( const wxString& num : expanded )
886 {
887 out.push_back( LOGICAL_PIN{ pin, num } );
888 wxLogTrace( traceStackedPins,
889 wxString::Format( "GetLogicalPins: base='%s' -> '%s'", pin->GetShownNumber(), num ) );
890 }
891 }
892 else
893 {
894 out.push_back( LOGICAL_PIN{ pin, pin->GetShownNumber() } );
895 wxLogTrace( traceStackedPins,
896 wxString::Format( "GetLogicalPins: base='%s' (no expansion)", pin->GetShownNumber() ) );
897 }
898 }
899
900 return out;
901}
902
903
905{
906 int count = 0;
907
908 for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) )
909 {
910 int pinCount = pin->GetStackedPinCount();
911 count += pinCount;
912 }
913
914 wxLogTrace( "CVPCB_PINCOUNT", "LIB_SYMBOL::GetPinCount total for lib='%s' => %d", GetLibId().Format().wx_str(),
915 count );
916
917 return count;
918}
919
920
921SCH_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aBodyStyle ) const
922{
923 for( SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) )
924 {
925 if( aNumber == pin->GetNumber() )
926 return pin;
927 }
928
929 return nullptr;
930}
931
932
933bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames, bool aTestType,
934 bool aTestOrientation, bool aTestLength ) const
935{
936 for( const SCH_PIN* pin : GetGraphicalPins() )
937 {
938 wxASSERT( pin );
939 bool foundMatch = false;
940
941 for( const SCH_PIN* otherPin : aOtherPart.GetGraphicalPins() )
942 {
943 wxASSERT( otherPin );
944
945 // Same unit?
946 if( pin->GetUnit() != otherPin->GetUnit() )
947 continue;
948
949 // Same body stype?
950 if( pin->GetBodyStyle() != otherPin->GetBodyStyle() )
951 continue;
952
953 // Same position?
954 if( pin->GetPosition() != otherPin->GetPosition() )
955 continue;
956
957 // Same number?
958 if( aTestNums && ( pin->GetNumber() != otherPin->GetNumber() ) )
959 continue;
960
961 // Same name?
962 if( aTestNames && ( pin->GetName() != otherPin->GetName() ) )
963 continue;
964
965 // Same electrical type?
966 if( aTestType && ( pin->GetType() != otherPin->GetType() ) )
967 continue;
968
969 // Same orientation?
970 if( aTestOrientation && ( pin->GetOrientation() != otherPin->GetOrientation() ) )
971 continue;
972
973 // Same length?
974 if( aTestLength && ( pin->GetLength() != otherPin->GetLength() ) )
975 continue;
976
977 foundMatch = true;
978 break; // Match found so search is complete.
979 }
980
981 if( !foundMatch )
982 {
983 // This means there was not an identical (according to the arguments)
984 // pin at the same position in the other symbol.
985 return true;
986 }
987 }
988
989 // The loop never gave up, so no conflicts were found.
990 return false;
991}
992
993std::vector<SCH_PIN*> LIB_SYMBOL::GetPins() const
994{
995 // Back-compat shim: return graphical pins for all units/body styles
996 return GetGraphicalPins( 0, 0 );
997}
998
999
1000const BOX2I LIB_SYMBOL::GetUnitBoundingBox( int aUnit, int aBodyStyle, bool aIgnoreHiddenFields,
1001 bool aIgnoreLabelsOnInvisiblePins ) const
1002{
1003 BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works
1004
1005 if( std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock() )
1006 bBox = parent->GetUnitBoundingBox( aUnit, aBodyStyle, aIgnoreHiddenFields, aIgnoreLabelsOnInvisiblePins );
1007
1008 for( const SCH_ITEM& item : m_drawings )
1009 {
1010 if( item.m_unit > 0 && m_unitCount > 1 && aUnit > 0 && aUnit != item.m_unit )
1011 continue;
1012
1013 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1014 continue;
1015
1016 if( aIgnoreHiddenFields && item.Type() == SCH_FIELD_T )
1017 {
1018 if( !static_cast<const SCH_FIELD&>( item ).IsVisible() )
1019 continue;
1020 }
1021
1022 if( item.Type() == SCH_PIN_T && !aIgnoreLabelsOnInvisiblePins )
1023 {
1024 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1025 bBox.Merge( pin.GetBoundingBox( true, true, false ) );
1026 }
1027 else
1028 {
1029 bBox.Merge( item.GetBoundingBox() );
1030 }
1031 }
1032
1033 return bBox;
1034}
1035
1036
1037const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aIncludePins,
1038 bool aIncludePrivateItems ) const
1039{
1040 BOX2I bbox;
1041
1042 for( const SCH_ITEM& item : m_drawings )
1043 {
1044 if( item.m_unit > 0 && aUnit > 0 && aUnit != item.m_unit )
1045 continue;
1046
1047 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1048 continue;
1049
1050 if( item.IsPrivate() && !aIncludePrivateItems )
1051 continue;
1052
1053 if( item.Type() == SCH_FIELD_T )
1054 continue;
1055
1056 if( item.Type() == SCH_PIN_T )
1057 {
1058 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1059
1060 if( pin.IsVisible() )
1061 {
1062 // Note: the roots of the pins are always included for symbols that don't have
1063 // a well-defined body.
1064
1065 if( aIncludePins )
1066 bbox.Merge( pin.GetBoundingBox( false, false, false ) );
1067 else
1068 bbox.Merge( pin.GetPinRoot() );
1069 }
1070 }
1071 else
1072 {
1073 bbox.Merge( item.GetBoundingBox() );
1074 }
1075 }
1076
1077 return bbox;
1078}
1079
1080
1082{
1083 m_drawings[SCH_FIELD_T].clear();
1084}
1085
1086
1088{
1089 AddDrawItem( aField );
1090}
1091
1092
1093void LIB_SYMBOL::SetFields( const std::vector<SCH_FIELD>& aFieldsList )
1094{
1096
1097 for( const SCH_FIELD& src : aFieldsList )
1098 {
1099 // drawings is a ptr_vector, new and copy an object on the heap.
1100 SCH_FIELD* field = new SCH_FIELD( src );
1101
1102 field->SetParent( this );
1103 m_drawings.push_back( field );
1104 }
1105
1106 m_drawings.sort();
1107}
1108
1109
1110void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aList, bool aVisibleOnly ) const
1111{
1112 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1113 {
1114 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1115
1116 if( aVisibleOnly )
1117 {
1118 if( !field->IsVisible() || field->GetText().IsEmpty() )
1119 continue;
1120 }
1121
1122 aList.push_back( const_cast<SCH_FIELD*>( field ) );
1123 }
1124
1125 std::sort( aList.begin(), aList.end(),
1126 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1127 {
1128 return lhs->GetOrdinal() < rhs->GetOrdinal();
1129 } );
1130}
1131
1132
1133void LIB_SYMBOL::CopyFields( std::vector<SCH_FIELD>& aList )
1134{
1135 std::vector<SCH_FIELD*> orderedFields;
1136
1137 GetFields( orderedFields );
1138
1139 for( SCH_FIELD* field : orderedFields )
1140 aList.emplace_back( *field );
1141}
1142
1143
1145{
1146 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id
1147
1148 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1149 ordinal = std::max( ordinal, static_cast<const SCH_FIELD*>( &item )->GetOrdinal() + 1 );
1150
1151 return ordinal;
1152}
1153
1154
1155const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const
1156{
1157 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1158 {
1159 const SCH_FIELD* field = static_cast<const SCH_FIELD*>( &item );
1160
1161 if( field->GetId() == aFieldType )
1162 return field;
1163 }
1164
1165 return nullptr;
1166}
1167
1168
1170{
1171 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1172 {
1173 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1174
1175 if( field->GetId() == aFieldType )
1176 return field;
1177 }
1178
1179 return nullptr;
1180}
1181
1182
1183const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const
1184{
1185 for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1186 {
1187 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1188
1189 if( field.GetName() == aFieldName )
1190 return &field;
1191 }
1192
1193 return nullptr;
1194}
1195
1196
1197SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName )
1198{
1199 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1200 {
1201 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1202
1203 if( field.GetName() == aFieldName )
1204 return &field;
1205 }
1206
1207 return nullptr;
1208}
1209
1210
1212{
1213 for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] )
1214 {
1215 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
1216
1217 if( field.GetCanonicalName().IsSameAs( aFieldName, false ) )
1218 return &field;
1219 }
1220
1221 return nullptr;
1222}
1223
1224
1226{
1227 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
1228 wxASSERT( field != nullptr );
1229 return *field;
1230}
1231
1232
1234{
1235 const SCH_FIELD* field = GetField( FIELD_T::REFERENCE );
1236 wxASSERT( field != nullptr );
1237 return *field;
1238}
1239
1240
1242{
1243 const SCH_FIELD* field = GetField( FIELD_T::FOOTPRINT );
1244 wxASSERT( field != nullptr );
1245 return *field;
1246}
1247
1248
1250{
1251 const SCH_FIELD* field = GetField( FIELD_T::DATASHEET );
1252 wxASSERT( field != nullptr );
1253 return *field;
1254}
1255
1256
1258{
1259 const SCH_FIELD* field = GetField( FIELD_T::DESCRIPTION );
1260 wxASSERT( field != nullptr );
1261 return *field;
1262}
1263
1264
1266{
1267 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
1268
1269 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1270
1271 wxString prefix = refDesignator;
1272
1273 while( prefix.Length() )
1274 {
1275 wxUniCharRef last = prefix.Last();
1276
1277 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1278 prefix.RemoveLast();
1279 else
1280 break;
1281 }
1282
1283 // Avoid a prefix containing trailing/leading spaces
1284 prefix.Trim( true );
1285 prefix.Trim( false );
1286
1287 return prefix;
1288}
1289
1290
1291void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1292{
1293 for( SCH_ITEM& item : m_drawings )
1294 aFunction( &item );
1295}
1296
1297
1298void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1299{
1300 for( SCH_ITEM& item : m_drawings )
1301 item.Move( aOffset );
1302}
1303
1304
1305// Before V10 we didn't store the number of body styles in a symbol -- we just looked through all
1306// its drawings each time we wanted to know. This is now only used to set the count when a legacy
1307// symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count
1308// is always 1 or 2, and when 2 it is always a De Morgan pair.)
1310{
1311 for( const SCH_ITEM& item : m_drawings )
1312 {
1313 if( item.m_bodyStyle > BODY_STYLE::BASE )
1314 return true;
1315 }
1316
1317 if( std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock() )
1318 return parent->HasLegacyAlternateBodyStyle();
1319
1320 return false;
1321}
1322
1323
1325{
1326 if( std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock() )
1327 return parent->GetMaxPinNumber();
1328
1329 int maxPinNumber = 0;
1330
1331 for( const SCH_ITEM& item : m_drawings[SCH_PIN_T] )
1332 {
1333 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1334 long currentPinNumber = 0;
1335
1336 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1337 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1338 }
1339
1340 return maxPinNumber;
1341}
1342
1343
1345{
1347
1348 for( SCH_ITEM& item : m_drawings )
1349 item.ClearTempFlags();
1350}
1351
1352
1354{
1356
1357 for( SCH_ITEM& item : m_drawings )
1358 item.ClearEditFlags();
1359}
1360
1361
1362SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint )
1363{
1364 for( SCH_ITEM& item : m_drawings )
1365 {
1366 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1367 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1368 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1369 {
1370 continue;
1371 }
1372
1373 if( item.HitTest( aPoint ) )
1374 return &item;
1375 }
1376
1377 return nullptr;
1378}
1379
1380
1381SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint,
1382 const TRANSFORM& aTransform )
1383{
1384 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1385 * VECTOR2I& pt ) to search items.
1386 * because this function uses DefaultTransform as orient/mirror matrix
1387 * we temporary copy aTransform in DefaultTransform
1388 */
1389 TRANSFORM transform = DefaultTransform;
1390 DefaultTransform = aTransform;
1391
1392 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1393
1394 // Restore matrix
1395 DefaultTransform = transform;
1396
1397 return item;
1398}
1399
1400
1401INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
1402{
1403 // The part itself is never inspected, only its children
1404 for( SCH_ITEM& item : m_drawings )
1405 {
1406 if( item.IsType( aScanTypes ) )
1407 {
1408 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1409 return INSPECT_RESULT::QUIT;
1410 }
1411 }
1412
1414}
1415
1416
1417void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1418{
1419 if( m_unitCount == aCount )
1420 return;
1421
1422 if( aCount < m_unitCount )
1423 {
1424 // Iterate each drawing-type bucket and erase items that belong to units > aCount.
1425 for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
1426 {
1427 auto it = m_drawings.begin( type );
1428
1429 while( it != m_drawings.end( type ) )
1430 {
1431 if( it->m_unit > aCount )
1432 it = m_drawings.erase( it ); // returns next iterator
1433 else
1434 ++it;
1435 }
1436 }
1437 }
1438 else if( aDuplicateDrawItems )
1439 {
1440 int prevCount = m_unitCount;
1441
1442 // Temporary storage for new items, as adding new items directly to
1443 // m_drawings may cause the buffer reallocation which invalidates the
1444 // iterators
1445 std::vector<SCH_ITEM*> tmp;
1446
1447 for( SCH_ITEM& item : m_drawings )
1448 {
1449 if( item.m_unit != 1 )
1450 continue;
1451
1452 for( int j = prevCount + 1; j <= aCount; j++ )
1453 {
1454 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1455 newItem->m_unit = j;
1456 tmp.push_back( newItem );
1457 }
1458 }
1459
1460 for( SCH_ITEM* item : tmp )
1461 m_drawings.push_back( item );
1462 }
1463
1464 m_drawings.sort();
1465 m_unitCount = aCount;
1466}
1467
1468
1470{
1471 if( std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock() )
1472 return parent->GetUnitCount();
1473
1474 return m_unitCount;
1475}
1476
1477
1478void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins )
1479{
1480 if( GetBodyStyleCount() == aCount )
1481 return;
1482
1483 // Duplicate items to create the converted shape
1484 if( GetBodyStyleCount() < aCount )
1485 {
1486 if( aDuplicateDrawItems || aDuplicatePins )
1487 {
1488 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1489
1490 for( SCH_ITEM& item : m_drawings )
1491 {
1492 if( item.Type() != SCH_PIN_T && !aDuplicateDrawItems )
1493 continue;
1494
1495 if( item.m_bodyStyle == 1 )
1496 {
1497 SCH_ITEM* newItem = item.Duplicate( IGNORE_PARENT_GROUP );
1498 newItem->m_bodyStyle = 2;
1499 tmp.push_back( newItem );
1500 }
1501 }
1502
1503 // Transfer the new pins to the LIB_SYMBOL.
1504 for( SCH_ITEM* item : tmp )
1505 m_drawings.push_back( item );
1506 }
1507 }
1508 else
1509 {
1510 // Delete converted shape items because the converted shape does not exist
1512
1513 while( i != m_drawings.end() )
1514 {
1515 if( i->m_bodyStyle > 1 )
1516 i = m_drawings.erase( i );
1517 else
1518 ++i;
1519 }
1520 }
1521
1522 m_drawings.sort();
1523}
1524
1525
1526std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1527{
1528 std::vector<SCH_ITEM*> unitItems;
1529
1530 for( SCH_ITEM& item : m_drawings )
1531 {
1532 if( item.Type() == SCH_FIELD_T )
1533 continue;
1534
1535 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1536 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1537 {
1538 unitItems.push_back( &item );
1539 }
1540 }
1541
1542 return unitItems;
1543}
1544
1545
1546std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
1547{
1548 std::vector<LIB_SYMBOL_UNIT> units;
1549
1550 for( SCH_ITEM& item : m_drawings )
1551 {
1552 if( item.Type() == SCH_FIELD_T )
1553 continue;
1554
1555 int unit = item.GetUnit();
1556 int bodyStyle = item.GetBodyStyle();
1557
1558 auto it = std::find_if( units.begin(), units.end(),
1559 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
1560 {
1561 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
1562 } );
1563
1564 if( it == units.end() )
1565 {
1566 LIB_SYMBOL_UNIT newUnit;
1567 newUnit.m_unit = item.GetUnit();
1568 newUnit.m_bodyStyle = item.GetBodyStyle();
1569 newUnit.m_items.push_back( &item );
1570 units.emplace_back( newUnit );
1571 }
1572 else
1573 {
1574 it->m_items.push_back( &item );
1575 }
1576 }
1577
1578 return units;
1579}
1580
1581
1582#define REPORT( msg ) \
1583 { \
1584 if( aReporter ) \
1585 aReporter->Report( msg ); \
1586 }
1587#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
1588
1589int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
1590{
1591 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MM );
1592
1593 if( m_me == aRhs.m_me )
1594 return 0;
1595
1596 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
1597 {
1598 if( int tmp = m_name.Cmp( aRhs.m_name ) )
1599 return tmp;
1600
1601 if( int tmp = m_libId.compare( aRhs.m_libId ) )
1602 return tmp;
1603
1604 if( m_parent.lock() < aRhs.m_parent.lock() )
1605 return -1;
1606
1607 if( m_parent.lock() > aRhs.m_parent.lock() )
1608 return 1;
1609 }
1610
1611 int retv = 0;
1612
1613 if( m_options != aRhs.m_options )
1614 {
1615 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
1616 REPORT( _( "Power flag differs." ) );
1617
1618 if( !aReporter )
1619 return retv;
1620 }
1621
1622 if( int tmp = m_unitCount - aRhs.m_unitCount )
1623 {
1624 retv = tmp;
1625 REPORT( _( "Unit count differs." ) );
1626
1627 if( !aReporter )
1628 return retv;
1629 }
1630
1631 // Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
1632
1633 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
1634 std::set<const SCH_FIELD*> aFields;
1635 std::set<const SCH_PIN*> aPins;
1636
1637 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
1638 {
1639 if( it->Type() == SCH_SHAPE_T )
1640 aShapes.insert( &( *it ) );
1641 else if( it->Type() == SCH_FIELD_T )
1642 aFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
1643 else if( it->Type() == SCH_PIN_T )
1644 aPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
1645 }
1646
1647 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
1648 std::set<const SCH_FIELD*> bFields;
1649 std::set<const SCH_PIN*> bPins;
1650
1651 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
1652 {
1653 if( it->Type() == SCH_SHAPE_T )
1654 bShapes.insert( &( *it ) );
1655 else if( it->Type() == SCH_FIELD_T )
1656 bFields.insert( static_cast<const SCH_FIELD*>( &( *it ) ) );
1657 else if( it->Type() == SCH_PIN_T )
1658 bPins.insert( static_cast<const SCH_PIN*>( &( *it ) ) );
1659 }
1660
1661 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
1662 {
1663 retv = tmp;
1664 REPORT( _( "Graphic item count differs." ) );
1665
1666 if( !aReporter )
1667 return retv;
1668 }
1669 else
1670 {
1671 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
1672 {
1673 if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) )
1674 {
1675 retv = tmp2;
1676 REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ),
1677 ITEM_DESC( *bIt ) ) );
1678
1679 if( !aReporter )
1680 return retv;
1681 }
1682 }
1683 }
1684
1685 for( const SCH_PIN* aPin : aPins )
1686 {
1687 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
1688
1689 if( !bPin )
1690 {
1691 retv = 1;
1692 REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
1693
1694 if( !aReporter )
1695 return retv;
1696 }
1697 else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
1698 {
1699 retv = tmp;
1700 REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ),
1701 ITEM_DESC( bPin ) ) );
1702
1703 if( !aReporter )
1704 return retv;
1705 }
1706 }
1707
1708 for( const SCH_PIN* bPin : bPins )
1709 {
1710 const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
1711
1712 if( !aPin )
1713 {
1714 retv = 1;
1715 REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
1716
1717 if( !aReporter )
1718 return retv;
1719 }
1720 }
1721
1722 for( const SCH_FIELD* aField : aFields )
1723 {
1724 const SCH_FIELD* bField = nullptr;
1725
1726 if( aField->IsMandatory() )
1727 bField = aRhs.GetField( aField->GetId() );
1728 else
1729 bField = aRhs.GetField( aField->GetName() );
1730
1731 if( !bField )
1732 {
1733 retv = 1;
1734 REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
1735
1736 if( !aReporter )
1737 return retv;
1738 }
1739 else
1740 {
1741 int tmp = 0;
1742
1743 // For EQUALITY comparison, we need to compare field content directly
1744 // since SCH_ITEM::compare() returns 0 for EQUALITY flag
1745 if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
1746 {
1747 // Compare field text content
1748 tmp = aField->GetText().compare( bField->GetText() );
1749 }
1750
1751 if( tmp == 0 )
1752 {
1753 // Fall back to base class comparison for other properties
1754 tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags );
1755 }
1756
1757 if( tmp != 0 )
1758 {
1759 retv = tmp;
1760 REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ),
1761 ITEM_DESC( aField ), ITEM_DESC( bField ) ) );
1762
1763 if( !aReporter )
1764 return retv;
1765 }
1766 }
1767 }
1768
1769 for( const SCH_FIELD* bField : bFields )
1770 {
1771 const SCH_FIELD* aField = nullptr;
1772
1773 if( bField->IsMandatory() )
1774 aField = aRhs.GetField( bField->GetId() );
1775 else
1776 aField = aRhs.GetField( bField->GetName() );
1777
1778 if( !aField )
1779 {
1780 retv = 1;
1781 REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
1782
1783 if( !aReporter )
1784 return retv;
1785 }
1786 }
1787
1788 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
1789 {
1790 retv = tmp;
1791 REPORT( _( "Footprint filter count differs." ) );
1792
1793 if( !aReporter )
1794 return retv;
1795 }
1796 else
1797 {
1798 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
1799 {
1800 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
1801 {
1802 retv = tmp2;
1803 REPORT( _( "Footprint filters differ." ) );
1804
1805 if( !aReporter )
1806 return retv;
1807 }
1808 }
1809 }
1810
1811 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
1812 {
1813 retv = tmp;
1814 REPORT( _( "Symbol keywords differ." ) );
1815
1816 if( !aReporter )
1817 return retv;
1818 }
1819
1820 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
1821 {
1822 retv = tmp;
1823 REPORT( _( "Symbol pin name offsets differ." ) );
1824
1825 if( !aReporter )
1826 return retv;
1827 }
1828
1829 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
1830 {
1831 if( m_showPinNames != aRhs.m_showPinNames )
1832 {
1833 retv = ( m_showPinNames ) ? 1 : -1;
1834 REPORT( _( "Show pin names settings differ." ) );
1835
1836 if( !aReporter )
1837 return retv;
1838 }
1839
1841 {
1842 retv = ( m_showPinNumbers ) ? 1 : -1;
1843 REPORT( _( "Show pin numbers settings differ." ) );
1844
1845 if( !aReporter )
1846 return retv;
1847 }
1848
1850 {
1851 retv = ( m_excludedFromSim ) ? -1 : 1;
1852 REPORT( _( "Exclude from simulation settings differ." ) );
1853
1854 if( !aReporter )
1855 return retv;
1856 }
1857
1859 {
1860 retv = ( m_excludedFromBOM ) ? -1 : 1;
1861 REPORT( _( "Exclude from bill of materials settings differ." ) );
1862
1863 if( !aReporter )
1864 return retv;
1865 }
1866
1868 {
1869 retv = ( m_excludedFromBoard ) ? -1 : 1;
1870 REPORT( _( "Exclude from board settings differ." ) );
1871
1872 if( !aReporter )
1873 return retv;
1874 }
1875 }
1876
1877 if( !aReporter )
1878 {
1879 if( m_unitsLocked != aRhs.m_unitsLocked )
1880 return ( m_unitsLocked ) ? 1 : -1;
1881
1882 // Compare unit display names...
1884 return -1;
1885 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
1886 return 1;
1887
1888 // ... and body style names.
1890 return -1;
1891 else if( m_bodyStyleNames > aRhs.m_bodyStyleNames )
1892 return 1;
1893 }
1894
1895 return retv;
1896}
1897
1898
1899int LIB_SYMBOL::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
1900{
1901 if( Type() != aOther.Type() )
1902 return Type() - aOther.Type();
1903
1904 const LIB_SYMBOL* tmp = static_cast<const LIB_SYMBOL*>( &aOther );
1905
1906 return Compare( *tmp, aCompareFlags );
1907}
1908
1909
1910double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
1911{
1912 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
1913
1914 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
1915 double similarity = 0.0;
1916 int totalItems = 0;
1917
1918 if( m_Uuid == aOther.m_Uuid )
1919 return 1.0;
1920
1921 for( const SCH_ITEM& item : m_drawings )
1922 {
1923 totalItems += 1;
1924 double max_similarity = 0.0;
1925
1926 for( const SCH_ITEM& otherItem : other.m_drawings )
1927 {
1928 double temp_similarity = item.Similarity( otherItem );
1929 max_similarity = std::max( max_similarity, temp_similarity );
1930
1931 if( max_similarity == 1.0 )
1932 break;
1933 }
1934
1935 similarity += max_similarity;
1936 }
1937
1938 for( const SCH_PIN* pin : GetPins() )
1939 {
1940 totalItems += 1;
1941 double max_similarity = 0.0;
1942
1943 for( const SCH_PIN* otherPin : other.GetPins() )
1944 {
1945 double temp_similarity = pin->Similarity( *otherPin );
1946 max_similarity = std::max( max_similarity, temp_similarity );
1947
1948 if( max_similarity == 1.0 )
1949 break;
1950 }
1951
1952 similarity += max_similarity;
1953 }
1954
1955 if( totalItems == 0 )
1956 similarity = 0.0;
1957 else
1958 similarity /= totalItems;
1959
1961 similarity *= 0.9;
1962
1964 similarity *= 0.9;
1965
1967 similarity *= 0.9;
1968
1969 if( m_flags != other.m_flags )
1970 similarity *= 0.9;
1971
1972 if( m_unitCount != other.m_unitCount )
1973 similarity *= 0.5;
1974
1975 if( GetBodyStyleCount() != other.GetBodyStyleCount() )
1976 similarity *= 0.5;
1977 else if( m_bodyStyleNames != other.m_bodyStyleNames )
1978 similarity *= 0.9;
1979
1980 if( m_pinNameOffset != other.m_pinNameOffset )
1981 similarity *= 0.9;
1982
1983 if( m_showPinNames != other.m_showPinNames )
1984 similarity *= 0.9;
1985
1986 if( m_showPinNumbers != other.m_showPinNumbers )
1987 similarity *= 0.9;
1988
1989 return similarity;
1990}
1991
1992
1994{
1995 return static_cast<EMBEDDED_FILES*>( this );
1996}
1997
1998
2000{
2001 return static_cast<const EMBEDDED_FILES*>( this );
2002}
2003
2004
2005void LIB_SYMBOL::AppendParentEmbeddedFiles( std::vector<EMBEDDED_FILES*>& aStack ) const
2006{
2007 std::shared_ptr<LIB_SYMBOL> parent = m_parent.lock();
2008
2009 while( parent )
2010 {
2011 aStack.push_back( parent->GetEmbeddedFiles() );
2012 parent = parent->GetParent().lock();
2013 }
2014}
2015
2016
2017std::set<KIFONT::OUTLINE_FONT*> LIB_SYMBOL::GetFonts() const
2018{
2019 using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
2020
2021 std::set<KIFONT::OUTLINE_FONT*> fonts;
2022
2023 for( const SCH_ITEM& item : m_drawings )
2024 {
2025 if( item.Type() == SCH_TEXT_T )
2026 {
2027 const SCH_TEXT& text = static_cast<const SCH_TEXT&>( item );
2028
2029 if( auto* font = text.GetFont(); font && !font->IsStroke() )
2030 {
2031 auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
2032 auto permission = outline->GetEmbeddingPermission();
2033
2034 if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE )
2035 {
2036 fonts.insert( outline );
2037 }
2038 }
2039 }
2040 }
2041
2042 return fonts;
2043}
2044
2045
2047{
2048 std::set<KIFONT::OUTLINE_FONT*> fonts = GetFonts();
2049
2050 for( KIFONT::OUTLINE_FONT* font : fonts )
2051 {
2052 auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2054 }
2055}
2056
2057
2058std::optional<const std::set<wxString>> LIB_SYMBOL::GetJumperPinGroup( const wxString& aPinNumber ) const
2059{
2060 for( const std::set<wxString>& group : m_jumperPinGroups )
2061 {
2062 if( group.contains( aPinNumber ) )
2063 return group;
2064 }
2065
2066 return std::nullopt;
2067}
2068
2069static struct LIB_SYMBOL_DESC
2070{
2072 {
2076
2077 const wxString groupFields = _HKI( "Fields" );
2078
2081 groupFields );
2084 groupFields );
2087 groupFields );
2090 groupFields );
2093 groupFields );
2094
2095 const wxString groupSymbolDef = _HKI( "Symbol Definition" );
2096
2097 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Power Symbol" ),
2100 groupSymbolDef );
2101 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Define as Local Power Symbol" ),
2104 groupSymbolDef );
2105
2106 const wxString groupPinDisplay = _HKI( "Pin Display" );
2107
2108 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers,
2110 groupPinDisplay );
2111 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames,
2113 groupPinDisplay );
2114 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Place Pin Names Inside" ),
2117 groupPinDisplay );
2118 propMgr.AddProperty( new PROPERTY<SYMBOL, int>( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset,
2120 groupPinDisplay );
2121
2122 const wxString groupAttributes = _HKI( "Attributes" );
2123
2124 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Simulation" ),
2127 groupAttributes );
2128 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude from Board" ), &SYMBOL::SetExcludedFromBoard,
2130 groupAttributes );
2131 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Exclude from Bill of Materials" ),
2134 groupAttributes );
2135
2136 const wxString groupUnits = _HKI( "Units and Body Styles" );
2137
2138 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, int>( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp,
2140 groupUnits );
2141 propMgr.AddProperty( new PROPERTY<LIB_SYMBOL, bool>( _HKI( "Units are Interchangeable" ),
2144 groupUnits );
2145
2146 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
2147 {
2148 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2149 return symbol->IsMultiBodyStyle();
2150
2151 return false;
2152 };
2153
2156 groupUnits )
2157 .SetAvailableFunc( multiBodyStyle )
2159 []( INSPECTABLE* aItem )
2160 {
2161 wxPGChoices choices;
2162
2163 if( LIB_SYMBOL* symbol = dynamic_cast<LIB_SYMBOL*>( aItem ) )
2164 {
2165 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
2166 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
2167 }
2168
2169 return choices;
2170 } );
2171 }
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:402
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:399
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
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:511
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:754
int m_bodyStyle
Definition sch_item.h:755
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:702
friend class LIB_SYMBOL
Definition sch_item.h:773
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:256
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:63
bool m_showPinNumbers
Definition symbol.h:245
void SetExcludedFromBoard(bool aExcludeFromBoard) override
Set or clear exclude from board netlist flag.
Definition symbol.h:207
SYMBOL(KICAD_T idType)
Definition symbol.h:65
bool m_excludedFromSim
Definition symbol.h:247
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
Definition symbol.h:213
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition symbol.h:171
bool m_showPinNames
Definition symbol.h:244
int GetPinNameOffset() const
Definition symbol.h:160
virtual void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition symbol.h:165
bool GetExcludedFromBoard() const override
Definition symbol.h:208
bool m_excludedFromBOM
Definition symbol.h:248
virtual 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