KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <sch_collectors.h>
26#include <sch_commit.h>
27#include <sch_edit_frame.h>
28#include <widgets/msgpanel.h>
29#include <bitmaps.h>
30#include <core/mirror.h>
31#include <sch_shape.h>
32#include <pgm_base.h>
33#include <sim/sim_model.h>
34#include <sim/spice_generator.h>
35#include <sim/sim_lib_mgr.h>
36#include <trace_helpers.h>
37#include <trigo.h>
38#include <refdes_utils.h>
39#include <wx/log.h>
41#include <sch_plotter.h>
42#include <string_utils.h>
44#include <sch_rule_area.h>
45
46#include <utility>
47#include <validators.h>
48
49
50std::unordered_map<TRANSFORM, int> SCH_SYMBOL::s_transformToOrientationCache;
51
52
57std::string toUTFTildaText( const wxString& txt )
58{
59 std::string ret = TO_UTF8( txt );
60
61 for( char& c : ret )
62 {
63 if( (unsigned char) c <= ' ' )
64 c = '~';
65 }
66
67 return ret;
68}
69
70
72 SYMBOL( nullptr, SCH_SYMBOL_T )
73{
74 Init( VECTOR2I( 0, 0 ) );
75}
76
77
78SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId,
79 const SCH_SHEET_PATH* aSheet, int aUnit, int aBodyStyle,
80 const VECTOR2I& aPosition, EDA_ITEM* aParent ) :
81 SYMBOL( aParent, SCH_SYMBOL_T )
82{
83 Init( aPosition );
84
85 m_unit = aUnit;
86 m_bodyStyle = aBodyStyle;
87 m_lib_id = aLibId;
88
89 std::unique_ptr< LIB_SYMBOL > part;
90
91 part = aSymbol.Flatten();
92 part->SetParent();
93 SetLibSymbol( part.release() );
94
95 // Copy fields from the library symbol
96 UpdateFields( aSheet,
97 true, /* update style */
98 false, /* update ref */
99 false, /* update other fields */
100 true, /* reset ref */
101 true /* reset other fields */ );
102
103 m_prefix = UTIL::GetRefDesPrefix( m_part->GetReferenceField().GetText() );
104
105 if( aSheet )
107
108 // Inherit the include in bill of materials and board netlist settings from flattened
109 // library symbol.
110 m_excludedFromSim = m_part->GetExcludedFromSim();
111 m_excludedFromBOM = m_part->GetExcludedFromBOM();
112 m_excludedFromBoard = m_part->GetExcludedFromBoard();
113}
114
115
116SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet,
117 const PICKED_SYMBOL& aSel, const VECTOR2I& aPosition, EDA_ITEM* aParent ) :
118 SCH_SYMBOL( aSymbol, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, aPosition, aParent )
119{
120 // Set any fields that were modified as part of the symbol selection
121 for( const auto& [fieldId, fieldValue] : aSel.Fields )
122 {
123 if( fieldId == FIELD_T::REFERENCE )
124 SetRef( aSheet, fieldValue );
125 else if( SCH_FIELD* field = GetField( fieldId ) )
126 field->SetText( fieldValue );
127 }
128}
129
130
132 SYMBOL( aSymbol )
133{
134 m_parent = aSymbol.m_parent;
135 m_pos = aSymbol.m_pos;
136 m_unit = aSymbol.m_unit;
137 m_bodyStyle = aSymbol.m_bodyStyle;
138 m_lib_id = aSymbol.m_lib_id;
140 m_DNP = aSymbol.m_DNP;
141
142 const_cast<KIID&>( m_Uuid ) = aSymbol.m_Uuid;
143
144 m_transform = aSymbol.m_transform;
145 m_prefix = aSymbol.m_prefix;
147 m_fields = aSymbol.m_fields;
148
149 // Re-parent the fields, which before this had aSymbol as parent
150 for( SCH_FIELD& field : m_fields )
151 field.SetParent( this );
152
153 m_pins.clear();
154
155 // Copy (and re-parent) the pins
156 for( const std::unique_ptr<SCH_PIN>& pin : aSymbol.m_pins )
157 {
158 m_pins.emplace_back( std::make_unique<SCH_PIN>( *pin ) );
159 m_pins.back()->SetParent( this );
160 }
161
162 if( aSymbol.m_part )
163 SetLibSymbol( new LIB_SYMBOL( *aSymbol.m_part ) );
164
167}
168
169
173
174
175void SCH_SYMBOL::Init( const VECTOR2I& pos )
176{
178 m_pos = pos;
179 m_unit = 1; // In multi unit chip - which unit to draw.
180 m_bodyStyle = BODY_STYLE::BASE; // De Morgan Handling
181
182 // The rotation/mirror transformation matrix. pos normal
184
185 auto addField =
186 [&]( FIELD_T id, SCH_LAYER_ID layer )
187 {
188 m_fields.emplace_back( this, id, GetCanonicalFieldName( id ) );
189 m_fields.back().SetTextPos( pos );
190 m_fields.back().SetLayer( layer );
191 };
192
193 // construct only the mandatory fields
195 addField( FIELD_T::VALUE, LAYER_VALUEPART );
196 addField( FIELD_T::FOOTPRINT, LAYER_FIELDS );
197 addField( FIELD_T::DATASHEET, LAYER_FIELDS );
199
200 m_prefix = wxString( wxT( "U" ) );
201 m_isInNetlist = true;
202}
203
204
206{
207 return new SCH_SYMBOL( *this );
208}
209
210
212{
213 return m_part == nullptr;
214}
215
216
218{
219 // If a symbol's anchor is not grid-aligned to its pins then moving from the anchor is
220 // going to end up moving the symbol's pins off-grid.
221
222 // The minimal grid size allowed to place a pin is 25 mils
223 const int min_grid_size = schIUScale.MilsToIU( 25 );
224
225 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
226 {
227 if( ( ( pin->GetPosition().x - m_pos.x ) % min_grid_size ) != 0 )
228 return false;
229
230 if( ( ( pin->GetPosition().y - m_pos.y ) % min_grid_size ) != 0 )
231 return false;
232 }
233
234 return true;
235}
236
237
238void SCH_SYMBOL::SetLibId( const LIB_ID& aLibId )
239{
240 m_lib_id = aLibId;
241}
242
243
245{
246 if( !m_schLibSymbolName.IsEmpty() )
247 return m_schLibSymbolName;
248 else
249 return m_lib_id.Format();
250}
251
252
254{
255 wxCHECK2( !aLibSymbol || aLibSymbol->IsRoot(), aLibSymbol = nullptr );
256
257 m_part.reset( aLibSymbol );
258
259 // We've just reset the library symbol, so the lib_pins, which were just
260 // pointers to the old symbol, need to be cleared.
261 for( auto& pin : m_pins )
262 pin->SetLibPin( nullptr );
263
264 UpdatePins();
265}
266
267
269{
270 if( m_part )
271 return m_part->GetDescription();
272
273 return wxEmptyString;
274}
275
276
278{
279 if( m_part )
280 return m_part->GetKeyWords();
281
282 return wxEmptyString;
283}
284
285
287{
288 if( m_part )
289 return m_part->GetDatasheetField().GetText();
290
291 return wxEmptyString;
292}
293
294
296{
297 std::map<wxString, wxString> altPinMap;
298 std::map<wxString, SCH_PIN::ALT> altPinDefs;
299 std::map<wxString, std::set<SCH_PIN*>> pinUuidMap;
300 std::set<SCH_PIN*> unassignedSchPins;
301 std::set<SCH_PIN*> unassignedLibPins;
302
303 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
304 {
305 pinUuidMap[ pin->GetNumber() ].insert( pin.get() );
306
307 unassignedSchPins.insert( pin.get() );
308
309 if( !pin->GetAlt().IsEmpty() )
310 {
311 altPinMap[ pin->GetNumber() ] = pin->GetAlt();
312 auto altDefIt = pin->GetAlternates().find( pin->GetAlt() );
313
314 if( altDefIt != pin->GetAlternates().end() )
315 altPinDefs[ pin->GetNumber() ] = altDefIt->second;
316 }
317
318 pin->SetLibPin( nullptr );
319 }
320
321 m_pinMap.clear();
322
323 if( !m_part )
324 return;
325
326 for( SCH_PIN* libPin : m_part->GetPins() )
327 {
328 // NW: Don't filter by unit: this data-structure is used for all instances,
329 // some of which might have different units.
330 if( libPin->GetBodyStyle() && m_bodyStyle && m_bodyStyle != libPin->GetBodyStyle() )
331 continue;
332
333 SCH_PIN* pin = nullptr;
334
335 auto ii = pinUuidMap.find( libPin->GetNumber() );
336
337 if( ii == pinUuidMap.end() || ii->second.empty() )
338 {
339 unassignedLibPins.insert( libPin );
340 continue;
341 }
342
343 auto it = ii->second.begin();
344 pin = *it;
345 ii->second.erase( it );
346 pin->GetAlternates() = libPin->GetAlternates();
347 pin->SetLibPin( libPin );
348 pin->SetPosition( libPin->GetPosition() );
349 pin->SetUnit( libPin->GetUnit() );
350 pin->SetBodyStyle( libPin->GetBodyStyle() );
351
352 unassignedSchPins.erase( pin );
353
354 auto iii = altPinMap.find( libPin->GetNumber() );
355
356 if( iii != altPinMap.end() )
357 {
358 wxString altName = iii->second;
359
360 if( pin->GetAlternates().find( altName ) == pin->GetAlternates().end() )
361 {
362 auto defIt = altPinDefs.find( libPin->GetNumber() );
363
364 if( defIt != altPinDefs.end() )
365 {
366 for( const auto& [ name, alt ] : pin->GetAlternates() )
367 {
368 if( alt.m_Shape == defIt->second.m_Shape && alt.m_Type == defIt->second.m_Type )
369 {
370 altName = name;
371 break;
372 }
373 }
374 }
375 }
376
377 pin->SetAlt( altName );
378 }
379
380 m_pinMap[ libPin ] = pin;
381 }
382
383 // Add any pins that were not found in the symbol
384 for( SCH_PIN* libPin : unassignedLibPins )
385 {
386 SCH_PIN* pin = nullptr;
387
388 // First try to re-use an existing pin
389 if( !unassignedSchPins.empty() )
390 {
391 auto it = unassignedSchPins.begin();
392 pin = *it;
393 unassignedSchPins.erase( it );
394 }
395 else
396 {
397 // This is a pin that was not found in the symbol, so create a new one.
398 pin = m_pins.emplace_back( std::make_unique<SCH_PIN>( SCH_PIN( this, libPin ) ) ).get();
399 }
400
401 m_pinMap[ libPin ] = pin;
402 pin->GetAlternates() = libPin->GetAlternates();
403 pin->SetLibPin( libPin );
404 pin->SetPosition( libPin->GetPosition() );
405 pin->SetUnit( libPin->GetUnit() );
406 pin->SetBodyStyle( libPin->GetBodyStyle() );
407 pin->SetNumber( libPin->GetNumber() );
408
409 auto iii = altPinMap.find( libPin->GetNumber() );
410
411 if( iii != altPinMap.end() )
412 {
413 wxString altName = iii->second;
414
415 if( pin->GetAlternates().find( altName ) == pin->GetAlternates().end() )
416 {
417 auto defIt = altPinDefs.find( libPin->GetNumber() );
418
419 if( defIt != altPinDefs.end() )
420 {
421 for( const auto& [ name, alt ] : pin->GetAlternates() )
422 {
423 if( alt.m_Shape == defIt->second.m_Shape && alt.m_Type == defIt->second.m_Type )
424 {
425 altName = name;
426 break;
427 }
428 }
429 }
430 }
431
432 pin->SetAlt( altName );
433 }
434 }
435
436 // If we have any pins left in the symbol that were not found in the library, remove them.
437 for( auto it1 = m_pins.begin(); it1 != m_pins.end() && !unassignedSchPins.empty(); )
438 {
439 auto it2 = unassignedSchPins.find( it1->get() );
440
441 if( it2 != unassignedSchPins.end() )
442 {
443 it1 = m_pins.erase( it1 );
444 unassignedSchPins.erase( it2 );
445 }
446 else
447 {
448 ++it1;
449 }
450 }
451
452 // If the symbol is selected, then its pins are selected.
453 if( IsSelected() )
454 {
455 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
456 pin->SetSelected();
457 }
458
459}
460
461
462void SCH_SYMBOL::SetBodyStyle( int aBodyStyle )
463{
464 if( aBodyStyle != m_bodyStyle )
465 {
466 m_bodyStyle = aBodyStyle;
467
468 // The body style may have a different pin layout so the update the pin map.
469 UpdatePins();
470 }
471}
472
473
475{
476 if( m_part )
477 return m_part->GetUnitCount();
478
479 return 0;
480}
481
482
484{
485 if( m_part )
486 return m_part->GetBodyStyleCount();
487
488 return 0;
489}
490
491
493{
494 if( m_part )
495 return m_part->HasDeMorganBodyStyles();
496
497 return false;
498}
499
500
501wxString SCH_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
502{
503 if( m_part )
504 return m_part->GetUnitDisplayName( aUnit, aLabel );
505 else if( aLabel )
506 return wxString::Format( _( "Unit %s" ), SubReference( aUnit ) );
507 else
508 return SubReference( aUnit );
509}
510
511
512wxString SCH_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
513{
514 if( m_part )
515 return m_part->GetBodyStyleDescription( aBodyStyle, aLabel );
516 else
517 return wxT( "?" );
518}
519
520
521bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
522 bool aTestFromEnd ) const
523{
524 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
525 {
526 if( !aTestFromEnd )
527 {
528 if( instance.m_Path == aSheetPath )
529 {
530 aInstance = instance;
531 return true;
532 }
533 }
534 else if( instance.m_Path.EndsWith( aSheetPath ) )
535 {
536 aInstance = instance;
537 return true;
538 }
539 }
540
541 return false;
542}
543
544
545void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
546{
547 RemoveInstance( aInstancePath.Path() );
548}
549
550
551void SCH_SYMBOL::RemoveInstance( const KIID_PATH& aInstancePath )
552{
553 // Search for an existing path and remove it if found
554 // (search from back to avoid invalidating iterator on remove)
555 for( int ii = m_instanceReferences.size() - 1; ii >= 0; --ii )
556 {
557 if( m_instanceReferences[ii].m_Path == aInstancePath )
558 {
559 wxLogTrace( traceSchSheetPaths, wxS( "Removing symbol instance:\n"
560 " sheet path %s\n"
561 " reference %s, unit %d from symbol %s." ),
562 aInstancePath.AsString(),
563 m_instanceReferences[ii].m_Reference,
564 m_instanceReferences[ii].m_Unit,
565 m_Uuid.AsString() );
566
567 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
568 }
569 }
570}
571
572
573void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef, int aUnit )
574{
575 SCH_SYMBOL_INSTANCE instance;
576 instance.m_Path = aPath;
577 instance.m_Reference = aRef;
578 instance.m_Unit = aUnit;
579
580 AddHierarchicalReference( instance );
581}
582
583
585{
586 RemoveInstance( aInstance.m_Path );
587
588 SCH_SYMBOL_INSTANCE instance = aInstance;
589
590 wxLogTrace( traceSchSheetPaths, wxS( "Adding symbol '%s' instance:\n"
591 " sheet path '%s'\n"
592 " reference '%s'\n"
593 " unit %d\n" ),
594 m_Uuid.AsString(),
595 instance.m_Path.AsString(),
596 instance.m_Reference,
597 instance.m_Unit );
598
599 m_instanceReferences.push_back( instance );
600
601 // This should set the default instance to the first saved instance data for each symbol
602 // when importing sheets.
603 if( m_instanceReferences.size() == 1 )
604 {
606 m_unit = instance.m_Unit;
607 }
608}
609
610
611const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
612{
613 KIID_PATH path = sheet->Path();
614 wxString ref;
615 wxString subRef;
616
617 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
618 {
619 if( instance.m_Path == path )
620 {
621 ref = instance.m_Reference;
622 subRef = SubReference( instance.m_Unit );
623 break;
624 }
625 }
626
627 // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
628 // use this as a default for this path. This will happen if we load a version 1 schematic
629 // file. It will also mean that multiple instances of the same sheet by default all have
630 // the same symbol references, but perhaps this is best.
631 if( ref.IsEmpty() && !GetField( FIELD_T::REFERENCE )->GetText().IsEmpty() )
633
634 if( ref.IsEmpty() )
636
637 if( aIncludeUnit && GetUnitCount() > 1 )
638 ref += subRef;
639
640 return ref;
641}
642
643
644void SCH_SYMBOL::SetRefProp( const wxString& aRef )
645{
647
648 if( validator.DoValidate( aRef, nullptr ) )
649 SetRef( &Schematic()->CurrentSheet(), aRef );
650}
651
652
653void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
654{
655 KIID_PATH path = sheet->Path();
656 bool found = false;
657
658 // check to see if it is already there before inserting it
660 {
661 if( instance.m_Path == path )
662 {
663 found = true;
664 instance.m_Reference = ref;
665 break;
666 }
667 }
668
669 if( !found )
671
672 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
673 pin->ClearDefaultNetName( sheet );
674
675 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
677
678 // Reinit the m_prefix member if needed
680
681 if( m_prefix.IsEmpty() )
682 m_prefix = wxT( "U" );
683
684 // Power symbols have references starting with # and are not included in netlists
685 m_isInNetlist = ! ref.StartsWith( wxT( "#" ) );
686}
687
688
689bool SCH_SYMBOL::IsAnnotated( const SCH_SHEET_PATH* aSheet ) const
690{
691 KIID_PATH path = aSheet->Path();
692
693 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
694 {
695 if( instance.m_Path == path )
696 return !instance.m_Reference.IsEmpty() && instance.m_Reference.Last() != '?';
697 }
698
699 return false;
700}
701
702
704{
705 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
706
707 refDesignator.Replace( "~", " " );
708
709 wxString prefix = refDesignator;
710
711 while( prefix.Length() )
712 {
713 wxUniCharRef last = prefix.Last();
714
715 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
716 prefix.RemoveLast();
717 else
718 break;
719 }
720
721 // Avoid a prefix containing trailing/leading spaces
722 prefix.Trim( true );
723 prefix.Trim( false );
724
725 if( !prefix.IsEmpty() )
726 SetPrefix( prefix );
727}
728
729
730wxString SCH_SYMBOL::SubReference( int aUnit, bool aAddSeparator ) const
731{
732 if( SCHEMATIC* schematic = Schematic() )
733 return schematic->Settings().SubReference( aUnit, aAddSeparator );
734
735 return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
736}
737
738
740{
741 KIID_PATH path = aSheet->Path();
742
743 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
744 {
745 if( instance.m_Path == path )
746 return instance.m_Unit;
747 }
748
749 // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
750 // version 1 schematic file.
751 return m_unit;
752}
753
754
755void SCH_SYMBOL::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
756{
757 KIID_PATH path = aSheet->Path();
758
759 // check to see if it is already there before inserting it
761 {
762 if( instance.m_Path == path )
763 {
764 instance.m_Unit = aUnitSelection;
765 return;
766 }
767 }
768
769 // didn't find it; better add it
771}
772
773
774void SCH_SYMBOL::SetDNP(bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
775{
776 if( !aInstance || aVariantName.IsEmpty() )
777 {
778 m_DNP = aEnable;
779 return;
780 }
781
782 SCH_SYMBOL_INSTANCE instance;
783
784 wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), /* void */,
785 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
786 aInstance->PathHumanReadable() ) );
787
788 if( aVariantName.IsEmpty() )
789 {
790 instance.m_DNP = aEnable;
791 }
792 else
793 {
794 if( instance.m_Variants.contains( aVariantName ) )
795 {
796 instance.m_Variants[aVariantName].m_DNP = aEnable;
797 }
798 else
799 {
800 SCH_SYMBOL_VARIANT variant( aVariantName );
801
802 variant.InitializeAttributes( *this );
803 variant.m_DNP = aEnable;
804 AddVariant( *aInstance, variant );
805 }
806 }
807}
808
809
810bool SCH_SYMBOL::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
811{
812 if( !aInstance || aVariantName.IsEmpty() )
813 return m_DNP;
814
815 SCH_SYMBOL_INSTANCE instance;
816
817 wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), m_DNP,
818 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
819 aInstance->PathHumanReadable() ) );
820
821 if( aVariantName.IsEmpty() )
822 {
823 return instance.m_DNP;
824 }
825 else
826 {
827 wxCHECK_MSG( instance.m_Variants.contains( aVariantName ), false,
828 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s' for variant '%s'." ),
829 aInstance->PathHumanReadable(), aVariantName ) );
830
831 return instance.m_Variants[aVariantName].m_DNP;
832 }
833}
834
835
836void SCH_SYMBOL::SetDNP( bool aEnable, const SCH_SHEET_PATH& aInstance, const std::vector<wxString>& aVariantNames )
837{
838 for( const wxString& variantName : aVariantNames )
839 SetDNP( aEnable, &aInstance, variantName );
840}
841
842
843void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance,
844 const wxString& aVariantName )
845{
846 if( !aInstance || aVariantName.IsEmpty() )
847 {
848 m_excludedFromBOM = aEnable;
849 return;
850 }
851
852 SCH_SYMBOL_INSTANCE instance;
853
854 wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), /* void */,
855 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
856 aInstance->PathHumanReadable() ) );
857
858 if( aVariantName.IsEmpty() )
859 {
860 instance.m_ExcludedFromBOM = aEnable;
861 }
862 else
863 {
864 if( instance.m_Variants.contains( aVariantName ) )
865 {
866 instance.m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
867 }
868 else
869 {
870 SCH_SYMBOL_VARIANT variant( aVariantName );
871
872 variant.InitializeAttributes( *this );
873 variant.m_ExcludedFromBOM = aEnable;
874 AddVariant( *aInstance, variant );
875 }
876 }
877}
878
879
880bool SCH_SYMBOL::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
881{
882 if( !aInstance || aVariantName.IsEmpty() )
883 return m_excludedFromBOM;
884
885 SCH_SYMBOL_INSTANCE instance;
886
887 wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), m_excludedFromBOM,
888 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
889 aInstance->PathHumanReadable() ) );
890
891 if( aVariantName.IsEmpty() )
892 {
893 return instance.m_ExcludedFromBOM;
894 }
895 else
896 {
897 wxCHECK_MSG( instance.m_Variants.contains( aVariantName ), false,
898 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s' variant '%s'." ),
899 aInstance->PathHumanReadable(), aVariantName ) );
900
901 return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
902 }
903}
904
905
906void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH& aInstance,
907 const std::vector<wxString>& aVariantNames )
908{
909 for( const wxString& variantName : aVariantNames )
910 SetExcludedFromBOM( aEnable, &aInstance, variantName );
911}
912
913
914void SCH_SYMBOL::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
915{
916 if( !aInstance || aVariantName.IsEmpty() )
917 {
918 m_excludedFromSim = aEnable;
919 return;
920 }
921
922 SCH_SYMBOL_INSTANCE instance;
923
924 wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), /* void */,
925 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
926 aInstance->PathHumanReadable() ) );
927
928 if( aVariantName.IsEmpty() )
929 {
930 instance.m_ExcludedFromSim = aEnable;
931 }
932 else
933 {
934 if( instance.m_Variants.contains( aVariantName ) )
935 {
936 instance.m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
937 }
938 else
939 {
940 SCH_SYMBOL_VARIANT variant( aVariantName );
941
942 variant.InitializeAttributes( *this );
943 variant.m_ExcludedFromSim = aEnable;
944 AddVariant( *aInstance, variant );
945 }
946 }
947}
948
949
950bool SCH_SYMBOL::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
951{
952 if( !aInstance || aVariantName.IsEmpty() )
953 return m_excludedFromSim;
954
955 SCH_SYMBOL_INSTANCE instance;
956
957 wxCHECK_MSG( GetInstance( instance, aInstance->Path() ), m_excludedFromSim,
958 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
959 aInstance->PathHumanReadable() ) );
960
961 if( aVariantName.IsEmpty() )
962 {
963 return instance.m_ExcludedFromSim;
964 }
965 else
966 {
967 wxCHECK_MSG( instance.m_Variants.contains( aVariantName ), false,
968 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s' variant '%s'." ),
969 aInstance->PathHumanReadable(), aVariantName ) );
970
971 return instance.m_Variants[aVariantName].m_ExcludedFromSim;
972 }
973}
974
975
976void SCH_SYMBOL::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH& aInstance,
977 const std::vector<wxString>& aVariantNames )
978{
979 for( const wxString& variantName : aVariantNames )
980 SetExcludedFromSim( aEnable, &aInstance, variantName );
981}
982
983
984void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
985{
987 instance.m_Unit = aUnitSelection;
988}
989
990
991const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aPath,
992 bool aAllowExtraText ) const
993{
994 if( aResolve )
995 return GetField( FIELD_T::VALUE )->GetShownText( aPath, aAllowExtraText );
996
997 return GetField( FIELD_T::VALUE )->GetText();
998}
999
1000
1001void SCH_SYMBOL::SetValueFieldText( const wxString& aValue )
1002{
1003 GetField( FIELD_T::VALUE )->SetText( aValue );
1004}
1005
1006
1007const wxString SCH_SYMBOL::GetFootprintFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
1008 bool aAllowExtraText ) const
1009{
1010 if( aResolve )
1011 return GetField( FIELD_T::FOOTPRINT )->GetShownText( aPath, aAllowExtraText );
1012
1013 return GetField( FIELD_T::FOOTPRINT )->GetText();
1014}
1015
1016
1017void SCH_SYMBOL::SetFootprintFieldText( const wxString& aFootprint )
1018{
1019 GetField( FIELD_T::FOOTPRINT )->SetText( aFootprint );
1020}
1021
1022
1024{
1025 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
1026 return field;
1027
1028 m_fields.emplace_back( this, aFieldType );
1029 return &m_fields.back();
1030}
1031
1032
1033const SCH_FIELD* SCH_SYMBOL::GetField( FIELD_T aFieldType ) const
1034{
1035 return FindField( m_fields, aFieldType );
1036}
1037
1038
1039SCH_FIELD* SCH_SYMBOL::GetField( const wxString& aFieldName )
1040{
1041 return FindField( m_fields, aFieldName );
1042}
1043
1044
1045const SCH_FIELD* SCH_SYMBOL::GetField( const wxString& aFieldName ) const
1046{
1047 return FindField( m_fields, aFieldName );
1048}
1049
1050
1051void SCH_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly ) const
1052{
1053 for( const SCH_FIELD& field : m_fields )
1054 {
1055 if( aVisibleOnly )
1056 {
1057 if( !field.IsVisible() || field.GetText().IsEmpty() )
1058 continue;
1059 }
1060
1061 aVector.push_back( const_cast<SCH_FIELD*>( &field ) );
1062 }
1063
1064 std::sort( aVector.begin(), aVector.end(),
1065 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1066 {
1067 return lhs->GetOrdinal() < rhs->GetOrdinal();
1068 } );
1069}
1070
1071
1073{
1074 return NextFieldOrdinal( m_fields );
1075}
1076
1077
1079{
1080 m_fields.push_back( aField );
1081 return &m_fields.back();
1082}
1083
1084
1085void SCH_SYMBOL::RemoveField( const wxString& aFieldName )
1086{
1087 for( unsigned ii = 0; ii < m_fields.size(); ++ii )
1088 {
1089 if( m_fields[ii].IsMandatory() )
1090 continue;
1091
1092 if( aFieldName == m_fields[ii].GetName( false ) )
1093 {
1094 m_fields.erase( m_fields.begin() + ii );
1095 return;
1096 }
1097 }
1098}
1099
1100
1102{
1103 for( SCH_FIELD& field : m_fields )
1104 {
1105 if( field.GetName().IsSameAs( aFieldName, false ) )
1106 return &field;
1107 }
1108
1109 return nullptr;
1110}
1111
1112
1113void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef,
1114 bool aUpdateOtherFields, bool aResetRef, bool aResetOtherFields )
1115{
1116 if( m_part )
1117 {
1118 std::vector<SCH_FIELD*> fields;
1119 m_part->GetFields( fields );
1120
1121 for( const SCH_FIELD* libField : fields )
1122 {
1123 SCH_FIELD* schField;
1124 FIELD_T fieldType = FIELD_T::USER;
1125
1126 if( libField->IsMandatory() )
1127 {
1128 fieldType = libField->GetId();
1129 schField = GetField( fieldType );
1130 }
1131 else
1132 {
1133 schField = GetField( libField->GetCanonicalName() );
1134
1135 if( !schField )
1136 {
1137 schField = AddField( SCH_FIELD( this, FIELD_T::USER, libField->GetCanonicalName() ) );
1138 schField->ImportValues( *libField );
1139 schField->SetTextPos( m_pos + libField->GetTextPos() );
1140 }
1141 }
1142
1143 schField->SetPrivate( libField->IsPrivate() );
1144
1145 if( aUpdateStyle )
1146 {
1147 schField->ImportValues( *libField );
1148 schField->SetTextPos( m_pos + libField->GetTextPos() );
1149 }
1150
1151 if( fieldType == FIELD_T::REFERENCE && aPath )
1152 {
1153 if( aResetRef )
1154 SetRef( aPath, m_part->GetField( FIELD_T::REFERENCE )->GetText() );
1155 else if( aUpdateRef )
1156 SetRef( aPath, libField->GetText() );
1157 }
1158 else if( fieldType == FIELD_T::VALUE )
1159 {
1160 SetValueFieldText( UnescapeString( libField->GetText() ) );
1161 }
1162 else if( fieldType == FIELD_T::DATASHEET )
1163 {
1164 if( aResetOtherFields )
1165 schField->SetText( GetDatasheet() ); // alias-specific value
1166 else if( aUpdateOtherFields )
1167 schField->SetText( libField->GetText() );
1168 }
1169 else
1170 {
1171 if( aResetOtherFields || aUpdateOtherFields )
1172 schField->SetText( libField->GetText() );
1173 }
1174 }
1175 }
1176}
1177
1178
1179void SCH_SYMBOL::SyncOtherUnits( const SCH_SHEET_PATH& aSourceSheet, SCH_COMMIT& aCommit,
1180 PROPERTY_BASE* aProperty )
1181{
1182 bool updateValue = true;
1183 bool updateExclFromBOM = true;
1184 bool updateExclFromBoard = true;
1185 bool updateDNP = true;
1186 bool updateOtherFields = true;
1187 bool updatePins = true;
1188
1189 if( aProperty )
1190 {
1191 updateValue = aProperty->Name() == _HKI( "Value" );
1192 updateExclFromBoard = aProperty->Name() == _HKI( "Exclude From Board" );
1193 updateExclFromBOM = aProperty->Name() == _HKI( "Exclude From Bill of Materials" );
1194 updateDNP = aProperty->Name() == _HKI( "Do not Populate" );
1195 updateOtherFields = false;
1196 updatePins = false;
1197 }
1198
1199 if( !updateValue
1200 && !updateExclFromBOM
1201 && !updateExclFromBoard
1202 && !updateDNP
1203 && !updateOtherFields
1204 && !updatePins )
1205 {
1206 return;
1207 }
1208
1209 // Keep fields other than the reference, include/exclude flags, and alternate pin assignments
1210 // in sync in multi-unit parts.
1211 if( GetUnitCount() > 1 && IsAnnotated( &aSourceSheet ) )
1212 {
1213 wxString ref = GetRef( &aSourceSheet );
1214
1215 for( SCH_SHEET_PATH& sheet : Schematic()->Hierarchy() )
1216 {
1217 SCH_SCREEN* screen = sheet.LastScreen();
1218 std::vector<SCH_SYMBOL*> otherUnits;
1219
1220 CollectOtherUnits( ref, m_unit, m_lib_id, sheet, &otherUnits );
1221
1222 for( SCH_SYMBOL* otherUnit : otherUnits )
1223 {
1224 aCommit.Modify( otherUnit, screen );
1225
1226 if( updateValue )
1227 otherUnit->SetValueFieldText( GetField( FIELD_T::VALUE )->GetText() );
1228
1229 if( updateOtherFields )
1230 {
1231 for( SCH_FIELD& field : m_fields )
1232 {
1233 if( field.GetId() == FIELD_T::REFERENCE || field.GetId() == FIELD_T::VALUE )
1234 {
1235 // already handled
1236 continue;
1237 }
1238
1239 SCH_FIELD* otherField;
1240
1241 if( field.IsMandatory() )
1242 otherField = otherUnit->GetField( field.GetId() );
1243 else
1244 otherField = otherUnit->GetField( field.GetName() );
1245
1246 if( otherField )
1247 {
1248 otherField->SetText( field.GetText() );
1249 }
1250 else
1251 {
1252 SCH_FIELD newField( field );
1253 const_cast<KIID&>( newField.m_Uuid ) = KIID();
1254
1255 newField.Offset( -GetPosition() );
1256 newField.Offset( otherUnit->GetPosition() );
1257
1258 newField.SetParent( otherUnit );
1259 otherUnit->AddField( newField );
1260 }
1261 }
1262
1263 for( int ii = (int) otherUnit->GetFields().size() - 1; ii >= 0; ii-- )
1264 {
1265 SCH_FIELD& otherField = otherUnit->GetFields()[ii];
1266
1267 if( !otherField.IsMandatory() && !GetField( otherField.GetName() ) )
1268 otherUnit->GetFields().erase( otherUnit->GetFields().begin() + ii );
1269 }
1270 }
1271
1272 if( updateExclFromBOM )
1273 otherUnit->SetExcludedFromBOM( m_excludedFromBOM );
1274
1275 if( updateExclFromBoard )
1276 otherUnit->SetExcludedFromBoard( m_excludedFromBoard );
1277
1278 if( updateDNP )
1279 otherUnit->SetDNP( GetDNP( &aSourceSheet ), &sheet );
1280
1281 if( updatePins )
1282 {
1283 for( const std::unique_ptr<SCH_PIN>& model_pin : m_pins )
1284 {
1285 SCH_PIN* src_pin = otherUnit->GetPin( model_pin->GetNumber() );
1286
1287 if( src_pin )
1288 src_pin->SetAlt( model_pin->GetAlt() );
1289 }
1290 }
1291 }
1292 }
1293 }
1294}
1295
1296
1297void SCH_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1298{
1299 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1300 aFunction( pin.get() );
1301
1302 for( SCH_FIELD& field : m_fields )
1303 aFunction( &field );
1304}
1305
1306
1307SCH_PIN* SCH_SYMBOL::GetPin( const wxString& aNumber ) const
1308{
1309 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1310 {
1311 if( pin->GetNumber() == aNumber )
1312 return pin.get();
1313 }
1314
1315 return nullptr;
1316}
1317
1318
1319const SCH_PIN* SCH_SYMBOL::GetPin( const VECTOR2I& aPos ) const
1320{
1321 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1322 {
1323 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
1324 : GetUnit();
1325 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
1326 : GetBodyStyle();
1327
1328 if( pin_unit > 0 && pin_unit != GetUnit() )
1329 continue;
1330
1331 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
1332 continue;
1333
1334 if( pin->GetPosition() == aPos )
1335 return pin.get();
1336 }
1337
1338 return nullptr;
1339}
1340
1341
1342std::vector<SCH_PIN*> SCH_SYMBOL::GetLibPins() const
1343{
1344 if( m_part )
1345 return m_part->GetGraphicalPins( m_unit, m_bodyStyle );
1346
1347 return std::vector<SCH_PIN*>();
1348}
1349
1350
1351std::vector<SCH_PIN*> SCH_SYMBOL::GetAllLibPins() const
1352{
1353 if( m_part )
1354 return m_part->GetPins();
1355
1356 return std::vector<SCH_PIN*>();
1357}
1358
1359
1361{
1362 return m_part ? m_part->GetPinCount() : 0;
1363}
1364
1365
1367{
1368 auto it = m_pinMap.find( aLibPin );
1369
1370 if( it != m_pinMap.end() )
1371 return it->second;
1372
1373 wxFAIL_MSG_AT( "Pin not found", __FILE__, __LINE__, __FUNCTION__ );
1374 return nullptr;
1375}
1376
1377
1378std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
1379{
1380 std::vector<SCH_PIN*> pins;
1381 int unit = m_unit;
1382
1383 if( !aSheet && Schematic() )
1384 aSheet = &Schematic()->CurrentSheet();
1385
1386 if( aSheet )
1387 unit = GetUnitSelection( aSheet );
1388
1389 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1390 {
1391 if( unit && pin->GetUnit() && pin->GetUnit() != unit )
1392 continue;
1393
1394 pins.push_back( pin.get() );
1395 }
1396
1397 return pins;
1398}
1399
1400
1401std::vector<SCH_PIN*> SCH_SYMBOL::GetPins() const
1402{
1403 return GetPins( nullptr );
1404}
1405
1406
1408{
1409 wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T,
1410 wxT( "Cannot swap data with invalid symbol." ) );
1411
1412 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
1413
1414 std::swap( m_lib_id, symbol->m_lib_id );
1415
1416 m_pins.swap( symbol->m_pins ); // std::vector's swap()
1417
1418 for( std::unique_ptr<SCH_PIN>& pin : symbol->m_pins )
1419 pin->SetParent( symbol );
1420
1421 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1422 pin->SetParent( this );
1423
1424 LIB_SYMBOL* libSymbol = symbol->m_part.release();
1425 symbol->m_part = std::move( m_part );
1426 symbol->UpdatePins();
1427 m_part.reset( libSymbol );
1428 UpdatePins();
1429
1430 std::swap( m_pos, symbol->m_pos );
1431 std::swap( m_unit, symbol->m_unit );
1432 std::swap( m_bodyStyle, symbol->m_bodyStyle );
1433
1434 m_fields.swap( symbol->m_fields ); // std::vector's swap()
1435
1436 for( SCH_FIELD& field : symbol->m_fields )
1437 field.SetParent( symbol );
1438
1439 for( SCH_FIELD& field : m_fields )
1440 field.SetParent( this );
1441
1442 TRANSFORM tmp = m_transform;
1443
1444 m_transform = symbol->m_transform;
1445 symbol->m_transform = tmp;
1446
1447 std::swap( m_excludedFromSim, symbol->m_excludedFromSim );
1448 std::swap( m_excludedFromBOM, symbol->m_excludedFromBOM );
1449 std::swap( m_DNP, symbol->m_DNP );
1450 std::swap( m_excludedFromBoard, symbol->m_excludedFromBoard );
1451
1452 std::swap( m_instanceReferences, symbol->m_instanceReferences );
1453 std::swap( m_schLibSymbolName, symbol->m_schLibSymbolName );
1454}
1455
1456
1457void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
1458{
1459 for( const SCH_FIELD& field : m_fields )
1460 {
1461 if( field.IsPrivate() )
1462 continue;
1463
1464 if( field.IsMandatory() )
1465 aVars->push_back( field.GetCanonicalName().Upper() );
1466 else
1467 aVars->push_back( field.GetName() );
1468 }
1469
1470 aVars->push_back( wxT( "OP" ) );
1471 aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
1472 aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
1473 aVars->push_back( wxT( "UNIT" ) );
1474 aVars->push_back( wxT( "SHORT_REFERENCE" ) );
1475 aVars->push_back( wxT( "SYMBOL_LIBRARY" ) );
1476 aVars->push_back( wxT( "SYMBOL_NAME" ) );
1477 aVars->push_back( wxT( "SYMBOL_DESCRIPTION" ) );
1478 aVars->push_back( wxT( "SYMBOL_KEYWORDS" ) );
1479 aVars->push_back( wxT( "EXCLUDE_FROM_BOM" ) );
1480 aVars->push_back( wxT( "EXCLUDE_FROM_BOARD" ) );
1481 aVars->push_back( wxT( "EXCLUDE_FROM_SIM" ) );
1482 aVars->push_back( wxT( "DNP" ) );
1483 aVars->push_back( wxT( "SHORT_NET_NAME(<pin_number>)" ) );
1484 aVars->push_back( wxT( "NET_NAME(<pin_number>)" ) );
1485 aVars->push_back( wxT( "NET_CLASS(<pin_number>)" ) );
1486 aVars->push_back( wxT( "PIN_NAME(<pin_number>)" ) );
1487}
1488
1489
1490bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
1491{
1492 static wxRegEx operatingPoint( wxT( "^"
1493 "OP"
1494 "(:[^.]*)?" // pin
1495 "(.([0-9])?" // precisionStr
1496 "([a-zA-Z]*))?" // rangeStr
1497 "$" ) );
1498
1499 wxCHECK( aPath, false );
1500
1501 SCHEMATIC* schematic = Schematic();
1502
1503 if( !schematic )
1504 return false;
1505
1506 if( operatingPoint.Matches( *token ) )
1507 {
1508 wxString pin( operatingPoint.GetMatch( *token, 1 ).Lower() );
1509 wxString precisionStr( operatingPoint.GetMatch( *token, 3 ) );
1510 wxString rangeStr( operatingPoint.GetMatch( *token, 4 ) );
1511
1512 int precision = precisionStr.IsEmpty() ? 3 : precisionStr[0] - '0';
1513 wxString range = rangeStr.IsEmpty() ? wxString( wxS( "~A" ) ) : rangeStr;
1514
1515 SIM_LIB_MGR simLibMgr( &schematic->Project() );
1516
1517 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1518 embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() );
1519
1520 if( m_part )
1521 embeddedFilesStack.push_back( m_part->GetEmbeddedFiles() );
1522
1523 simLibMgr.SetFilesStack( std::move( embeddedFilesStack ) );
1524
1525 NULL_REPORTER devnull;
1526 SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast<SCH_SYMBOL&>( *this ),
1527 true, aDepth + 1, devnull ).model;
1528 SPICE_ITEM spiceItem;
1529 spiceItem.refName = GetRef( aPath );
1530
1531 wxString spiceRef = model.SpiceGenerator().ItemName( spiceItem );
1532 spiceRef = spiceRef.Lower();
1533
1534 if( pin.IsEmpty() )
1535 {
1536 *token = schematic->GetOperatingPoint( spiceRef, precision, range );
1537 return true;
1538 }
1539 else if( pin == wxS( ":power" ) )
1540 {
1541 if( rangeStr.IsEmpty() )
1542 range = wxS( "~W" );
1543
1544 *token = schematic->GetOperatingPoint( spiceRef + wxS( ":power" ), precision, range );
1545 return true;
1546 }
1547 else
1548 {
1549 pin = pin.SubString( 1, -1 ); // Strip ':' from front
1550
1551 for( const std::reference_wrapper<const SIM_MODEL_PIN>& modelPin : model.GetPins() )
1552 {
1553 SCH_PIN* symbolPin = GetPin( modelPin.get().symbolPinNumber );
1554
1555 if( pin == symbolPin->GetName().Lower() || pin == symbolPin->GetNumber().Lower() )
1556 {
1557 if( model.GetPins().size() == 2 )
1558 {
1559 *token = schematic->GetOperatingPoint( spiceRef, precision, range );
1560 }
1561 else
1562 {
1563 wxString signalName = spiceRef + wxS( ":" ) + modelPin.get().modelPinName;
1564 *token = schematic->GetOperatingPoint( signalName, precision, range );
1565 }
1566
1567 return true;
1568 }
1569 }
1570 }
1571
1572 *token = wxS( "?" );
1573 return true;
1574 }
1575
1576 if( token->Contains( ':' ) )
1577 {
1578 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
1579 return true;
1580 }
1581
1582 for( const SCH_FIELD& field : m_fields )
1583 {
1584 wxString fieldName = field.IsMandatory() ? field.GetCanonicalName()
1585 : field.GetName();
1586
1587 wxString textToken = field.GetText();
1588 textToken.Replace( " ", wxEmptyString );
1589 wxString tokenString = "${" + fieldName + "}";
1590
1591 // If the field data is just a reference to the field, don't resolve
1592 if( textToken.IsSameAs( tokenString, false ) )
1593 return true;
1594
1595 if( token->IsSameAs( fieldName, false ) )
1596 {
1597 if( field.GetId() == FIELD_T::REFERENCE )
1598 *token = GetRef( aPath, true );
1599 else
1600 *token = field.GetShownText( aPath, false, aDepth + 1 );
1601
1602 return true;
1603 }
1604 }
1605
1606 // Consider missing simulation fields as empty, not un-resolved
1607 if( token->IsSameAs( wxT( "SIM.DEVICE" ) )
1608 || token->IsSameAs( wxT( "SIM.TYPE" ) )
1609 || token->IsSameAs( wxT( "SIM.PINS" ) )
1610 || token->IsSameAs( wxT( "SIM.PARAMS" ) )
1611 || token->IsSameAs( wxT( "SIM.LIBRARY" ) )
1612 || token->IsSameAs( wxT( "SIM.NAME" ) ) )
1613 {
1614 *token = wxEmptyString;
1615 return true;
1616 }
1617
1618 for( const TEMPLATE_FIELDNAME& templateFieldname :
1620 {
1621 if( token->IsSameAs( templateFieldname.m_Name )
1622 || token->IsSameAs( templateFieldname.m_Name.Upper() ) )
1623 {
1624 // If we didn't find it in the fields list then it isn't set on this symbol.
1625 // Just return an empty string.
1626 *token = wxEmptyString;
1627 return true;
1628 }
1629 }
1630
1631 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
1632 {
1633 wxString footprint = GetFootprintFieldText( true, aPath, false );
1634
1635 wxArrayString parts = wxSplit( footprint, ':' );
1636
1637 if( parts.Count() > 0 )
1638 *token = parts[ 0 ];
1639 else
1640 *token = wxEmptyString;
1641
1642 return true;
1643 }
1644 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
1645 {
1646 wxString footprint = GetFootprintFieldText( true, aPath, false );
1647
1648 wxArrayString parts = wxSplit( footprint, ':' );
1649
1650 if( parts.Count() > 1 )
1651 *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
1652 else
1653 *token = wxEmptyString;
1654
1655 return true;
1656 }
1657 else if( token->IsSameAs( wxT( "UNIT" ) ) )
1658 {
1659 *token = SubReference( GetUnitSelection( aPath ) );
1660 return true;
1661 }
1662 else if( token->IsSameAs( wxT( "SHORT_REFERENCE" ) ) )
1663 {
1664 *token = GetRef( aPath, false );
1665 return true;
1666 }
1667 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
1668 {
1669 *token = m_lib_id.GetUniStringLibNickname();
1670 return true;
1671 }
1672 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
1673 {
1674 *token = m_lib_id.GetUniStringLibItemName();
1675 return true;
1676 }
1677 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
1678 {
1679 *token = GetDescription();
1680 return true;
1681 }
1682 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
1683 {
1684 *token = GetKeyWords();
1685 return true;
1686 }
1687 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
1688 {
1689 *token = wxEmptyString;
1690
1691 if( aPath->GetExcludedFromBOM() || this->ResolveExcludedFromBOM() )
1692 *token = _( "Excluded from BOM" );
1693
1694 return true;
1695 }
1696 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
1697 {
1698 *token = wxEmptyString;
1699
1700 if( aPath->GetExcludedFromBoard() || this->ResolveExcludedFromBoard() )
1701 *token = _( "Excluded from board" );
1702
1703 return true;
1704 }
1705 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
1706 {
1707 *token = wxEmptyString;
1708
1709 if( aPath->GetExcludedFromSim() || this->ResolveExcludedFromSim() )
1710 *token = _( "Excluded from simulation" );
1711
1712 return true;
1713 }
1714 else if( token->IsSameAs( wxT( "DNP" ) ) )
1715 {
1716 *token = wxEmptyString;
1717
1718 if( aPath->GetDNP() || this->ResolveDNP() )
1719 *token = _( "DNP" );
1720
1721 return true;
1722 }
1723 else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) )
1724 || token->StartsWith( wxT( "NET_NAME(" ) )
1725 || token->StartsWith( wxT( "NET_CLASS(" ) )
1726 || token->StartsWith( wxT( "PIN_NAME(" ) ) )
1727 {
1728 wxString pinNumber = token->AfterFirst( '(' );
1729 pinNumber = pinNumber.BeforeLast( ')' );
1730
1731 for( SCH_PIN* pin : GetPins( aPath ) )
1732 {
1733 if( pin->GetNumber() == pinNumber )
1734 {
1735 if( token->StartsWith( wxT( "PIN_NAME" ) ) )
1736 {
1737 *token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
1738 return true;
1739 }
1740
1741 SCH_CONNECTION* conn = pin->Connection( aPath );
1742
1743 if( !conn )
1744 *token = wxEmptyString;
1745 else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
1746 *token = conn->LocalName();
1747 else if( token->StartsWith( wxT( "NET_NAME" ) ) )
1748 *token = conn->Name();
1749 else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
1750 *token = pin->GetEffectiveNetClass( aPath )->GetName();
1751
1752 return true;
1753 }
1754 }
1755 }
1756
1757 // See if parent can resolve it (this will recurse to ancestors)
1758 if( aPath->Last() && aPath->Last()->ResolveTextVar( aPath, token, aDepth + 1 ) )
1759 return true;
1760
1761 return false;
1762}
1763
1764
1765void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1766{
1767 if( aSheetPath )
1768 {
1769 KIID_PATH path = aSheetPath->Path();
1770
1771 for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1772 {
1773 if( instance.m_Path == path )
1774 {
1775 if( instance.m_Reference.IsEmpty() || aResetPrefix )
1776 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1777 else
1778 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1779 }
1780 }
1781 }
1782 else
1783 {
1784 for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1785 {
1786 if( instance.m_Reference.IsEmpty() || aResetPrefix)
1787 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1788 else
1789 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1790 }
1791 }
1792
1793 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1794 pin->ClearDefaultNetName( aSheetPath );
1795
1796 // These 2 changes do not work in complex hierarchy.
1797 // When a clear annotation is made, the calling function must call a
1798 // UpdateAllScreenReferences for the active sheet.
1799 // But this call cannot made here.
1800 wxString currentReference = GetField( FIELD_T::REFERENCE )->GetText();
1801
1802 if( currentReference.IsEmpty() || aResetPrefix )
1804 else
1806}
1807
1808
1810{
1811 // An empty sheet path is illegal, at a minimum the root sheet UUID must be present.
1812 wxCHECK( aSheetPath.size() > 0, false );
1813
1814 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1815 {
1816 // if aSheetPath is found, nothing to do:
1817 if( instance.m_Path == aSheetPath )
1818 return false;
1819 }
1820
1821 // This entry does not exist: add it, with its last-used reference
1822 AddHierarchicalReference( aSheetPath, GetField( FIELD_T::REFERENCE )->GetText(), m_unit );
1823 return true;
1824}
1825
1826
1827void SCH_SYMBOL::SetOrientation( int aOrientation )
1828{
1829 TRANSFORM temp = TRANSFORM();
1830 bool transform = false;
1831
1832 switch( aOrientation )
1833 {
1834 case SYM_ORIENT_0:
1835 case SYM_NORMAL: // default transform matrix
1837 break;
1838
1839 case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
1840 temp.x1 = 0;
1841 temp.y1 = 1;
1842 temp.x2 = -1;
1843 temp.y2 = 0;
1844 transform = true;
1845 break;
1846
1847 case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1848 temp.x1 = 0;
1849 temp.y1 = -1;
1850 temp.x2 = 1;
1851 temp.y2 = 0;
1852 transform = true;
1853 break;
1854
1855 case SYM_MIRROR_Y: // Mirror Y (incremental transform)
1856 temp.x1 = -1;
1857 temp.y1 = 0;
1858 temp.x2 = 0;
1859 temp.y2 = 1;
1860 transform = true;
1861 break;
1862
1863 case SYM_MIRROR_X: // Mirror X (incremental transform)
1864 temp.x1 = 1;
1865 temp.y1 = 0;
1866 temp.x2 = 0;
1867 temp.y2 = -1;
1868 transform = true;
1869 break;
1870
1871 case SYM_ORIENT_90:
1874 break;
1875
1876 case SYM_ORIENT_180:
1880 break;
1881
1882 case SYM_ORIENT_270:
1885 break;
1886
1887 case ( SYM_ORIENT_0 + SYM_MIRROR_X ):
1890 break;
1891
1892 case ( SYM_ORIENT_0 + SYM_MIRROR_Y ):
1895 break;
1896
1901 break;
1902
1903 case ( SYM_ORIENT_90 + SYM_MIRROR_X ):
1906 break;
1907
1908 case ( SYM_ORIENT_90 + SYM_MIRROR_Y ):
1911 break;
1912
1917 break;
1918
1919 case ( SYM_ORIENT_180 + SYM_MIRROR_X ):
1922 break;
1923
1924 case ( SYM_ORIENT_180 + SYM_MIRROR_Y ):
1927 break;
1928
1933 break;
1934
1935 case ( SYM_ORIENT_270 + SYM_MIRROR_X ):
1938 break;
1939
1940 case ( SYM_ORIENT_270 + SYM_MIRROR_Y ):
1943 break;
1944
1949 break;
1950
1951 default:
1952 transform = false;
1953 wxFAIL_MSG( "Invalid schematic symbol orientation type." );
1954 break;
1955 }
1956
1957 if( transform )
1958 {
1959 /* The new matrix transform is the old matrix transform modified by the
1960 * requested transformation, which is the temp transform (rot,
1961 * mirror ..) in order to have (in term of matrix transform):
1962 * transform coord = new_m_transform * coord
1963 * where transform coord is the coord modified by new_m_transform from
1964 * the initial value coord.
1965 * new_m_transform is computed (from old_m_transform and temp) to
1966 * have:
1967 * transform coord = old_m_transform * temp
1968 */
1969 TRANSFORM newTransform;
1970
1971 newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1972 newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1973 newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1974 newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1975 m_transform = newTransform;
1976 }
1977}
1978
1979
1981{
1982 /*
1983 * This is slow, but also a bizarre algorithm. I don't feel like unteasing the algorithm right
1984 * now, so let's just cache it for the moment.
1985 */
1988
1989 int rotate_values[] =
1990 {
2003 };
2004
2005 // Try to find the current transform option:
2006 TRANSFORM transform = m_transform;
2007 SCH_SYMBOL temp( *this );
2008 temp.SetParentGroup( nullptr );
2009
2010 for( int type_rotate : rotate_values )
2011 {
2012 temp.SetOrientation( type_rotate );
2013
2014 if( transform == temp.GetTransform() )
2015 {
2017 return type_rotate;
2018 }
2019 }
2020
2021 // Error: orientation not found in list (should not happen)
2022 wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
2023
2024 return SYM_NORMAL;
2025}
2026
2027
2028#if defined(DEBUG)
2029
2030void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const
2031{
2032 // for now, make it look like XML:
2033 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
2034 << " ref=\"" << TO_UTF8( GetField( FIELD_T::REFERENCE )->GetName() )
2035 << '"' << " chipName=\""
2036 << GetLibId().Format().wx_str() << '"' << m_pos
2037 << " layer=\"" << m_layer
2038 << '"' << ">\n";
2039
2040 // skip the reference, it's been output already.
2041 for( int i = 1; i < (int) GetFields().size(); ++i )
2042 {
2043 const wxString& value = GetFields()[i].GetText();
2044
2045 if( !value.IsEmpty() )
2046 {
2047 NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
2048 << TO_UTF8( GetFields()[i].GetName() )
2049 << '"' << " value=\""
2050 << TO_UTF8( value ) << "\"/>\n";
2051 }
2052 }
2053
2054 NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
2055}
2056
2057#endif
2058
2059
2060BOX2I SCH_SYMBOL::doGetBoundingBox( bool aIncludePins, bool aIncludeFields ) const
2061{
2062 BOX2I bBox;
2063
2064 if( m_part )
2065 bBox = m_part->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, false );
2066 else
2068 false );
2069
2070 bBox = m_transform.TransformCoordinate( bBox );
2071 bBox.Normalize();
2072
2073 bBox.Offset( m_pos );
2074
2075 if( aIncludeFields )
2076 {
2077 for( const SCH_FIELD& field : m_fields )
2078 {
2079 if( field.IsVisible() )
2080 bBox.Merge( field.GetBoundingBox() );
2081 }
2082 }
2083
2084 return bBox;
2085}
2086
2087
2089{
2090 try
2091 {
2092 return doGetBoundingBox( false, false );
2093 }
2094 catch( const boost::bad_pointer& e )
2095 {
2096 wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ), e.what() ) );
2097 return BOX2I();
2098 }
2099}
2100
2101
2103{
2104 return doGetBoundingBox( true, false );
2105}
2106
2107
2109{
2110 return doGetBoundingBox( true, true );
2111}
2112
2113
2114void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2115{
2116 wxString msg;
2117
2118 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
2119 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
2120
2121 auto addExcludes =
2122 [&]()
2123 {
2124 wxArrayString msgs;
2125
2126 if( GetExcludedFromSim() )
2127 msgs.Add( _( "Simulation" ) );
2128
2129 if( GetExcludedFromBOM() )
2130 msgs.Add( _( "BOM" ) );
2131
2132 if( GetExcludedFromBoard() )
2133 msgs.Add( _( "Board" ) );
2134
2135 if( GetDNP( currentSheet ) )
2136 msgs.Add( _( "DNP" ) );
2137
2138 msg = wxJoin( msgs, '|' );
2139 msg.Replace( '|', wxS( ", " ) );
2140
2141 if( !msg.empty() )
2142 aList.emplace_back( _( "Exclude from" ), msg );
2143 };
2144
2145 // part and alias can differ if alias is not the root
2146 if( m_part )
2147 {
2148 if( m_part.get() != LIB_SYMBOL::GetDummy() )
2149 {
2150 if( m_part->IsPower() )
2151 {
2152 // Don't use GetShownText(); we want to see the variable references here
2153 aList.emplace_back( _( "Power symbol" ),
2154 KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) );
2155 }
2156 else
2157 {
2158 aList.emplace_back( _( "Reference" ),
2159 UnescapeString( GetRef( currentSheet ) ) );
2160
2161 // Don't use GetShownText(); we want to see the variable references here
2162 aList.emplace_back( _( "Value" ),
2163 KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) );
2164 addExcludes();
2165 aList.emplace_back( _( "Name" ),
2167 GetLibId().GetLibItemName() ) );
2168 }
2169
2170#if 0 // Display symbol flags, for debug only
2171 aList.emplace_back( _( "flags" ), wxString::Format( "%X", GetEditFlags() ) );
2172#endif
2173
2174 if( !m_part->IsRoot() )
2175 {
2176 msg = _( "Missing parent" );
2177
2178 std::shared_ptr< LIB_SYMBOL > parent = m_part->GetParent().lock();
2179
2180 if( parent )
2181 msg = parent->GetName();
2182
2183 aList.emplace_back( _( "Derived from" ), UnescapeString( msg ) );
2184 }
2185 else if( !m_lib_id.GetLibNickname().empty() )
2186 {
2187 aList.emplace_back( _( "Library" ), m_lib_id.GetLibNickname() );
2188 }
2189 else
2190 {
2191 aList.emplace_back( _( "Library" ), _( "Undefined!!!" ) );
2192 }
2193
2194 // Display the current associated footprint, if exists.
2195 // Don't use GetShownText(); we want to see the variable references here
2196 msg = KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::FOOTPRINT )->GetText() );
2197
2198 if( msg.IsEmpty() )
2199 msg = _( "<Unknown>" );
2200
2201 aList.emplace_back( _( "Footprint" ), msg );
2202
2203 // Display description of the symbol, and keywords found in lib
2204 aList.emplace_back( _( "Description" ) + wxT( ": " )
2205 + GetField( FIELD_T::DESCRIPTION )->GetText(),
2206 _( "Keywords" ) + wxT( ": " ) + m_part->GetKeyWords() );
2207 }
2208 }
2209 else
2210 {
2211 aList.emplace_back( _( "Reference" ), GetRef( currentSheet ) );
2212
2213 // Don't use GetShownText(); we want to see the variable references here
2214 aList.emplace_back( _( "Value" ),
2215 KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) );
2216 addExcludes();
2217 aList.emplace_back( _( "Name" ),
2218 KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) );
2219
2220 wxString libNickname = GetLibId().GetLibNickname();
2221
2222 if( libNickname.empty() )
2223 msg = _( "No library defined!" );
2224 else
2225 msg.Printf( _( "Symbol not found in %s!" ), libNickname );
2226
2227 aList.emplace_back( _( "Library" ), msg );
2228 }
2229}
2230
2231
2236
2237
2239{
2240 std::unique_ptr<LIB_SYMBOL>& libSymbolRef = GetLibSymbolRef();
2241
2242 if( !libSymbolRef )
2243 return nullptr;
2244
2246}
2247
2248
2250{
2251 int dx = m_pos.x;
2252
2254 MIRROR( m_pos.x, aCenter );
2255 dx -= m_pos.x; // dx,0 is the move vector for this transform
2256
2257 for( SCH_FIELD& field : m_fields )
2258 {
2259 // Move the fields to the new position because the symbol itself has moved.
2260 VECTOR2I pos = field.GetTextPos();
2261 pos.x -= dx;
2262 field.SetTextPos( pos );
2263 }
2264}
2265
2266
2268{
2269 int dy = m_pos.y;
2270
2272 MIRROR( m_pos.y, aCenter );
2273 dy -= m_pos.y; // 0,dy is the move vector for this transform
2274
2275 for( SCH_FIELD& field : m_fields )
2276 {
2277 // Move the fields to the new position because the symbol itself has moved.
2278 VECTOR2I pos = field.GetTextPos();
2279 pos.y -= dy;
2280 field.SetTextPos( pos );
2281 }
2282}
2283
2284
2285void SCH_SYMBOL::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
2286{
2287 VECTOR2I prev = m_pos;
2288
2289 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
2290
2292
2293 for( SCH_FIELD& field : m_fields )
2294 {
2295 // Move the fields to the new position because the symbol itself has moved.
2296 VECTOR2I pos = field.GetTextPos();
2297 pos.x -= prev.x - m_pos.x;
2298 pos.y -= prev.y - m_pos.y;
2299 field.SetTextPos( pos );
2300 }
2301}
2302
2303
2304bool SCH_SYMBOL::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
2305{
2306 if( aSearchData.searchMetadata )
2307 {
2308 if( EDA_ITEM::Matches( GetSchSymbolLibraryName(), aSearchData ) )
2309 return true;
2310
2311 if( EDA_ITEM::Matches( GetDescription(), aSearchData ) )
2312 return true;
2313
2314 if( EDA_ITEM::Matches( GetKeyWords(), aSearchData ) )
2315 return true;
2316 }
2317
2318 for( SCH_ITEM& drawItem : GetLibSymbolRef()->GetDrawItems() )
2319 {
2320 if( drawItem.Matches( aSearchData, aAuxData ) )
2321 return true;
2322 }
2323
2324 // Symbols are searchable via the child field and pin item text.
2325 return false;
2326}
2327
2328
2329void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
2330{
2331 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2332 {
2333 SCH_PIN* lib_pin = pin->GetLibPin();
2334
2335 if( lib_pin && lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
2336 continue;
2337
2338 DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
2339 aItemList.push_back( item );
2340 }
2341}
2342
2343
2344bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
2345 std::vector<DANGLING_END_ITEM>& aItemListByPos,
2346 const SCH_SHEET_PATH* aPath )
2347{
2348 bool changed = false;
2349
2350 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2351 {
2352 bool previousState = pin->IsDangling();
2353 pin->SetIsDangling( true );
2354
2355 VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
2356
2357 auto lower = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, pos );
2358 bool do_break = false;
2359
2360 for( auto it = lower; it < aItemListByPos.end() && it->GetPosition() == pos; it++ )
2361 {
2362 DANGLING_END_ITEM& each_item = *it;
2363
2364 // Some people like to stack pins on top of each other in a symbol to indicate
2365 // internal connection. While technically connected, it is not particularly useful
2366 // to display them that way, so skip any pins that are in the same symbol as this
2367 // one.
2368 if( each_item.GetParent() == this )
2369 continue;
2370
2371 switch( each_item.GetType() )
2372 {
2373 case PIN_END:
2374 case LABEL_END:
2375 case SHEET_LABEL_END:
2376 case WIRE_END:
2377 case NO_CONNECT_END:
2378 case JUNCTION_END:
2379 pin->SetIsDangling( false );
2380 do_break = true;
2381 break;
2382
2383 default:
2384 break;
2385 }
2386
2387 if( do_break )
2388 break;
2389 }
2390
2391 changed = ( changed || ( previousState != pin->IsDangling() ) );
2392 }
2393
2394 return changed;
2395}
2396
2397
2399{
2400 if( ( aPin == nullptr ) || ( aPin->Type() != SCH_PIN_T ) )
2401 return VECTOR2I( 0, 0 );
2402
2403 return m_transform.TransformCoordinate( aPin->GetPosition() ) + m_pos;
2404}
2405
2406
2408 const SCH_SHEET_PATH* aInstance ) const
2409{
2410 // Do not compare to ourself.
2411 if( aItem == this )
2412 return false;
2413
2414 const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( aItem );
2415
2416 // Don't compare against a different SCH_ITEM.
2417 wxCHECK( symbol, false );
2418
2419 // The move algorithm marks any pins that are being moved without something attached
2420 // (during the move) as dangling. We always need to recheck connectivity in this case
2421 // or we will not notice changes when the user places the symbol back in the same position
2422 // it started.
2423 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2424 {
2425 if( pin->IsDangling() )
2426 return true;
2427 }
2428
2429 if( GetPosition() != symbol->GetPosition() )
2430 return true;
2431
2432 if( GetLibId() != symbol->GetLibId() )
2433 return true;
2434
2435 if( GetUnitSelection( aInstance ) != symbol->GetUnitSelection( aInstance ) )
2436 return true;
2437
2438 if( GetRef( aInstance ) != symbol->GetRef( aInstance ) )
2439 return true;
2440
2441 // Power symbol value field changes are connectivity changes.
2442 if( IsPower()
2443 && ( GetValue( true, aInstance, false ) != symbol->GetValue( true, aInstance, false ) ) )
2444 return true;
2445
2446 if( m_pins.size() != symbol->m_pins.size() )
2447 return true;
2448
2449 for( size_t i = 0; i < m_pins.size(); i++ )
2450 {
2451 if( m_pins[i]->HasConnectivityChanges( symbol->m_pins[i].get() ) )
2452 return true;
2453 }
2454
2455 return false;
2456}
2457
2458
2459std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
2460{
2461 std::vector<VECTOR2I> retval;
2462
2463 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2464 {
2465 // Collect only pins attached to the current unit and convert.
2466 // others are not associated to this symbol instance
2467 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2468 : GetUnit();
2469 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2470 : GetBodyStyle();
2471
2472 if( pin_unit > 0 && pin_unit != GetUnit() )
2473 continue;
2474
2475 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2476 continue;
2477
2478 retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos );
2479 }
2480
2481 return retval;
2482}
2483
2484
2486{
2487 if( m_part )
2488 {
2489 // Calculate the position relative to the symbol.
2490 VECTOR2I libPosition = aPosition - m_pos;
2491
2492 return m_part->LocateDrawItem( m_unit, m_bodyStyle, aType, libPosition, m_transform );
2493 }
2494
2495 return nullptr;
2496}
2497
2498
2499wxString SCH_SYMBOL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2500{
2501 return wxString::Format( _( "Symbol %s [%s]" ),
2503 KIUI::EllipsizeMenuText( GetLibId().GetLibItemName() ) );
2504}
2505
2506
2507INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData,
2508 const std::vector<KICAD_T>& aScanTypes )
2509{
2510 for( KICAD_T scanType : aScanTypes )
2511 {
2512 if( scanType == SCH_LOCATE_ANY_T || ( scanType == SCH_SYMBOL_T )
2513 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
2514 {
2515 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
2516 return INSPECT_RESULT::QUIT;
2517 }
2518
2519 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
2520 {
2521 for( SCH_FIELD& field : m_fields )
2522 {
2523 if( INSPECT_RESULT::QUIT == aInspector( &field, (void*) this ) )
2524 return INSPECT_RESULT::QUIT;
2525 }
2526 }
2527
2528 if( scanType == SCH_FIELD_LOCATE_REFERENCE_T )
2529 {
2530 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::REFERENCE ), (void*) this ) )
2531 return INSPECT_RESULT::QUIT;
2532 }
2533
2534 if( scanType == SCH_FIELD_LOCATE_VALUE_T
2535 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
2536 {
2537 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::VALUE ), (void*) this ) )
2538 return INSPECT_RESULT::QUIT;
2539 }
2540
2541 if( scanType == SCH_FIELD_LOCATE_FOOTPRINT_T )
2542 {
2543 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::FOOTPRINT ), (void*) this ) )
2544 return INSPECT_RESULT::QUIT;
2545 }
2546
2547 if( scanType == SCH_FIELD_LOCATE_DATASHEET_T )
2548 {
2549 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::DATASHEET ), (void*) this ) )
2550 return INSPECT_RESULT::QUIT;
2551 }
2552
2553 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_PIN_T )
2554 {
2555 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2556 {
2557 // Collect only pins attached to the current unit and convert.
2558 // others are not associated to this symbol instance
2559 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2560 : GetUnit();
2561 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2562 : GetBodyStyle();
2563
2564 if( pin_unit > 0 && pin_unit != GetUnit() )
2565 continue;
2566
2567 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2568 continue;
2569
2570 if( INSPECT_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
2571 return INSPECT_RESULT::QUIT;
2572 }
2573 }
2574 }
2575
2577}
2578
2579
2580bool SCH_SYMBOL::operator <( const SCH_ITEM& aItem ) const
2581{
2582 if( Type() != aItem.Type() )
2583 return Type() < aItem.Type();
2584
2585 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( &aItem );
2586
2588
2589 if( rect.GetArea() != symbol->GetBodyAndPinsBoundingBox().GetArea() )
2590 return rect.GetArea() < symbol->GetBodyAndPinsBoundingBox().GetArea();
2591
2592 if( m_pos.x != symbol->m_pos.x )
2593 return m_pos.x < symbol->m_pos.x;
2594
2595 if( m_pos.y != symbol->m_pos.y )
2596 return m_pos.y < symbol->m_pos.y;
2597
2598 return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
2599}
2600
2601
2602bool SCH_SYMBOL::operator==( const SCH_SYMBOL& aSymbol ) const
2603{
2604 std::vector<SCH_FIELD*> fields, otherFields;
2605
2606 GetFields( fields, false );
2607 aSymbol.GetFields( otherFields, false );
2608
2609 if( fields.size() != otherFields.size() )
2610 return false;
2611
2612 for( int ii = 0; ii < (int) fields.size(); ii++ )
2613 {
2614 if( fields[ii]->GetId() == FIELD_T::REFERENCE )
2615 continue;
2616
2617 if( fields[ii]->GetText().Cmp( otherFields[ii]->GetText() ) != 0 )
2618 return false;
2619 }
2620
2621 return true;
2622}
2623
2624
2625bool SCH_SYMBOL::operator!=( const SCH_SYMBOL& aSymbol ) const
2626{
2627 return !( *this == aSymbol );
2628}
2629
2630
2632{
2633 wxCHECK_MSG( Type() == aSymbol.Type(), *this,
2634 wxT( "Cannot assign object type " ) + aSymbol.GetClass() + wxT( " to type " ) +
2635 GetClass() );
2636
2637 if( &aSymbol != this )
2638 {
2639 SYMBOL::operator=( aSymbol );
2640
2641 m_lib_id = aSymbol.m_lib_id;
2642 m_part.reset( aSymbol.m_part ? new LIB_SYMBOL( *aSymbol.m_part ) : nullptr );
2643 m_pos = aSymbol.m_pos;
2644 m_unit = aSymbol.m_unit;
2645 m_bodyStyle = aSymbol.m_bodyStyle;
2646 m_transform = aSymbol.m_transform;
2647
2649
2650 m_fields = aSymbol.m_fields; // std::vector's assignment operator
2651
2652 // Reparent fields after assignment to new symbol.
2653 for( SCH_FIELD& field : m_fields )
2654 field.SetParent( this );
2655
2656 UpdatePins();
2657 }
2658
2659 return *this;
2660}
2661
2662
2663bool SCH_SYMBOL::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2664{
2665 BOX2I bBox = GetBodyBoundingBox();
2666 bBox.Inflate( aAccuracy / 2 );
2667
2668 if( bBox.Contains( aPosition ) )
2669 return true;
2670
2671 return false;
2672}
2673
2674
2675bool SCH_SYMBOL::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2676{
2678 return false;
2679
2680 BOX2I rect = aRect;
2681
2682 rect.Inflate( aAccuracy / 2 );
2683
2684 if( aContained )
2685 return rect.Contains( GetBodyBoundingBox() );
2686
2687 return rect.Intersects( GetBodyBoundingBox() );
2688}
2689
2690
2691bool SCH_SYMBOL::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
2692{
2694 return false;
2695
2696 return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
2697}
2698
2699
2700bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
2701{
2702 VECTOR2I new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_pos );
2703
2704 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2705 {
2706 if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
2707 continue;
2708
2709 // Collect only pins attached to the current unit and convert.
2710 // others are not associated to this symbol instance
2711 if( pin->GetUnit() > 0 && pin->GetUnit() != GetUnit() )
2712 continue;
2713
2714 if( pin->GetBodyStyle() > 0 && pin->GetBodyStyle() != GetBodyStyle() )
2715 continue;
2716
2717 if( pin->GetLocalPosition() == new_pos )
2718 return true;
2719 }
2720
2721 return false;
2722}
2723
2724
2726{
2727 return m_isInNetlist;
2728}
2729
2730
2731void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
2732 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
2733{
2734 if( aBackground )
2735 return;
2736
2737 if( m_part )
2738 {
2739 std::vector<SCH_PIN*> libPins = m_part->GetGraphicalPins( GetUnit(), GetBodyStyle() );
2740
2741 // Copy the source so we can re-orient and translate it.
2742 LIB_SYMBOL tempSymbol( *m_part );
2743 std::vector<SCH_PIN*> tempPins = tempSymbol.GetGraphicalPins( GetUnit(), GetBodyStyle() );
2744
2745 // Copy the pin info from the symbol to the temp pins
2746 for( unsigned i = 0; i < tempPins.size(); ++ i )
2747 {
2748 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2749 SCH_PIN* tempPin = tempPins[ i ];
2750
2751 tempPin->SetName( symbolPin->GetShownName() );
2752 tempPin->SetType( symbolPin->GetType() );
2753 tempPin->SetShape( symbolPin->GetShape() );
2754
2755 if( symbolPin->IsDangling() )
2756 tempPin->SetFlags( IS_DANGLING );
2757 }
2758
2759 for( SCH_ITEM& item : tempSymbol.GetDrawItems() )
2760 {
2761 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( &item ) )
2762 {
2763 // Use SCH_FIELD's text resolver
2764 SCH_FIELD dummy( this, FIELD_T::USER );
2765 dummy.SetText( text->GetText() );
2766 text->SetText( dummy.GetShownText( false ) );
2767 }
2768 }
2769
2770 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
2771 TRANSFORM savedTransform = renderSettings->m_Transform;
2772 renderSettings->m_Transform = GetTransform();
2773 aPlotter->StartBlock( nullptr );
2774
2775 for( bool local_background : { true, false } )
2776 {
2777 tempSymbol.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(),
2778 m_pos, GetDNP() );
2779
2780 for( SCH_FIELD field : m_fields )
2781 {
2782 field.ClearRenderCache();
2783 field.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(),
2784 m_pos, GetDNP() );
2785 }
2786 }
2787
2788 if( m_DNP )
2789 PlotDNP( aPlotter );
2790
2791 SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
2792
2793 // Plot attributes to a hypertext menu
2794 if( aPlotOpts.m_PDFPropertyPopups )
2795 {
2796 std::vector<wxString> properties;
2797
2798 for( const SCH_FIELD& field : GetFields() )
2799 {
2800 wxString text_field = field.GetShownText( sheet, false);
2801
2802 if( text_field.IsEmpty() )
2803 continue;
2804
2805 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2806 field.GetName(), text_field ) );
2807 }
2808
2809 if( !m_part->GetKeyWords().IsEmpty() )
2810 {
2811 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2812 _( "Keywords" ),
2813 m_part->GetKeyWords() ) );
2814 }
2815
2816 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
2817 }
2818
2819 aPlotter->EndBlock( nullptr );
2820 renderSettings->m_Transform = savedTransform;
2821
2822 if( !m_part->IsPower() )
2823 aPlotter->Bookmark( GetBoundingBox(), GetRef( sheet ), _( "Symbols" ) );
2824 }
2825}
2826
2827
2828void SCH_SYMBOL::PlotDNP( PLOTTER* aPlotter ) const
2829{
2830 BOX2I bbox = GetBodyBoundingBox();
2832 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(),
2833 pins.GetEnd().x - bbox.GetEnd().x ),
2834 std::max( bbox.GetY() - pins.GetY(),
2835 pins.GetEnd().y - bbox.GetEnd().y ) );
2836 int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
2837
2838 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
2839 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
2840 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
2841
2842 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
2843 aPlotter->SetColor( renderSettings->GetLayerColor( LAYER_DNP_MARKER ) );
2844
2845 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, nullptr );
2846
2847 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
2848 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
2849 strokeWidth, nullptr );
2850}
2851
2852
2853void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter ) const
2854{
2855 if( m_part )
2856 {
2857 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
2858 TRANSFORM savedTransform = renderSettings->m_Transform;
2859 renderSettings->m_Transform = GetTransform();
2860
2861 std::vector<SCH_PIN*> libPins = m_part->GetGraphicalPins( GetUnit(), GetBodyStyle() );
2862
2863 // Copy the source to stay const
2864 LIB_SYMBOL tempSymbol( *m_part );
2865 std::vector<SCH_PIN*> tempPins = tempSymbol.GetGraphicalPins( GetUnit(), GetBodyStyle() );
2866 SCH_PLOT_OPTS plotOpts;
2867
2868 // Copy the pin info from the symbol to the temp pins
2869 for( unsigned i = 0; i < tempPins.size(); ++ i )
2870 {
2871 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2872 SCH_PIN* tempPin = tempPins[ i ];
2873
2874 tempPin->SetName( symbolPin->GetShownName() );
2875 tempPin->SetType( symbolPin->GetType() );
2876 tempPin->SetShape( symbolPin->GetShape() );
2877 tempPin->Plot( aPlotter, false, plotOpts, GetUnit(), GetBodyStyle(), m_pos, GetDNP() );
2878 }
2879
2880 renderSettings->m_Transform = savedTransform;
2881 }
2882}
2883
2884
2886{
2887 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2888 {
2889 if( pin->IsBrightened() )
2890 return true;
2891 }
2892
2893 return false;
2894}
2895
2896
2898{
2899 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2900 pin->ClearBrightened();
2901}
2902
2903
2904/*
2905 * When modified at the schematic level, we still store the values of these flags in the
2906 * associated m_part. If m_part now diverges from other usages, a new derived LIB_SYMBOL
2907 * will be created and stored locally in the schematic.
2908 */
2910{
2911 return m_part && m_part->GetShowPinNames();
2912}
2913
2914
2916{
2917 if( m_part )
2918 m_part->SetShowPinNames( aShow );
2919}
2920
2921
2923{
2924 return m_part && m_part->GetShowPinNumbers();
2925}
2926
2927
2929{
2930 if( m_part )
2931 m_part->SetShowPinNumbers( aShow );
2932}
2933
2934
2936{
2937 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2938 {
2939 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2940 : GetUnit();
2941 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2942 : GetBodyStyle();
2943
2944 if( pin_unit > 0 && pin_unit != GetUnit() )
2945 continue;
2946
2947 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2948 continue;
2949
2950 if( pin->IsPointClickableAnchor( aPos ) )
2951 return true;
2952 }
2953
2954 return false;
2955}
2956
2957
2959{
2960 // return true if the symbol is equivalent to a global label:
2961 // It is a Power symbol
2962 // It has only one pin type Power input
2963
2965 return false;
2966
2967 std::vector<SCH_PIN*> pin_list = GetAllLibPins();
2968
2969 if( pin_list.size() != 1 )
2970 return false;
2971
2972 return pin_list[0]->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN;
2973}
2974
2975
2977{
2978 // return true if the symbol is equivalent to a local label:
2979 // It is a Power symbol
2980 // It has only one pin type Power input
2981
2983 return false;
2984
2985 std::vector<SCH_PIN*> pin_list = GetAllLibPins();
2986
2987 if( pin_list.size() != 1 )
2988 return false;
2989
2990 return pin_list[0]->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN;
2991}
2992
2993
2995{
2996 if( !m_part )
2997 return false;
2998
2999 return m_part->IsLocalPower();
3000}
3001
3002
3004{
3005 if( !m_part )
3006 return false;
3007
3008 return m_part->IsGlobalPower();
3009}
3010
3011
3013{
3014 return IsLocalPower() || IsGlobalPower();
3015}
3016
3017
3019{
3020 wxCHECK( m_part, false );
3021
3022 return m_part->IsNormal();
3023}
3024
3025
3026std::unordered_set<wxString> SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const
3027{
3028 std::unordered_set<wxString> componentClass;
3029
3030 auto getComponentClassFields =
3031 [&]( const std::vector<SCH_FIELD>& fields )
3032 {
3033 for( const SCH_FIELD& field : fields )
3034 {
3035 if( field.GetCanonicalName() == wxT( "Component Class" ) )
3036 {
3037 if( field.GetShownText( aPath, false ) != wxEmptyString )
3038 componentClass.insert( field.GetShownText( aPath, false ) );
3039 }
3040 }
3041 };
3042
3043 // First get component classes set on the symbol itself
3044 getComponentClassFields( m_fields );
3045
3046 // Now get component classes set on any enclosing rule areas
3047 for( const SCH_RULE_AREA* ruleArea : m_rule_areas_cache )
3048 {
3049 for( const SCH_DIRECTIVE_LABEL* label : ruleArea->GetDirectives() )
3050 {
3051 getComponentClassFields( label->GetFields() );
3052 }
3053 }
3054
3055 return componentClass;
3056}
3057
3058
3059std::optional<SCH_SYMBOL_VARIANT> SCH_SYMBOL::GetVariant( const SCH_SHEET_PATH& aInstance,
3060 const wxString& aVariantName ) const
3061{
3062 SCH_SYMBOL_INSTANCE instance;
3063
3064 if( !GetInstance( instance, aInstance.Path() ) || !instance.m_Variants.contains( aVariantName ) )
3065 return std::nullopt;
3066
3067 return instance.m_Variants.find( aVariantName )->second;
3068}
3069
3070
3071void SCH_SYMBOL::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SYMBOL_VARIANT& aVariant )
3072{
3073 SCH_SYMBOL_INSTANCE instance;
3074
3075 // The instance path must already exist.
3076 if( !GetInstance( instance, aInstance.Path() ) )
3077 return;
3078
3079 instance.m_Variants.emplace( std::make_pair( aVariant.m_Name, aVariant ) );
3080}
3081
3082
3083void SCH_SYMBOL::DeleteVariant( const SCH_SHEET_PATH& aInstance, const wxString& aVariantName )
3084{
3085 SCH_SYMBOL_INSTANCE instance;
3086
3087 // The instance path must already exist.
3088 if( !GetInstance( instance, aInstance.Path() ) || !instance.m_Variants.contains( aVariantName ) )
3089 return;
3090
3091 instance.m_Variants.erase( aVariantName );
3092}
3093
3094
3095bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
3096{
3097 if( Type() != aOther.Type() )
3098 return false;
3099
3100 const SCH_SYMBOL& symbol = static_cast<const SCH_SYMBOL&>( aOther );
3101
3102 if( GetLibId() != symbol.GetLibId() )
3103 return false;
3104
3105 if( GetPosition() != symbol.GetPosition() )
3106 return false;
3107
3108 if( GetUnit() != symbol.GetUnit() )
3109 return false;
3110
3111 if( GetBodyStyle() != symbol.GetBodyStyle() )
3112 return false;
3113
3114 if( GetTransform() != symbol.GetTransform() )
3115 return false;
3116
3117 if( GetFields() != symbol.GetFields() )
3118 return false;
3119
3120 if( m_pins.size() != symbol.m_pins.size() )
3121 return false;
3122
3123 for( unsigned i = 0; i < m_pins.size(); ++i )
3124 {
3125 if( *m_pins[i] != *symbol.m_pins[i] )
3126 return false;
3127 }
3128
3129 return true;
3130}
3131
3132
3133double SCH_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
3134{
3135 if( Type() != aOther.Type() )
3136 return 0.0;
3137
3138 const SCH_SYMBOL& symbol = static_cast<const SCH_SYMBOL&>( aOther );
3139
3140 if( GetLibId() != symbol.GetLibId() )
3141 return 0.0;
3142
3143 if( GetPosition() == symbol.GetPosition() )
3144 return 1.0;
3145
3146 return 0.0;
3147}
3148
3149
3150static struct SCH_SYMBOL_DESC
3151{
3153 {
3155 .Map( SYMBOL_ANGLE_0, wxS( "0" ) )
3156 .Map( SYMBOL_ANGLE_90, wxS( "90" ) )
3157 .Map( SYMBOL_ANGLE_180, wxS( "180" ) )
3158 .Map( SYMBOL_ANGLE_270, wxS( "270" ) );
3159
3163
3164 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Position X" ),
3167 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Position Y" ),
3170
3173 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Mirror X" ),
3175 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Mirror Y" ),
3177
3178 auto hasLibPart =
3179 []( INSPECTABLE* aItem ) -> bool
3180 {
3181 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3182 return symbol->GetLibSymbolRef() != nullptr;
3183
3184 return false;
3185 };
3186
3187 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Pin numbers" ),
3189 .SetAvailableFunc( hasLibPart );
3190
3191 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Pin names" ),
3193 .SetAvailableFunc( hasLibPart );
3194
3195 const wxString groupFields = _HKI( "Fields" );
3196
3197 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Reference" ),
3199 groupFields );
3200 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Value" ),
3202 groupFields );
3203 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Library Link" ),
3205 groupFields );
3206 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Library Description" ),
3208 groupFields );
3209 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Keywords" ),
3211 groupFields );
3212
3213 auto multiUnit =
3214 [=]( INSPECTABLE* aItem ) -> bool
3215 {
3216 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3217 return symbol->IsMultiUnit();
3218
3219 return false;
3220 };
3221
3222 auto multiBodyStyle =
3223 [=]( INSPECTABLE* aItem ) -> bool
3224 {
3225 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3226 return symbol->IsMultiBodyStyle();
3227
3228 return false;
3229 };
3230
3231 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Unit" ),
3233 .SetAvailableFunc( multiUnit )
3234 .SetChoicesFunc( []( INSPECTABLE* aItem )
3235 {
3236 wxPGChoices choices;
3237
3238 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3239 {
3240 for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
3241 choices.Add( symbol->GetUnitDisplayName( ii, false ), ii );
3242 }
3243
3244 return choices;
3245 } );
3246
3247 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Body Style" ),
3249 .SetAvailableFunc( multiBodyStyle )
3250 .SetChoicesFunc( []( INSPECTABLE* aItem )
3251 {
3252 wxPGChoices choices;
3253
3254 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3255 {
3256 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
3257 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
3258 }
3259
3260 return choices;
3261 } );
3262
3263 const wxString groupAttributes = _HKI( "Attributes" );
3264
3265 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude From Board" ),
3267 groupAttributes );
3268 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Simulation" ),
3270 groupAttributes );
3271 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Bill of Materials" ),
3273 groupAttributes );
3274 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Do not Populate" ),
3276 groupAttributes );
3277 }
3279
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BITMAPS
A list of all bitmap identifiers.
@ add_component
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr const Vec GetEnd() const
Definition box2.h:212
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:146
constexpr coord_type GetY() const
Definition box2.h:208
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr coord_type GetX() const
Definition box2.h:207
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
constexpr ecoord_type GetArea() const
Return the area of the rectangle.
Definition box2.h:761
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr void Offset(coord_type dx, coord_type dy)
Definition box2.h:259
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:311
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
static std::vector< DANGLING_END_ITEM >::iterator get_lower_pos(std::vector< DANGLING_END_ITEM > &aItemListByPos, const VECTOR2I &aPos)
Definition sch_item.cpp:804
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition sch_item.h:96
DANGLING_END_T GetType() const
Definition sch_item.h:132
const EDA_ITEM * GetParent() const
Definition sch_item.h:131
The base class for create windows for drawing purpose.
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:148
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
const KIID m_Uuid
Definition eda_item.h:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:527
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:401
virtual void SetParentGroup(EDA_GROUP *aGroup)
Definition eda_item.h:115
bool IsSelected() const
Definition eda_item.h:127
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:528
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:589
void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:607
static ENUM_MAP< T > & Instance()
Definition property.h:721
A text control validator used for validating the text allowed in fields.
Definition validators.h:142
bool DoValidate(const wxString &aValue, wxWindow *aParent)
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:37
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxString AsString() const
Definition kiid.cpp:356
Definition kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
UTF8 Format() const
Definition lib_id.cpp:119
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:87
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition lib_symbol.h:207
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.
static wxString LetterSubReference(int aUnit, wxChar aInitialLetter)
static LIB_SYMBOL * GetDummy()
Returns a dummy LIB_SYMBOL, used when one is missing in the schematic.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition lib_symbol.h:690
void SetParent(LIB_SYMBOL *aParent=nullptr)
wxString GetName() const override
Definition lib_symbol.h:150
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.
const BOX2I GetBodyBoundingBox(int aUnit, int aBodyStyle, bool aIncludePins, bool aIncludePrivateItems) const
Get the symbol bounding box excluding fields.
EMBEDDED_FILES * GetEmbeddedFiles() override
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
A singleton reporter that reports to nowhere.
Definition reporter.h:216
Base plotter engine class.
Definition plotter.h:121
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition plotter.h:483
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition plotter.h:545
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:539
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:472
virtual void SetColor(const COLOR4D &color)=0
virtual void EndBlock(void *aData)
calling this function allows one to define the end of a group of drawing items for instance in SVG or...
Definition plotter.h:554
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
const wxString & Name() const
Definition property.h:220
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.
Holds all the data relating to one schematic.
Definition schematic.h:88
wxString GetOperatingPoint(const wxString &aNetName, int aPrecision, const wxString &aRange)
SCHEMATIC_SETTINGS & Settings() const
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:103
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:171
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
Schematic editor (Eeschema) main window.
SCH_SHEET_PATH & GetCurrentSheet() const
bool IsMandatory() const
void ImportValues(const SCH_FIELD &aSource)
Copy parameters from a SCH_FIELD source.
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
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
void SetPrivate(bool aPrivate)
Definition sch_item.h:252
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:244
int GetBodyStyle() const
Definition sch_item.h:247
friend class LIB_SYMBOL
Definition sch_item.h:771
int GetUnit() const
Definition sch_item.h:238
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:755
std::unordered_set< SCH_RULE_AREA * > m_rule_areas_cache
Store pointers to rule areas which this item is contained within.
Definition sch_item.h:768
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
SCH_LAYER_ID m_layer
Definition sch_item.h:751
void SetAlt(const wxString &aAlt)
Set the name of the alternate pin.
Definition sch_pin.cpp:432
void SetName(const wxString &aName)
Definition sch_pin.cpp:418
const wxString & GetName() const
Definition sch_pin.cpp:400
bool IsDangling() const override
Definition sch_pin.cpp:460
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.
Definition sch_pin.cpp:1305
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition sch_pin.h:96
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:255
wxString GetShownName() const
Definition sch_pin.cpp:576
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:332
const wxString & GetNumber() const
Definition sch_pin.h:124
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:277
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:312
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool GetExcludedFromBOM() const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
bool GetExcludedFromSim() const
bool GetExcludedFromBoard() const
bool GetDNP() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
Variant information for a schematic symbol.
void InitializeAttributes(const SCH_SYMBOL &aSymbol)
Schematic symbol object.
Definition sch_symbol.h:75
wxString GetUnitDisplayName(int aUnit, bool aLabel) const override
Return the display name for a given unit aUnit.
void SetValueProp(const wxString &aRef)
Definition sch_symbol.h:499
SCH_SYMBOL & operator=(const SCH_SYMBOL &aItem)
int GetUnitProp() const
Definition sch_symbol.h:504
size_t GetFullPinCount() const
void UpdatePrefix()
Set the prefix based on the current reference designator.
wxString m_prefix
C, R, U, Q etc - the first character(s) which typically indicate what the symbol is.
Definition sch_symbol.h:896
wxString GetDescription() const override
std::unordered_map< SCH_PIN *, SCH_PIN * > m_pinMap
Library pin pointer : SCH_PIN indices.
Definition sch_symbol.h:917
void SetMirrorX(bool aMirror)
Definition sch_symbol.h:319
bool IsSymbolLikePowerGlobalLabel() const
VECTOR2I m_pos
Definition sch_symbol.h:894
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts do.
wxString GetSymbolIDAsString() const
Definition sch_symbol.h:166
LIB_ID m_lib_id
Name and library the symbol was loaded from, i.e. 74xx:74LS00.
Definition sch_symbol.h:895
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
bool GetShowPinNumbers() const override
wxString GetDatasheet() const
Return the documentation text for the given part alias.
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void SetLibId(const LIB_ID &aName)
bool HasBrightenedPins()
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the symbol's fields.
Definition sch_symbol.h:436
BOX2I GetBodyAndPinsBoundingBox() const override
Return a bounding box for the symbol body and pins but not the fields.
wxString GetBodyStyleProp() const override
Definition sch_symbol.h:515
void SetRefProp(const wxString &aRef)
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...
virtual void SetDNP(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
SCH_ITEM * GetDrawItem(const VECTOR2I &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the symbol library item at aPosition that is part of this symbol.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void PlotDNP(PLOTTER *aPlotter) const
Plot the red 'X' over the symbol.
bool operator!=(const SCH_SYMBOL &aSymbol) const
void SetShowPinNumbers(bool aShow) override
Set or clear the pin number visibility flag.
SYMBOL_ORIENTATION_PROP GetOrientationProp() const
Definition sch_symbol.h:302
int GetY() const
Definition sch_symbol.h:814
wxString SubReference(int aUnit, bool aAddSeparator=true) const
wxString GetClass() const override
Return the class name.
Definition sch_symbol.h:114
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
bool IsAnnotated(const SCH_SHEET_PATH *aSheet) const
Check if the symbol has a valid annotation (reference) for the given sheet path.
void SetMirrorY(bool aMirror)
Definition sch_symbol.h:336
void PlotPins(PLOTTER *aPlotter) const
Plot just the symbol pins.
void SetBodyStyleProp(const wxString &aBodyStyle) override
Definition sch_symbol.h:520
void SetValueFieldText(const wxString &aValue)
int GetX() const
Definition sch_symbol.h:811
std::vector< SCH_PIN * > GetPins() const override
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
void SetExcludedFromSim(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from simulation flag.
void SetExcludedFromSimProp(bool aEnable)
Definition sch_symbol.h:713
void SetBodyStyle(int aBodyStyle) override
void SetShowPinNames(bool aShow) override
Set or clear the pin name visibility flag.
wxString GetKeyWords() const override
wxString GetSchSymbolLibraryName() const
void DeleteVariant(const SCH_SHEET_PATH &aInstance, const wxString &aVariantName)
bool IsInNetlist() const
std::optional< SCH_SYMBOL_VARIANT > GetVariant(const SCH_SHEET_PATH &aInstance, const wxString &aVariantName) const
void ClearBrightenedPins()
void SetY(int aY)
Definition sch_symbol.h:815
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
bool GetExcludedFromSimProp() const
Definition sch_symbol.h:708
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool IsGlobalPower() const override
bool GetMirrorX() const
Definition sch_symbol.h:331
wxString GetRefProp() const
Definition sch_symbol.h:487
wxString GetBodyStyleDescription(int aBodyStyle, bool aLabel) const override
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
void SetExcludedFromBOMProp(bool aEnable)
Definition sch_symbol.h:696
static std::unordered_map< TRANSFORM, int > s_transformToOrientationCache
Definition sch_symbol.h:927
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
std::vector< SCH_SYMBOL_INSTANCE > m_instanceReferences
Define the hierarchical path and reference of the symbol.
Definition sch_symbol.h:924
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const override
void SyncOtherUnits(const SCH_SHEET_PATH &aSourceSheet, SCH_COMMIT &aCommit, PROPERTY_BASE *aProperty)
Keep fields other than the reference, include/exclude flags, and alternate pin assignments in sync in...
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
Search for a SCH_FIELD with aFieldName.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
bool IsPointClickableAnchor(const VECTOR2I &aPos) const override
void UpdateFields(const SCH_SHEET_PATH *aPath, bool aUpdateStyle, bool aUpdateRef, bool aUpdateOtherFields, bool aResetRef, bool aResetOtherFields)
Restore fields to the original library values.
wxString m_schLibSymbolName
The name used to look up a symbol in the symbol library embedded in a schematic.
Definition sch_symbol.h:908
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void SetOrientationProp(SYMBOL_ORIENTATION_PROP aAngle)
Orientation/mirroring access for property manager.
Definition sch_symbol.h:293
bool GetShowPinNames() const override
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
bool HasDeMorganBodyStyles() const override
std::vector< SCH_FIELD > m_fields
Variable length list of fields.
Definition sch_symbol.h:910
std::vector< SCH_PIN * > GetAllLibPins() const
int GetBodyStyleCount() const override
Return the number of body styles of the symbol.
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
bool GetDNPProp() const
Definition sch_symbol.h:680
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void SetFootprintFieldText(const wxString &aFootprint)
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
VECTOR2I GetPosition() const override
Definition sch_symbol.h:808
std::unique_ptr< LIB_SYMBOL > m_part
A flattened copy of the LIB_SYMBOL from the PROJECT object's libraries.
Definition sch_symbol.h:912
int GetNextFieldOrdinal() const
Return the next ordinal for a user field for this symbol.
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
void Init(const VECTOR2I &pos=VECTOR2I(0, 0))
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:164
bool operator<(const SCH_ITEM &aItem) const override
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
void SetUnitProp(int aUnit)
Definition sch_symbol.h:509
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos, const SCH_SHEET_PATH *aPath=nullptr) override
Test if the symbol's dangling state has changed for all pins.
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
void AddVariant(const SCH_SHEET_PATH &aInstance, const SCH_SYMBOL_VARIANT &aVariant)
BOX2I doGetBoundingBox(bool aIncludePins, bool aIncludeFields) const
bool GetMirrorY() const
Definition sch_symbol.h:348
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
void SetDNPProp(bool aEnable)
Definition sch_symbol.h:682
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
void SetX(int aX)
Definition sch_symbol.h:812
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
bool m_isInNetlist
True if the symbol should appear in netlist.
Definition sch_symbol.h:914
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
wxString GetValueProp() const
Definition sch_symbol.h:494
bool IsLocalPower() const override
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
int GetUnitCount() const override
Return the number of units per package of the symbol.
void SetPrefix(const wxString &aPrefix)
Definition sch_symbol.h:236
int GetOrientation() const override
Get the display symbol orientation.
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.
bool IsSymbolLikePowerLocalLabel() const
bool GetExcludedFromBOMProp() const
Definition sch_symbol.h:691
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
void SetExcludedFromBOM(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from schematic bill of materials flag.
bool IsNormal() const override
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:183
std::unordered_set< wxString > GetComponentClassNames(const SCH_SHEET_PATH *aPath) const
Return the component classes this symbol belongs in.
std::vector< std::unique_ptr< SCH_PIN > > m_pins
A SCH_PIN for every #LIB_PIN.
Definition sch_symbol.h:916
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
BOX2I GetBodyBoundingBox() const override
Return a bounding box for the symbol body but not the pins or fields.
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool IsMovableFromAnchorPoint() const override
Return true for items which are moved with the anchor point at mouse cursor and false for items moved...
bool IsPower() const override
bool operator==(const SCH_SYMBOL &aSymbol) const
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
Definition sim_lib_mgr.h:48
const SPICE_GENERATOR & SpiceGenerator() const
Definition sim_model.h:431
std::vector< std::reference_wrapper< const SIM_MODEL_PIN > > GetPins() const
virtual std::string ItemName(const SPICE_ITEM &aItem) const
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:63
bool m_DNP
True if symbol is set to 'Do Not Populate'.
Definition symbol.h:248
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 void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition symbol.h:169
const TRANSFORM & GetTransform() const
Definition symbol.h:218
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
bool m_excludedFromBoard
Definition symbol.h:247
virtual bool GetShowPinNames() const
Definition symbol.h:164
SYMBOL & operator=(const SYMBOL &aItem)
Definition symbol.h:91
virtual bool GetShowPinNumbers() const
Definition symbol.h:170
TRANSFORM m_transform
The rotation/mirror transformation.
Definition symbol.h:238
const std::vector< TEMPLATE_FIELDNAME > & GetTemplateFieldNames()
Return a template field name list for read only access.
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:46
wxString wx_str() const
Definition utf8.cpp:45
wxString m_Name
bool m_ExcludedFromBOM
bool m_ExcludedFromSim
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
T Convert(const wxString &aValue)
Convert a wxString to a generic type T.
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
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 STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define IS_DANGLING
indicates a pin is dangling
a few functions useful in geometry calculations.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:449
@ LAYER_DEVICE
Definition layer_ids.h:466
@ LAYER_VALUEPART
Definition layer_ids.h:461
@ LAYER_FIELDS
Definition layer_ids.h:462
@ LAYER_REFERENCEPART
Definition layer_ids.h:460
@ LAYER_DNP_MARKER
Definition layer_ids.h:478
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:45
Message panel definition file.
bool BoxHitTest(const VECTOR2I &aHitPoint, const BOX2I &aHittee, int aAccuracy)
Perform a point-to-box hit test.
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
wxString GetRefDesUnannotated(const wxString &aSource)
Return an unannotated refdes from either a prefix or an existing refdes.
#define _HKI(x)
Definition page_info.cpp:44
see class PGM_BASE
@ PT_NC
not connected (must be left open)
Definition pin_type.h:50
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:46
#define TYPE_HASH(x)
Definition property.h:74
#define NO_SETTER(owner, type)
Definition property.h:828
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition property.h:823
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
#define REGISTER_TYPE(x)
Collection of utility functions for component reference designators (refdes)
void CollectOtherUnits(const wxString &aRef, int aUnit, const LIB_ID &aLibId, SCH_SHEET_PATH &aSheet, std::vector< SCH_SYMBOL * > *otherUnits)
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
Definition sch_field.h:362
int NextFieldOrdinal(const std::vector< SCH_FIELD > &aFields)
Definition sch_field.h:351
@ NO_CONNECT_END
Definition sch_item.h:87
@ SHEET_LABEL_END
Definition sch_item.h:86
@ LABEL_END
Definition sch_item.h:83
@ JUNCTION_END
Definition sch_item.h:81
@ PIN_END
Definition sch_item.h:82
@ WIRE_END
Definition sch_item.h:79
@ BASE
Definition sch_item.h:59
std::string toUTFTildaText(const wxString &txt)
Convert a wxString to UTF8 and replace any control characters with a ~, where a control character is ...
static struct SCH_SYMBOL_DESC _SCH_SYMBOL_DESC
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::vector< std::pair< FIELD_T, wxString > > Fields
Definition sch_screen.h:87
bool m_PDFPropertyPopups
Definition sch_plotter.h:64
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
std::string refName
Hold a name of a symbol's field, field value, and default visibility.
SYMBOL_ORIENTATION_PROP
Definition symbol.h:51
@ SYMBOL_ANGLE_180
Definition symbol.h:54
@ SYMBOL_ANGLE_0
Definition symbol.h:52
@ SYMBOL_ANGLE_90
Definition symbol.h:53
@ SYMBOL_ANGLE_270
Definition symbol.h:55
@ SYM_ORIENT_270
Definition symbol.h:42
@ SYM_ROTATE_CLOCKWISE
Definition symbol.h:37
@ SYM_ROTATE_COUNTERCLOCKWISE
Definition symbol.h:38
@ SYM_MIRROR_Y
Definition symbol.h:44
@ SYM_ORIENT_180
Definition symbol.h:41
@ SYM_MIRROR_X
Definition symbol.h:43
@ SYM_NORMAL
Definition symbol.h:36
@ SYM_ORIENT_90
Definition symbol.h:40
@ SYM_ORIENT_0
Definition symbol.h:39
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ 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".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
wxLogTrace helper definitions.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:229
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:78
@ SCH_FIELD_LOCATE_REFERENCE_T
Definition typeinfo.h:184
@ SCH_FIELD_LOCATE_FOOTPRINT_T
Definition typeinfo.h:186
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_LOCATE_ANY_T
Definition typeinfo.h:203
@ SCH_FIELD_LOCATE_VALUE_T
Definition typeinfo.h:185
@ SCH_FIELD_LOCATE_DATASHEET_T
Definition typeinfo.h:187
@ SCH_SYMBOL_LOCATE_POWER_T
Definition typeinfo.h:200
@ SCH_PIN_T
Definition typeinfo.h:157
Custom text control validator definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694