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#include <properties/property.h>
50
51
52std::unordered_map<TRANSFORM, int> SCH_SYMBOL::s_transformToOrientationCache;
53
54
59std::string toUTFTildaText( const wxString& txt )
60{
61 std::string ret = TO_UTF8( txt );
62
63 for( char& c : ret )
64 {
65 if( (unsigned char) c <= ' ' )
66 c = '~';
67 }
68
69 return ret;
70}
71
72
74 SYMBOL( nullptr, SCH_SYMBOL_T )
75{
76 Init( VECTOR2I( 0, 0 ) );
77}
78
79
80SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId, const SCH_SHEET_PATH* aSheet, int aUnit,
81 int aBodyStyle, const VECTOR2I& aPosition, EDA_ITEM* aParent ) :
82 SYMBOL( aParent, SCH_SYMBOL_T )
83{
84 Init( aPosition );
85
86 m_unit = aUnit;
87 m_bodyStyle = aBodyStyle;
88 m_lib_id = aLibId;
89
90 std::unique_ptr<LIB_SYMBOL> part;
91
92 part = aSymbol.Flatten();
93 part->SetParent();
94 SetLibSymbol( part.release() );
95
96 // Copy fields from the library symbol
97 UpdateFields( aSheet, 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, const PICKED_SYMBOL& aSel,
117 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;
146 m_instances = aSymbol.m_instances;
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 = [&]( FIELD_T id, SCH_LAYER_ID layer )
186 {
187 m_fields.emplace_back( this, id, GetCanonicalFieldName( id ) );
188 m_fields.back().SetTextPos( pos );
189 m_fields.back().SetLayer( layer );
190 };
191
192 // construct only the mandatory fields
194 addField( FIELD_T::VALUE, LAYER_VALUEPART );
195 addField( FIELD_T::FOOTPRINT, LAYER_FIELDS );
196 addField( FIELD_T::DATASHEET, LAYER_FIELDS );
198
199 m_prefix = wxString( wxT( "U" ) );
200 m_isInNetlist = true;
201}
202
203
205{
206 return new SCH_SYMBOL( *this );
207}
208
209
211{
212 return m_part == nullptr;
213}
214
215
217{
218 // If a symbol's anchor is not grid-aligned to its pins then moving from the anchor is
219 // going to end up moving the symbol's pins off-grid.
220
221 // The minimal grid size allowed to place a pin is 25 mils
222 const int min_grid_size = schIUScale.MilsToIU( 25 );
223
224 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
225 {
226 if( ( ( pin->GetPosition().x - m_pos.x ) % min_grid_size ) != 0 )
227 return false;
228
229 if( ( ( pin->GetPosition().y - m_pos.y ) % min_grid_size ) != 0 )
230 return false;
231 }
232
233 return true;
234}
235
236
237void SCH_SYMBOL::SetLibId( const LIB_ID& aLibId )
238{
239 m_lib_id = aLibId;
240}
241
242
244{
245 if( !m_schLibSymbolName.IsEmpty() )
246 return m_schLibSymbolName;
247 else
248 return m_lib_id.Format();
249}
250
251
253{
254 wxCHECK2( !aLibSymbol || aLibSymbol->IsRoot(), aLibSymbol = nullptr );
255
256 m_part.reset( aLibSymbol );
257
258 // We've just reset the library symbol, so the lib_pins, which were just
259 // pointers to the old symbol, need to be cleared.
260 for( auto& pin : m_pins )
261 pin->SetLibPin( nullptr );
262
263 UpdatePins();
264}
265
266
268{
269 if( m_part )
270 return m_part->GetDescription();
271
272 return wxEmptyString;
273}
274
275
276wxString SCH_SYMBOL::GetShownDescription( int aDepth ) const
277{
278 if( m_part )
279 return m_part->GetShownDescription( aDepth );
280
281 return wxEmptyString;
282}
283
284
286{
287 if( m_part )
288 return m_part->GetKeyWords();
289
290 return wxEmptyString;
291}
292
293
294wxString SCH_SYMBOL::GetShownKeyWords( int aDepth ) const
295{
296 if( m_part )
297 return m_part->GetShownKeyWords( aDepth );
298
299 return wxEmptyString;
300}
301
302
304{
305 if( m_part )
306 return m_part->GetDatasheetField().GetText();
307
308 return wxEmptyString;
309}
310
311
313{
314 std::map<wxString, wxString> altPinMap;
315 std::map<wxString, SCH_PIN::ALT> altPinDefs;
316 std::map<wxString, std::set<SCH_PIN*>> pinUuidMap;
317 std::set<SCH_PIN*> unassignedSchPins;
318 std::set<SCH_PIN*> unassignedLibPins;
319
320 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
321 {
322 pinUuidMap[pin->GetNumber()].insert( pin.get() );
323
324 unassignedSchPins.insert( pin.get() );
325
326 if( !pin->GetAlt().IsEmpty() )
327 {
328 altPinMap[pin->GetNumber()] = pin->GetAlt();
329 auto altDefIt = pin->GetAlternates().find( pin->GetAlt() );
330
331 if( altDefIt != pin->GetAlternates().end() )
332 altPinDefs[pin->GetNumber()] = altDefIt->second;
333 }
334
335 pin->SetLibPin( nullptr );
336 }
337
338 m_pinMap.clear();
339
340 if( !m_part )
341 return;
342
343 for( SCH_PIN* libPin : m_part->GetPins() )
344 {
345 // NW: Don't filter by unit: this data-structure is used for all instances,
346 // some of which might have different units.
347 if( libPin->GetBodyStyle() && m_bodyStyle && m_bodyStyle != libPin->GetBodyStyle() )
348 continue;
349
350 SCH_PIN* pin = nullptr;
351
352 auto ii = pinUuidMap.find( libPin->GetNumber() );
353
354 if( ii == pinUuidMap.end() || ii->second.empty() )
355 {
356 unassignedLibPins.insert( libPin );
357 continue;
358 }
359
360 auto it = ii->second.begin();
361 pin = *it;
362 ii->second.erase( it );
363 pin->GetAlternates() = libPin->GetAlternates();
364 pin->SetLibPin( libPin );
365 pin->SetPosition( libPin->GetPosition() );
366 pin->SetUnit( libPin->GetUnit() );
367 pin->SetBodyStyle( libPin->GetBodyStyle() );
368
369 unassignedSchPins.erase( pin );
370
371 auto iii = altPinMap.find( libPin->GetNumber() );
372
373 if( iii != altPinMap.end() )
374 {
375 wxString altName = iii->second;
376
377 if( pin->GetAlternates().find( altName ) == pin->GetAlternates().end() )
378 {
379 auto defIt = altPinDefs.find( libPin->GetNumber() );
380
381 if( defIt != altPinDefs.end() )
382 {
383 for( const auto& [name, alt] : pin->GetAlternates() )
384 {
385 if( alt.m_Shape == defIt->second.m_Shape && alt.m_Type == defIt->second.m_Type )
386 {
387 altName = name;
388 break;
389 }
390 }
391 }
392 }
393
394 pin->SetAlt( altName );
395 }
396
397 m_pinMap[libPin] = pin;
398 }
399
400 // Add any pins that were not found in the symbol
401 for( SCH_PIN* libPin : unassignedLibPins )
402 {
403 SCH_PIN* pin = nullptr;
404
405 // First try to re-use an existing pin
406 if( !unassignedSchPins.empty() )
407 {
408 auto it = unassignedSchPins.begin();
409 pin = *it;
410 unassignedSchPins.erase( it );
411 }
412 else
413 {
414 // This is a pin that was not found in the symbol, so create a new one.
415 pin = m_pins.emplace_back( std::make_unique<SCH_PIN>( SCH_PIN( this, libPin ) ) ).get();
416 }
417
418 m_pinMap[libPin] = pin;
419 pin->GetAlternates() = libPin->GetAlternates();
420 pin->SetLibPin( libPin );
421 pin->SetPosition( libPin->GetPosition() );
422 pin->SetUnit( libPin->GetUnit() );
423 pin->SetBodyStyle( libPin->GetBodyStyle() );
424 pin->SetNumber( libPin->GetNumber() );
425
426 auto iii = altPinMap.find( libPin->GetNumber() );
427
428 if( iii != altPinMap.end() )
429 {
430 wxString altName = iii->second;
431
432 if( pin->GetAlternates().find( altName ) == pin->GetAlternates().end() )
433 {
434 auto defIt = altPinDefs.find( libPin->GetNumber() );
435
436 if( defIt != altPinDefs.end() )
437 {
438 for( const auto& [name, alt] : pin->GetAlternates() )
439 {
440 if( alt.m_Shape == defIt->second.m_Shape && alt.m_Type == defIt->second.m_Type )
441 {
442 altName = name;
443 break;
444 }
445 }
446 }
447 }
448
449 pin->SetAlt( altName );
450 }
451 }
452
453 // If we have any pins left in the symbol that were not found in the library, remove them.
454 for( auto it1 = m_pins.begin(); it1 != m_pins.end() && !unassignedSchPins.empty(); )
455 {
456 auto it2 = unassignedSchPins.find( it1->get() );
457
458 if( it2 != unassignedSchPins.end() )
459 {
460 it1 = m_pins.erase( it1 );
461 unassignedSchPins.erase( it2 );
462 }
463 else
464 {
465 ++it1;
466 }
467 }
468
469 // If the symbol is selected, then its pins are selected.
470 if( IsSelected() )
471 {
472 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
473 pin->SetSelected();
474 }
475}
476
477
478void SCH_SYMBOL::SetBodyStyle( int aBodyStyle )
479{
480 if( aBodyStyle != m_bodyStyle )
481 {
482 m_bodyStyle = aBodyStyle;
483
484 // The body style may have a different pin layout so the update the pin map.
485 UpdatePins();
486 }
487}
488
489
491{
492 if( m_part )
493 return m_part->GetUnitCount();
494
495 return 0;
496}
497
498
500{
501 if( m_part )
502 return m_part->GetBodyStyleCount();
503
504 return 0;
505}
506
507
509{
510 if( m_part )
511 return m_part->HasDeMorganBodyStyles();
512
513 return false;
514}
515
516
517wxString SCH_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
518{
519 if( m_part )
520 return m_part->GetUnitDisplayName( aUnit, aLabel );
521 else if( aLabel )
522 return wxString::Format( _( "Unit %s" ), SubReference( aUnit ) );
523 else
524 return SubReference( aUnit );
525}
526
527
528wxString SCH_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
529{
530 if( m_part )
531 return m_part->GetBodyStyleDescription( aBodyStyle, aLabel );
532 else
533 return wxT( "?" );
534}
535
536
537bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance, const KIID_PATH& aSheetPath, bool aTestFromEnd ) const
538{
539 for( const SCH_SYMBOL_INSTANCE& instance : m_instances )
540 {
541 if( !aTestFromEnd )
542 {
543 if( instance.m_Path == aSheetPath )
544 {
545 aInstance = instance;
546 return true;
547 }
548 }
549 else if( instance.m_Path.EndsWith( aSheetPath ) )
550 {
551 aInstance = instance;
552 return true;
553 }
554 }
555
556 return false;
557}
558
559
560void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
561{
562 RemoveInstance( aInstancePath.Path() );
563}
564
565
566void SCH_SYMBOL::RemoveInstance( const KIID_PATH& aInstancePath )
567{
568 // Search for an existing path and remove it if found
569 // (search from back to avoid invalidating iterator on remove)
570 for( int ii = m_instances.size() - 1; ii >= 0; --ii )
571 {
572 if( m_instances[ii].m_Path == aInstancePath )
573 {
574 wxLogTrace( traceSchSheetPaths,
575 wxS( "Removing symbol instance:\n"
576 " sheet path %s\n"
577 " reference %s, unit %d from symbol %s." ),
578 aInstancePath.AsString(), m_instances[ii].m_Reference, m_instances[ii].m_Unit,
579 m_Uuid.AsString() );
580
581 m_instances.erase( m_instances.begin() + ii );
582 }
583 }
584}
585
586
587void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef, int aUnit )
588{
589 SCH_SYMBOL_INSTANCE instance;
590 instance.m_Path = aPath;
591 instance.m_Reference = aRef;
592 instance.m_Unit = aUnit;
593
594 AddHierarchicalReference( instance );
595}
596
597
599{
600 RemoveInstance( aInstance.m_Path );
601
602 SCH_SYMBOL_INSTANCE instance = aInstance;
603
604 wxLogTrace( traceSchSheetPaths,
605 wxS( "Adding symbol '%s' instance:\n"
606 " sheet path '%s'\n"
607 " reference '%s'\n"
608 " unit %d\n" ),
609 m_Uuid.AsString(), instance.m_Path.AsString(), instance.m_Reference, instance.m_Unit );
610
611 m_instances.push_back( instance );
612
613 // This should set the default instance to the first saved instance data for each symbol
614 // when importing sheets.
615 if( m_instances.size() == 1 )
616 {
618 m_unit = instance.m_Unit;
619 }
620}
621
622
623const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
624{
625 KIID_PATH path = sheet->Path();
626 wxString ref;
627 wxString subRef;
628
629 wxLogTrace( traceSchSymbolRef, "GetRef for symbol %s on path %s (sheet path has %zu sheets)", m_Uuid.AsString(),
630 path.AsString(), sheet->size() );
631
632 wxLogTrace( traceSchSymbolRef, " Symbol has %zu instance references", m_instances.size() );
633
634 for( const SCH_SYMBOL_INSTANCE& instance : m_instances )
635 {
636 wxLogTrace( traceSchSymbolRef, " Instance: path=%s, ref=%s", instance.m_Path.AsString(),
637 instance.m_Reference );
638
639 if( instance.m_Path == path )
640 {
641 ref = instance.m_Reference;
642 subRef = SubReference( instance.m_Unit );
643 wxLogTrace( traceSchSymbolRef, " MATCH FOUND: ref=%s", ref );
644 break;
645 }
646 }
647
648 // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
649 // use this as a default for this path. This will happen if we load a version 1 schematic
650 // file. It will also mean that multiple instances of the same sheet by default all have
651 // the same symbol references, but perhaps this is best.
652 if( ref.IsEmpty() && !GetField( FIELD_T::REFERENCE )->GetText().IsEmpty() )
653 {
655 wxLogTrace( traceSchSymbolRef, " Using fallback from REFERENCE field: %s", ref );
656 }
657
658 if( ref.IsEmpty() )
659 {
661 wxLogTrace( traceSchSymbolRef, " Using unannotated reference: %s", ref );
662 }
663
664 if( aIncludeUnit && GetUnitCount() > 1 )
665 ref += subRef;
666
667 wxLogTrace( traceSchSymbolRef, " Final reference: %s", ref );
668
669 return ref;
670}
671
672
673void SCH_SYMBOL::SetRefProp( const wxString& aRef )
674{
676
677 if( validator.DoValidate( aRef, nullptr ) )
678 SetRef( &Schematic()->CurrentSheet(), aRef );
679}
680
681
682void SCH_SYMBOL::SetValueProp( const wxString& aValue )
683{
684 wxString currentVariant = Schematic()->GetCurrentVariant();
685 SetValueFieldText( aValue, &Schematic()->CurrentSheet(), currentVariant );
686}
687
688
689void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
690{
691 KIID_PATH path = sheet->Path();
692 bool found = false;
693
694 // check to see if it is already there before inserting it
695 for( SCH_SYMBOL_INSTANCE& instance : m_instances )
696 {
697 if( instance.m_Path == path )
698 {
699 found = true;
700 instance.m_Reference = ref;
701 break;
702 }
703 }
704
705 if( !found )
707
708 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
709 pin->ClearDefaultNetName( sheet );
710
711 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
713
714 // Reinit the m_prefix member if needed
716
717 if( m_prefix.IsEmpty() )
718 m_prefix = wxT( "U" );
719
720 // Power symbols have references starting with # and are not included in netlists
721 m_isInNetlist = !ref.StartsWith( wxT( "#" ) );
722}
723
724
725void SCH_SYMBOL::SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath,
726 const wxString& aVariantName )
727{
728 wxCHECK( !aFieldName.IsEmpty(), /* void */ );
729
730 SCH_FIELD* field = GetField( aFieldName );
731
732 wxCHECK( field, /* void */ );
733
734 switch( field->GetId() )
735 {
737 wxCHECK( aPath, /* void */ );
738 SetRef( aPath, aFieldText );
739 break;
740
742 {
743 wxString defaultText = GetFootprintFieldText( false, nullptr, false );
744
745 if( aFieldText != defaultText )
746 {
747 if( aVariantName.IsEmpty() )
748 {
749 SetFootprintFieldText( aFieldText );
750 }
751 else
752 {
753 wxCHECK( aPath, /* void */ );
754
755 SCH_SYMBOL_INSTANCE* instance = getInstance( *aPath );
756
757 wxCHECK( instance, /* void */ );
758
759 if( instance->m_Variants.contains( aVariantName ) )
760 {
761 instance->m_Variants[aVariantName].m_Fields[aFieldName] = aFieldText;
762 }
763 else
764 {
765 SCH_SYMBOL_VARIANT newVariant( aVariantName );
766
767 newVariant.InitializeAttributes( *this );
768 newVariant.m_Fields[aFieldName] = aFieldText;
769 instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
770 }
771 }
772 }
773
774 break;
775 }
776
777 default:
778 {
779 wxString defaultText = field->GetText( aPath );
780
781 if( aFieldText != defaultText )
782 {
783 if( aVariantName.IsEmpty() )
784 {
785 field->SetText( aFieldText );
786 }
787 else
788 {
789 SCH_SYMBOL_INSTANCE* instance = getInstance( *aPath );
790
791 wxCHECK( instance, /* void */ );
792
793 if( instance->m_Variants.contains( aVariantName ) )
794 {
795 instance->m_Variants[aVariantName].m_Fields[aFieldName] = aFieldText;
796 }
797 else
798 {
799 SCH_SYMBOL_VARIANT newVariant( aVariantName );
800
801 newVariant.InitializeAttributes( *this );
802 newVariant.m_Fields[aFieldName] = aFieldText;
803 instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
804 }
805 }
806 }
807
808 break;
809 }
810 }
811}
812
813
814wxString SCH_SYMBOL::GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
815 const wxString& aVariantName ) const
816{
817 wxCHECK( !aFieldName.IsEmpty(), wxEmptyString );
818
819 const SCH_FIELD* field = GetField( aFieldName );
820
821 wxCHECK( field, wxEmptyString );
822
823 switch( field->GetId() )
824 {
826 wxCHECK( aPath, field->GetText() );
827 return GetRef( aPath, false );
828 break;
829
831 if( !aVariantName.IsEmpty() && aPath )
832 {
833 const SCH_SYMBOL_INSTANCE* instance = getInstance( *aPath );
834
835 if( instance && instance->m_Variants.contains( aVariantName )
836 && instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
837 {
838 return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
839 }
840 }
841
842 return GetFootprintFieldText( false, nullptr, false );
843
844 default:
845 if( aVariantName.IsEmpty() )
846 {
847 return field->GetText();
848 }
849 else
850 {
851 const SCH_SYMBOL_INSTANCE* instance = getInstance( *aPath );
852
853 if( instance->m_Variants.contains( aVariantName )
854 && instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
855 return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
856 }
857
858 break;
859 }
860
861 return field->GetText();
862}
863
864
865bool SCH_SYMBOL::IsAnnotated( const SCH_SHEET_PATH* aSheet ) const
866{
867 KIID_PATH path = aSheet->Path();
868
869 for( const SCH_SYMBOL_INSTANCE& instance : m_instances )
870 {
871 if( instance.m_Path == path )
872 return !instance.m_Reference.IsEmpty() && instance.m_Reference.Last() != '?';
873 }
874
875 return false;
876}
877
878
880{
881 wxString refDesignator = GetField( FIELD_T::REFERENCE )->GetText();
882
883 refDesignator.Replace( "~", " " );
884
885 wxString prefix = refDesignator;
886
887 while( prefix.Length() )
888 {
889 wxUniCharRef last = prefix.Last();
890
891 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
892 prefix.RemoveLast();
893 else
894 break;
895 }
896
897 // Avoid a prefix containing trailing/leading spaces
898 prefix.Trim( true );
899 prefix.Trim( false );
900
901 if( !prefix.IsEmpty() )
902 SetPrefix( prefix );
903}
904
905
906wxString SCH_SYMBOL::SubReference( int aUnit, bool aAddSeparator ) const
907{
908 if( SCHEMATIC* schematic = Schematic() )
909 return schematic->Settings().SubReference( aUnit, aAddSeparator );
910
911 return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
912}
913
914
916{
917 KIID_PATH path = aSheet->Path();
918
919 for( const SCH_SYMBOL_INSTANCE& instance : m_instances )
920 {
921 if( instance.m_Path == path )
922 return instance.m_Unit;
923 }
924
925 // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
926 // version 1 schematic file.
927 return m_unit;
928}
929
930
931void SCH_SYMBOL::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
932{
933 KIID_PATH path = aSheet->Path();
934
935 // check to see if it is already there before inserting it
936 for( SCH_SYMBOL_INSTANCE& instance : m_instances )
937 {
938 if( instance.m_Path == path )
939 {
940 instance.m_Unit = aUnitSelection;
941 return;
942 }
943 }
944
945 // didn't find it; better add it
947}
948
949
950void SCH_SYMBOL::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
951{
952 if( !aInstance || aVariantName.IsEmpty() )
953 {
954 m_DNP = aEnable;
955 return;
956 }
957
958 SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
959
960 wxCHECK_MSG( instance, /* void */,
961 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
962 aInstance->PathHumanReadable() ) );
963
964 if( aVariantName.IsEmpty() )
965 {
966 m_DNP = aEnable;
967 }
968 else
969 {
970 if( instance->m_Variants.contains( aVariantName ) && ( aEnable != instance->m_Variants[aVariantName].m_DNP ) )
971 {
972 instance->m_Variants[aVariantName].m_DNP = aEnable;
973 }
974 else
975 {
976 SCH_SYMBOL_VARIANT variant( aVariantName );
977
978 variant.InitializeAttributes( *this );
979 variant.m_DNP = aEnable;
980 AddVariant( *aInstance, variant );
981 }
982 }
983}
984
985
986bool SCH_SYMBOL::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
987{
988 if( !aInstance || aVariantName.IsEmpty() )
989 return m_DNP;
990
991 SCH_SYMBOL_INSTANCE instance;
992
993 if( !GetInstance( instance, aInstance->Path() ) )
994 return m_DNP;
995
996 if( aVariantName.IsEmpty() )
997 return m_DNP;
998 else if( instance.m_Variants.contains( aVariantName ) )
999 return instance.m_Variants[aVariantName].m_DNP;
1000
1001 return m_DNP;
1002}
1003
1004
1005void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
1006{
1007 if( !aInstance || aVariantName.IsEmpty() )
1008 {
1009 m_excludedFromBOM = aEnable;
1010 return;
1011 }
1012
1013 SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
1014
1015 wxCHECK_MSG( instance, /* void */,
1016 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
1017 aInstance->PathHumanReadable() ) );
1018
1019 if( aVariantName.IsEmpty() )
1020 {
1021 m_excludedFromBOM = aEnable;
1022 }
1023 else
1024 {
1025 if( instance->m_Variants.contains( aVariantName )
1026 && ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromBOM ) )
1027 {
1028 instance->m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
1029 }
1030 else
1031 {
1032 SCH_SYMBOL_VARIANT variant( aVariantName );
1033
1034 variant.InitializeAttributes( *this );
1035 variant.m_ExcludedFromBOM = aEnable;
1036 AddVariant( *aInstance, variant );
1037 }
1038 }
1039}
1040
1041
1042bool SCH_SYMBOL::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
1043{
1044 if( !aInstance || aVariantName.IsEmpty() )
1045 return m_excludedFromBOM;
1046
1047 SCH_SYMBOL_INSTANCE instance;
1048
1049 if( !GetInstance( instance, aInstance->Path() ) )
1050 return m_excludedFromBOM;
1051
1052 if( aVariantName.IsEmpty() )
1053 return m_excludedFromBOM;
1054 else if( instance.m_Variants.contains( aVariantName ) )
1055 return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
1056
1057 // If the variant has not been defined yet, return the default exclude from BOM setting.
1058 return m_excludedFromBOM;
1059}
1060
1061
1062void SCH_SYMBOL::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
1063{
1064 if( !aInstance || aVariantName.IsEmpty() )
1065 {
1066 m_excludedFromSim = aEnable;
1067 return;
1068 }
1069
1070 SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
1071
1072 wxCHECK_MSG( instance, /* void */,
1073 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
1074 aInstance->PathHumanReadable() ) );
1075
1076 if( aVariantName.IsEmpty() )
1077 {
1078 m_excludedFromSim = aEnable;
1079 }
1080 else
1081 {
1082 if( instance->m_Variants.contains( aVariantName )
1083 && ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromSim ) )
1084 {
1085 instance->m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
1086 }
1087 else
1088 {
1089 SCH_SYMBOL_VARIANT variant( aVariantName );
1090
1091 variant.InitializeAttributes( *this );
1092 variant.m_ExcludedFromSim = aEnable;
1093 AddVariant( *aInstance, variant );
1094 }
1095 }
1096}
1097
1098
1099bool SCH_SYMBOL::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
1100{
1101 if( !aInstance || aVariantName.IsEmpty() )
1102 return m_excludedFromSim;
1103
1104 SCH_SYMBOL_INSTANCE instance;
1105
1106 if( !GetInstance( instance, aInstance->Path() ) )
1107 return m_excludedFromSim;
1108
1109 if( aVariantName.IsEmpty() )
1110 return m_excludedFromSim;
1111 else if ( instance.m_Variants.contains( aVariantName ) )
1112 return instance.m_Variants[aVariantName].m_ExcludedFromSim;
1113
1114 // If variant is not defined yet, return default exclude from simulation setting.
1115 return m_excludedFromSim;
1116}
1117
1118
1119void SCH_SYMBOL::SetExcludedFromBoard( bool aEnable, const SCH_SHEET_PATH* aInstance,
1120 const wxString& aVariantName )
1121{
1122 if( !aInstance || aVariantName.IsEmpty() )
1123 {
1124 m_excludedFromBoard = aEnable;
1125 return;
1126 }
1127
1128 SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
1129
1130 wxCHECK_MSG( instance, /* void */,
1131 wxString::Format( wxS( "Cannot set exclude from board for invalid sheet path '%s'." ),
1132 aInstance->PathHumanReadable() ) );
1133
1134 if( aVariantName.IsEmpty() )
1135 {
1136 m_excludedFromBoard = aEnable;
1137 }
1138 else
1139 {
1140 if( instance->m_Variants.contains( aVariantName )
1141 && ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromBoard ) )
1142 {
1143 instance->m_Variants[aVariantName].m_ExcludedFromBoard = aEnable;
1144 }
1145 else
1146 {
1147 SCH_SYMBOL_VARIANT variant( aVariantName );
1148
1149 variant.InitializeAttributes( *this );
1150 variant.m_ExcludedFromBoard = aEnable;
1151 AddVariant( *aInstance, variant );
1152 }
1153 }
1154}
1155
1156
1158 const wxString& aVariantName ) const
1159{
1160 if( !aInstance || aVariantName.IsEmpty() )
1161 return m_excludedFromBoard;
1162
1163 SCH_SYMBOL_INSTANCE instance;
1164
1165 if( !GetInstance( instance, aInstance->Path() ) )
1166 return m_excludedFromBoard;
1167
1168 if( aVariantName.IsEmpty() )
1169 return m_excludedFromBoard;
1170 else if( instance.m_Variants.contains( aVariantName ) )
1171 return instance.m_Variants[aVariantName].m_ExcludedFromBoard;
1172
1173 // If variant is not defined yet, return default exclude from board setting.
1174 return m_excludedFromBoard;
1175}
1176
1177
1178void SCH_SYMBOL::SetExcludedFromPosFiles( bool aEnable, const SCH_SHEET_PATH* aInstance,
1179 const wxString& aVariantName )
1180{
1181 if( !aInstance || aVariantName.IsEmpty() )
1182 {
1183 m_excludedFromPosFiles = aEnable;
1184 return;
1185 }
1186
1187 SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
1188
1189 wxCHECK_MSG( instance, /* void */,
1190 wxString::Format( wxS( "Cannot set exclude from pos files for invalid sheet path '%s'." ),
1191 aInstance->PathHumanReadable() ) );
1192
1193 if( aVariantName.IsEmpty() )
1194 {
1195 m_excludedFromPosFiles = aEnable;
1196 }
1197 else
1198 {
1199 if( instance->m_Variants.contains( aVariantName )
1200 && ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromPosFiles ) )
1201 {
1202 instance->m_Variants[aVariantName].m_ExcludedFromPosFiles = aEnable;
1203 }
1204 else
1205 {
1206 SCH_SYMBOL_VARIANT variant( aVariantName );
1207
1208 variant.InitializeAttributes( *this );
1209 variant.m_ExcludedFromPosFiles = aEnable;
1210 AddVariant( *aInstance, variant );
1211 }
1212 }
1213}
1214
1215
1217 const wxString& aVariantName ) const
1218{
1219 if( !aInstance || aVariantName.IsEmpty() )
1221
1222 SCH_SYMBOL_INSTANCE instance;
1223
1224 if( !GetInstance( instance, aInstance->Path() ) )
1226
1227 if( aVariantName.IsEmpty() )
1229 else if( instance.m_Variants.contains( aVariantName ) )
1230 return instance.m_Variants[aVariantName].m_ExcludedFromPosFiles;
1231
1232 // If variant is not defined yet, return default exclude from position files setting.
1234}
1235
1236
1237void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
1238{
1239 for( SCH_SYMBOL_INSTANCE& instance : m_instances )
1240 instance.m_Unit = aUnitSelection;
1241}
1242
1243
1244const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aInstance,
1245 bool aAllowExtraText, const wxString& aVariantName ) const
1246{
1247 if( aVariantName.IsEmpty() )
1248 {
1249 if( aResolve )
1250 return GetField( FIELD_T::VALUE )->GetShownText( aInstance, aAllowExtraText );
1251
1252 return GetField( FIELD_T::VALUE )->GetText();
1253 }
1254
1255 std::optional variant = GetVariant( *aInstance, aVariantName );
1256
1257 if( variant && variant->m_Fields.contains( GetField( FIELD_T::VALUE )->GetName() ) )
1258 return variant->m_Fields[GetField( FIELD_T::VALUE )->GetName()];
1259
1260 // Fall back to default value when variant doesn't have an override
1261 if( aResolve )
1262 return GetField( FIELD_T::VALUE )->GetShownText( aInstance, aAllowExtraText );
1263
1264 return GetField( FIELD_T::VALUE )->GetText();
1265}
1266
1267
1268void SCH_SYMBOL::SetValueFieldText( const wxString& aValue, const SCH_SHEET_PATH* aInstance,
1269 const wxString& aVariantName )
1270{
1271 if( !aInstance || aVariantName.IsEmpty() )
1272 {
1273 GetField( FIELD_T::VALUE )->SetText( aValue );
1274 return;
1275 }
1276
1277 SCH_SYMBOL_INSTANCE* instance = getInstance( *aInstance );
1278
1279 wxCHECK( instance, /* void */ );
1280
1281 wxString fieldName = GetField( FIELD_T::VALUE )->GetName();
1282
1283 if( instance->m_Variants.contains( aVariantName ) )
1284 {
1285 instance->m_Variants[aVariantName].m_Fields[fieldName] = aValue;
1286 }
1287 else
1288 {
1289 SCH_SYMBOL_VARIANT newVariant( aVariantName );
1290
1291 newVariant.InitializeAttributes( *this );
1292 newVariant.m_Fields[fieldName] = aValue;
1293 instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
1294 }
1295}
1296
1297
1298const wxString SCH_SYMBOL::GetFootprintFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
1299 bool aAllowExtraText, const wxString& aVariantName ) const
1300{
1301 if( aResolve )
1302 return GetField( FIELD_T::FOOTPRINT )->GetShownText( aPath, aAllowExtraText, 0, aVariantName );
1303
1304 return GetField( FIELD_T::FOOTPRINT )->GetText();
1305}
1306
1307
1308void SCH_SYMBOL::SetFootprintFieldText( const wxString& aFootprint )
1309{
1310 GetField( FIELD_T::FOOTPRINT )->SetText( aFootprint );
1311}
1312
1313
1315{
1316 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
1317 return field;
1318
1319 m_fields.emplace_back( this, aFieldType );
1320 return &m_fields.back();
1321}
1322
1323
1324const SCH_FIELD* SCH_SYMBOL::GetField( FIELD_T aFieldType ) const
1325{
1326 return FindField( m_fields, aFieldType );
1327}
1328
1329
1330SCH_FIELD* SCH_SYMBOL::GetField( const wxString& aFieldName )
1331{
1332 return FindField( m_fields, aFieldName );
1333}
1334
1335
1336const SCH_FIELD* SCH_SYMBOL::GetField( const wxString& aFieldName ) const
1337{
1338 return FindField( m_fields, aFieldName );
1339}
1340
1341
1342void SCH_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly ) const
1343{
1344 for( const SCH_FIELD& field : m_fields )
1345 {
1346 if( aVisibleOnly )
1347 {
1348 if( !field.IsVisible() || field.GetText().IsEmpty() )
1349 continue;
1350 }
1351
1352 aVector.push_back( const_cast<SCH_FIELD*>( &field ) );
1353 }
1354
1355 std::sort( aVector.begin(), aVector.end(),
1356 []( SCH_FIELD* lhs, SCH_FIELD* rhs )
1357 {
1358 return lhs->GetOrdinal() < rhs->GetOrdinal();
1359 } );
1360}
1361
1362
1364{
1365 return NextFieldOrdinal( m_fields );
1366}
1367
1368
1370{
1371 m_fields.push_back( aField );
1372 return &m_fields.back();
1373}
1374
1375
1376void SCH_SYMBOL::RemoveField( const wxString& aFieldName )
1377{
1378 for( unsigned ii = 0; ii < m_fields.size(); ++ii )
1379 {
1380 if( m_fields[ii].IsMandatory() )
1381 continue;
1382
1383 if( aFieldName == m_fields[ii].GetName( false ) )
1384 {
1385 m_fields.erase( m_fields.begin() + ii );
1386 return;
1387 }
1388 }
1389}
1390
1391
1393{
1394 for( SCH_FIELD& field : m_fields )
1395 {
1396 if( field.GetName().IsSameAs( aFieldName, false ) )
1397 return &field;
1398 }
1399
1400 return nullptr;
1401}
1402
1403
1404void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef, bool aUpdateOtherFields,
1405 bool aResetRef, bool aResetOtherFields )
1406{
1407 if( m_part )
1408 {
1409 std::vector<SCH_FIELD*> fields;
1410 m_part->GetFields( fields );
1411
1412 for( const SCH_FIELD* libField : fields )
1413 {
1414 SCH_FIELD* schField;
1415 FIELD_T fieldType = FIELD_T::USER;
1416
1417 if( libField->IsMandatory() )
1418 {
1419 fieldType = libField->GetId();
1420 schField = GetField( fieldType );
1421 }
1422 else
1423 {
1424 schField = GetField( libField->GetCanonicalName() );
1425
1426 if( !schField )
1427 {
1428 schField = AddField( SCH_FIELD( this, FIELD_T::USER, libField->GetCanonicalName() ) );
1429 schField->ImportValues( *libField );
1430 schField->SetTextPos( m_pos + libField->GetTextPos() );
1431 }
1432 }
1433
1434 schField->SetPrivate( libField->IsPrivate() );
1435
1436 if( aUpdateStyle )
1437 {
1438 schField->ImportValues( *libField );
1439 schField->SetTextPos( m_pos + libField->GetTextPos() );
1440 }
1441
1442 if( fieldType == FIELD_T::REFERENCE && aPath )
1443 {
1444 if( aResetRef )
1445 SetRef( aPath, m_part->GetField( FIELD_T::REFERENCE )->GetText() );
1446 else if( aUpdateRef )
1447 SetRef( aPath, libField->GetText() );
1448 }
1449 else if( fieldType == FIELD_T::VALUE )
1450 {
1451 SetValueFieldText( UnescapeString( libField->GetText() ) );
1452 }
1453 else if( fieldType == FIELD_T::DATASHEET )
1454 {
1455 if( aResetOtherFields )
1456 schField->SetText( GetDatasheet() ); // alias-specific value
1457 else if( aUpdateOtherFields )
1458 schField->SetText( libField->GetText() );
1459 }
1460 else
1461 {
1462 if( aResetOtherFields || aUpdateOtherFields )
1463 schField->SetText( libField->GetText() );
1464 }
1465 }
1466 }
1467}
1468
1469
1470void SCH_SYMBOL::SyncOtherUnits( const SCH_SHEET_PATH& aSourceSheet, SCH_COMMIT& aCommit,
1471 PROPERTY_BASE* aProperty, const wxString& aVariantName )
1472{
1473 bool updateValue = true;
1474 bool updateExclFromBOM = true;
1475 bool updateExclFromBoard = true;
1476 bool updateDNP = true;
1477 bool updateOtherFields = true;
1478 bool updatePins = true;
1479
1480 if( aProperty )
1481 {
1482 updateValue = aProperty->Name() == _HKI( "Value" );
1483 updateExclFromBoard = aProperty->Name() == _HKI( "Exclude From Board" );
1484 updateExclFromBOM = aProperty->Name() == _HKI( "Exclude From Bill of Materials" );
1485 updateDNP = aProperty->Name() == _HKI( "Do not Populate" );
1486 updateOtherFields = false;
1487 updatePins = false;
1488 }
1489
1490 if( !updateValue && !updateExclFromBOM && !updateExclFromBoard && !updateDNP && !updateOtherFields && !updatePins )
1491 {
1492 return;
1493 }
1494
1495 // Keep fields other than the reference, include/exclude flags, and alternate pin assignments
1496 // in sync in multi-unit parts.
1497 if( GetUnitCount() > 1 && IsAnnotated( &aSourceSheet ) )
1498 {
1499 wxString ref = GetRef( &aSourceSheet );
1500
1501 for( SCH_SHEET_PATH& sheet : Schematic()->Hierarchy() )
1502 {
1503 SCH_SCREEN* screen = sheet.LastScreen();
1504 std::vector<SCH_SYMBOL*> otherUnits;
1505
1506 CollectOtherUnits( ref, m_unit, m_lib_id, sheet, &otherUnits );
1507
1508 for( SCH_SYMBOL* otherUnit : otherUnits )
1509 {
1510 aCommit.Modify( otherUnit, screen );
1511
1512 if( updateValue )
1513 otherUnit->SetValueFieldText( GetField( FIELD_T::VALUE )->GetText() );
1514
1515 if( updateOtherFields )
1516 {
1517 for( SCH_FIELD& field : m_fields )
1518 {
1519 if( field.GetId() == FIELD_T::REFERENCE || field.GetId() == FIELD_T::VALUE )
1520 {
1521 // already handled
1522 continue;
1523 }
1524
1525 SCH_FIELD* otherField;
1526
1527 if( field.IsMandatory() )
1528 otherField = otherUnit->GetField( field.GetId() );
1529 else
1530 otherField = otherUnit->GetField( field.GetName() );
1531
1532 if( otherField )
1533 {
1534 otherField->SetText( field.GetText() );
1535 }
1536 else
1537 {
1538 SCH_FIELD newField( field );
1539 const_cast<KIID&>( newField.m_Uuid ) = KIID();
1540
1541 newField.Offset( -GetPosition() );
1542 newField.Offset( otherUnit->GetPosition() );
1543
1544 newField.SetParent( otherUnit );
1545 otherUnit->AddField( newField );
1546 }
1547 }
1548
1549 for( int ii = (int) otherUnit->GetFields().size() - 1; ii >= 0; ii-- )
1550 {
1551 SCH_FIELD& otherField = otherUnit->GetFields()[ii];
1552
1553 if( !otherField.IsMandatory() && !GetField( otherField.GetName() ) )
1554 otherUnit->GetFields().erase( otherUnit->GetFields().begin() + ii );
1555 }
1556 }
1557
1558 if( updateExclFromBOM )
1559 otherUnit->SetExcludedFromBOM( m_excludedFromBOM );
1560
1561 if( updateExclFromBoard )
1562 otherUnit->SetExcludedFromBoard( m_excludedFromBoard );
1563
1564 if( updateDNP )
1565 otherUnit->SetDNP( GetDNP( &aSourceSheet, aVariantName ), &sheet, aVariantName );
1566
1567 if( updatePins )
1568 {
1569 for( const std::unique_ptr<SCH_PIN>& model_pin : m_pins )
1570 {
1571 for( SCH_PIN* src_pin : otherUnit->GetPinsByNumber( model_pin->GetNumber() ) )
1572 src_pin->SetAlt( model_pin->GetAlt() );
1573 }
1574 }
1575 }
1576 }
1577 }
1578}
1579
1580
1581void SCH_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1582{
1583 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1584 aFunction( pin.get() );
1585
1586 for( SCH_FIELD& field : m_fields )
1587 aFunction( &field );
1588}
1589
1590
1591SCH_PIN* SCH_SYMBOL::GetPin( const wxString& aNumber ) const
1592{
1593 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1594 {
1595 if( pin->GetNumber() == aNumber )
1596 return pin.get();
1597 }
1598
1599 return nullptr;
1600}
1601
1602
1603std::vector<SCH_PIN*> SCH_SYMBOL::GetPinsByNumber( const wxString& aNumber ) const
1604{
1605 std::vector<SCH_PIN*> pins;
1606
1607 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1608 {
1609 if( pin->GetNumber() == aNumber )
1610 pins.push_back( pin.get() );
1611 }
1612
1613 return pins;
1614}
1615
1616
1617const SCH_PIN* SCH_SYMBOL::GetPin( const VECTOR2I& aPos ) const
1618{
1619 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1620 {
1621 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
1622 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle();
1623
1624 if( pin_unit > 0 && pin_unit != GetUnit() )
1625 continue;
1626
1627 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
1628 continue;
1629
1630 if( pin->GetPosition() == aPos )
1631 return pin.get();
1632 }
1633
1634 return nullptr;
1635}
1636
1637
1638std::vector<SCH_PIN*> SCH_SYMBOL::GetLibPins() const
1639{
1640 if( m_part )
1641 return m_part->GetGraphicalPins( m_unit, m_bodyStyle );
1642
1643 return std::vector<SCH_PIN*>();
1644}
1645
1646
1647std::vector<SCH_PIN*> SCH_SYMBOL::GetAllLibPins() const
1648{
1649 if( m_part )
1650 return m_part->GetPins();
1651
1652 return std::vector<SCH_PIN*>();
1653}
1654
1655
1657{
1658 return m_part ? m_part->GetPinCount() : 0;
1659}
1660
1661
1663{
1664 auto it = m_pinMap.find( aLibPin );
1665
1666 if( it != m_pinMap.end() )
1667 return it->second;
1668
1669 wxFAIL_MSG_AT( "Pin not found", __FILE__, __LINE__, __FUNCTION__ );
1670 return nullptr;
1671}
1672
1673
1674std::vector<const SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
1675{
1676 std::vector<const SCH_PIN*> pins;
1677 int unit = m_unit;
1678
1679 if( !aSheet && Schematic() )
1680 aSheet = &Schematic()->CurrentSheet();
1681
1682 if( aSheet )
1683 unit = GetUnitSelection( aSheet );
1684
1685 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1686 {
1687 if( unit && pin->GetUnit() && pin->GetUnit() != unit )
1688 continue;
1689
1690 pins.push_back( pin.get() );
1691 }
1692
1693 return pins;
1694}
1695
1696
1697std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet )
1698{
1699 std::vector<SCH_PIN*> pins;
1700 int unit = m_unit;
1701
1702 if( !aSheet && Schematic() )
1703 aSheet = &Schematic()->CurrentSheet();
1704
1705 if( aSheet )
1706 unit = GetUnitSelection( aSheet );
1707
1708 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1709 {
1710 if( unit && pin->GetUnit() && pin->GetUnit() != unit )
1711 continue;
1712
1713 pins.push_back( pin.get() );
1714 }
1715
1716 return pins;
1717}
1718
1719
1720std::vector<SCH_PIN*> SCH_SYMBOL::GetPins() const
1721{
1722 // Back-compat shim: return graphical pins for all units/body styles, violating const
1723 return const_cast<SCH_SYMBOL*>( this )->GetPins( nullptr );
1724}
1725
1726
1728{
1729 wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T, wxT( "Cannot swap data with invalid symbol." ) );
1730
1731 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
1732
1733 std::swap( m_lib_id, symbol->m_lib_id );
1734
1735 m_pins.swap( symbol->m_pins ); // std::vector's swap()
1736
1737 for( std::unique_ptr<SCH_PIN>& pin : symbol->m_pins )
1738 pin->SetParent( symbol );
1739
1740 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1741 pin->SetParent( this );
1742
1743 LIB_SYMBOL* libSymbol = symbol->m_part.release();
1744 symbol->m_part = std::move( m_part );
1745 symbol->UpdatePins();
1746 m_part.reset( libSymbol );
1747 UpdatePins();
1748
1749 std::swap( m_pos, symbol->m_pos );
1750 std::swap( m_unit, symbol->m_unit );
1751 std::swap( m_bodyStyle, symbol->m_bodyStyle );
1752
1753 m_fields.swap( symbol->m_fields ); // std::vector's swap()
1754
1755 for( SCH_FIELD& field : symbol->m_fields )
1756 field.SetParent( symbol );
1757
1758 for( SCH_FIELD& field : m_fields )
1759 field.SetParent( this );
1760
1761 TRANSFORM tmp = m_transform;
1762
1763 m_transform = symbol->m_transform;
1764 symbol->m_transform = tmp;
1765
1766 std::swap( m_excludedFromSim, symbol->m_excludedFromSim );
1767 std::swap( m_excludedFromBOM, symbol->m_excludedFromBOM );
1768 std::swap( m_DNP, symbol->m_DNP );
1769 std::swap( m_excludedFromBoard, symbol->m_excludedFromBoard );
1770
1771 std::swap( m_instances, symbol->m_instances );
1772 std::swap( m_schLibSymbolName, symbol->m_schLibSymbolName );
1773}
1774
1775
1776void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
1777{
1778 for( const SCH_FIELD& field : m_fields )
1779 {
1780 if( field.IsPrivate() )
1781 continue;
1782
1783 if( field.IsMandatory() )
1784 aVars->push_back( field.GetCanonicalName().Upper() );
1785 else
1786 aVars->push_back( field.GetName() );
1787 }
1788
1789 aVars->push_back( wxT( "OP" ) );
1790 aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
1791 aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
1792 aVars->push_back( wxT( "UNIT" ) );
1793 aVars->push_back( wxT( "SHORT_REFERENCE" ) );
1794 aVars->push_back( wxT( "SYMBOL_LIBRARY" ) );
1795 aVars->push_back( wxT( "SYMBOL_NAME" ) );
1796 aVars->push_back( wxT( "SYMBOL_DESCRIPTION" ) );
1797 aVars->push_back( wxT( "SYMBOL_KEYWORDS" ) );
1798 aVars->push_back( wxT( "EXCLUDE_FROM_BOM" ) );
1799 aVars->push_back( wxT( "EXCLUDE_FROM_BOARD" ) );
1800 aVars->push_back( wxT( "EXCLUDE_FROM_SIM" ) );
1801 aVars->push_back( wxT( "DNP" ) );
1802 aVars->push_back( wxT( "SHORT_NET_NAME(<pin_number>)" ) );
1803 aVars->push_back( wxT( "NET_NAME(<pin_number>)" ) );
1804 aVars->push_back( wxT( "NET_CLASS(<pin_number>)" ) );
1805 aVars->push_back( wxT( "PIN_NAME(<pin_number>)" ) );
1806 aVars->push_back( wxT( "REFERENCE(<pin_number>)" ) );
1807 aVars->push_back( wxT( "SHORT_REFERENCE(<pin_number>)" ) );
1808 aVars->push_back( wxT( "UNIT(<pin_number>)" ) );
1809}
1810
1811
1812bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
1813{
1814 return ResolveTextVar( aPath, token, wxEmptyString, aDepth );
1815}
1816
1817
1818bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token,
1819 const wxString& aVariantName, int aDepth ) const
1820{
1821 static wxRegEx operatingPoint( wxT( "^"
1822 "OP"
1823 "(:[^.]*)?" // pin
1824 "(.([0-9])?" // precisionStr
1825 "([a-zA-Z]*))?" // rangeStr
1826 "$" ) );
1827
1828 wxCHECK( aPath, false );
1829
1830 SCHEMATIC* schematic = Schematic();
1831
1832 if( !schematic )
1833 return false;
1834
1835 if( operatingPoint.Matches( *token ) )
1836 {
1837 wxString pin( operatingPoint.GetMatch( *token, 1 ).Lower() );
1838 wxString precisionStr( operatingPoint.GetMatch( *token, 3 ) );
1839 wxString rangeStr( operatingPoint.GetMatch( *token, 4 ) );
1840
1841 int precision = precisionStr.IsEmpty() ? 3 : precisionStr[0] - '0';
1842 wxString range = rangeStr.IsEmpty() ? wxString( wxS( "~A" ) ) : rangeStr;
1843
1844 SIM_LIB_MGR simLibMgr( &schematic->Project() );
1845
1846 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1847 embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() );
1848
1849 if( m_part )
1850 embeddedFilesStack.push_back( m_part->GetEmbeddedFiles() );
1851
1852 simLibMgr.SetFilesStack( std::move( embeddedFilesStack ) );
1853
1854 NULL_REPORTER devnull;
1855 SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast<SCH_SYMBOL&>( *this ), true, aDepth + 1,
1856 aVariantName, devnull ).model;
1857 SPICE_ITEM spiceItem;
1858 spiceItem.refName = GetRef( aPath );
1859
1860 wxString spiceRef = model.SpiceGenerator().ItemName( spiceItem );
1861 spiceRef = spiceRef.Lower();
1862
1863 if( pin.IsEmpty() )
1864 {
1865 *token = schematic->GetOperatingPoint( spiceRef, precision, range );
1866 return true;
1867 }
1868 else if( pin == wxS( ":power" ) )
1869 {
1870 if( rangeStr.IsEmpty() )
1871 range = wxS( "~W" );
1872
1873 *token = schematic->GetOperatingPoint( spiceRef + wxS( ":power" ), precision, range );
1874 return true;
1875 }
1876 else
1877 {
1878 pin = pin.SubString( 1, -1 ); // Strip ':' from front
1879
1880 for( const std::reference_wrapper<const SIM_MODEL_PIN>& modelPin : model.GetPins() )
1881 {
1882 SCH_PIN* symbolPin = GetPin( modelPin.get().symbolPinNumber );
1883
1884 if( pin == symbolPin->GetName().Lower() || pin == symbolPin->GetNumber().Lower() )
1885 {
1886 if( model.GetPins().size() == 2 )
1887 {
1888 *token = schematic->GetOperatingPoint( spiceRef, precision, range );
1889 }
1890 else
1891 {
1892 wxString signalName = spiceRef + wxS( ":" ) + modelPin.get().modelPinName;
1893 *token = schematic->GetOperatingPoint( signalName, precision, range );
1894 }
1895
1896 return true;
1897 }
1898 }
1899 }
1900
1901 *token = wxS( "?" );
1902 return true;
1903 }
1904
1905 if( token->Contains( ':' ) )
1906 {
1907 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
1908 return true;
1909 }
1910
1911 for( const SCH_FIELD& field : m_fields )
1912 {
1913 wxString fieldName = field.IsMandatory() ? field.GetCanonicalName() : field.GetName();
1914
1915 wxString textToken = field.GetText();
1916 textToken.Replace( " ", wxEmptyString );
1917 wxString tokenString = "${" + fieldName + "}";
1918
1919 // If the field data is just a reference to the field, don't resolve
1920 if( textToken.IsSameAs( tokenString, false ) )
1921 return true;
1922
1923 if( token->IsSameAs( fieldName, false ) )
1924 {
1925 if( field.GetId() == FIELD_T::REFERENCE )
1926 {
1927 *token = GetRef( aPath, true );
1928 }
1929 else if( !aVariantName.IsEmpty() )
1930 {
1931 // Check for variant-specific field value
1932 std::optional<SCH_SYMBOL_VARIANT> variant = GetVariant( *aPath, aVariantName );
1933
1934 if( variant && variant->m_Fields.contains( fieldName ) )
1935 *token = variant->m_Fields.at( fieldName );
1936 else
1937 *token = field.GetShownText( aPath, false, aDepth + 1 );
1938 }
1939 else
1940 {
1941 *token = field.GetShownText( aPath, false, aDepth + 1 );
1942 }
1943
1944 return true;
1945 }
1946 }
1947
1948 // Consider missing simulation fields as empty, not un-resolved
1949 if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) || token->IsSameAs( wxT( "SIM.TYPE" ) )
1950 || token->IsSameAs( wxT( "SIM.PINS" ) ) || token->IsSameAs( wxT( "SIM.PARAMS" ) )
1951 || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) || token->IsSameAs( wxT( "SIM.NAME" ) ) )
1952 {
1953 *token = wxEmptyString;
1954 return true;
1955 }
1956
1957 for( const TEMPLATE_FIELDNAME& templateFieldname :
1959 {
1960 if( token->IsSameAs( templateFieldname.m_Name ) || token->IsSameAs( templateFieldname.m_Name.Upper() ) )
1961 {
1962 // If we didn't find it in the fields list then it isn't set on this symbol.
1963 // Just return an empty string.
1964 *token = wxEmptyString;
1965 return true;
1966 }
1967 }
1968
1969 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
1970 {
1971 wxString footprint = GetFootprintFieldText( true, aPath, false );
1972
1973 wxArrayString parts = wxSplit( footprint, ':' );
1974
1975 if( parts.Count() > 0 )
1976 *token = parts[0];
1977 else
1978 *token = wxEmptyString;
1979
1980 return true;
1981 }
1982 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
1983 {
1984 wxString footprint = GetFootprintFieldText( true, aPath, false );
1985
1986 wxArrayString parts = wxSplit( footprint, ':' );
1987
1988 if( parts.Count() > 1 )
1989 *token = parts[std::min( 1, (int) parts.size() - 1 )];
1990 else
1991 *token = wxEmptyString;
1992
1993 return true;
1994 }
1995 else if( token->IsSameAs( wxT( "UNIT" ) ) )
1996 {
1997 *token = SubReference( GetUnitSelection( aPath ) );
1998 return true;
1999 }
2000 else if( token->IsSameAs( wxT( "SHORT_REFERENCE" ) ) )
2001 {
2002 *token = GetRef( aPath, false );
2003 return true;
2004 }
2005 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
2006 {
2007 *token = m_lib_id.GetUniStringLibNickname();
2008 return true;
2009 }
2010 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
2011 {
2012 *token = m_lib_id.GetUniStringLibItemName();
2013 return true;
2014 }
2015 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
2016 {
2017 *token = GetShownDescription( aDepth + 1 );
2018 return true;
2019 }
2020 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
2021 {
2022 *token = GetShownKeyWords( aDepth + 1 );
2023 return true;
2024 }
2025 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
2026 {
2027 *token = wxEmptyString;
2028
2029 if( aPath->GetExcludedFromBOM() || this->ResolveExcludedFromBOM() )
2030 *token = _( "Excluded from BOM" );
2031
2032 return true;
2033 }
2034 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
2035 {
2036 *token = wxEmptyString;
2037
2038 if( aPath->GetExcludedFromBoard() || this->ResolveExcludedFromBoard() )
2039 *token = _( "Excluded from board" );
2040
2041 return true;
2042 }
2043 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
2044 {
2045 *token = wxEmptyString;
2046
2047 if( aPath->GetExcludedFromSim() || this->ResolveExcludedFromSim() )
2048 *token = _( "Excluded from simulation" );
2049
2050 return true;
2051 }
2052 else if( token->IsSameAs( wxT( "DNP" ) ) )
2053 {
2054 *token = wxEmptyString;
2055
2056 wxString variant = aVariantName.IsEmpty() ? schematic->GetCurrentVariant() : aVariantName;
2057
2058 if( aPath->GetDNP() || this->ResolveDNP( aPath, variant ) )
2059 *token = _( "DNP" );
2060
2061 return true;
2062 }
2063 else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) ) || token->StartsWith( wxT( "NET_NAME(" ) )
2064 || token->StartsWith( wxT( "NET_CLASS(" ) ) || token->StartsWith( wxT( "PIN_NAME(" ) )
2065 || token->StartsWith( wxT( "PIN_BASE_NAME(" ) ) || token->StartsWith( wxT( "PIN_ALT_LIST(" ) )
2066 || token->StartsWith( wxT( "REFERENCE(" ) ) || token->StartsWith( wxT( "SHORT_REFERENCE(" ) )
2067 || token->StartsWith( wxT( "UNIT(" ) ) )
2068 {
2069 wxString pinNumber = token->AfterFirst( '(' );
2070 pinNumber = pinNumber.BeforeLast( ')' );
2071
2072 bool isReferenceFunction = token->StartsWith( wxT( "REFERENCE(" ) );
2073 bool isShortReferenceFunction = token->StartsWith( wxT( "SHORT_REFERENCE(" ) );
2074 bool isUnitFunction = token->StartsWith( wxT( "UNIT(" ) );
2075
2076 // First, try to find the pin in the current unit (for backward compatibility)
2077 // For REFERENCE/SHORT_REFERENCE/UNIT functions, always search all pins to find which unit the pin belongs to
2078 std::vector<const SCH_PIN*> pinsToSearch;
2079 std::vector<const SCH_PIN*> altPinsToSearch;
2080
2081 if( isReferenceFunction || isShortReferenceFunction || isUnitFunction )
2082 {
2083 for( SCH_PIN* pin : GetAllLibPins() )
2084 pinsToSearch.push_back( pin );
2085 }
2086 else
2087 {
2088 for( const SCH_PIN* pin : GetPins( aPath ) )
2089 pinsToSearch.push_back( pin );
2090
2091 for( SCH_PIN* pin : GetAllLibPins() )
2092 altPinsToSearch.push_back( pin );
2093 }
2094
2095 for( const SCH_PIN* pin : pinsToSearch )
2096 {
2097 if( pin->GetNumber() == pinNumber )
2098 {
2099 if( isReferenceFunction || isShortReferenceFunction || isUnitFunction )
2100 {
2101 int pinUnit = pin->GetUnit();
2102 wxString result;
2103
2104 if( isReferenceFunction )
2105 {
2106 // Return the full unit reference (e.g., "J601A")
2107 if( pinUnit > 0 )
2108 result = GetRef( aPath, false ) + SubReference( pinUnit, false );
2109 else
2110 result = GetRef( aPath, false );
2111 }
2112 else if( isShortReferenceFunction )
2113 {
2114 // Return the reference without unit (e.g., "J601")
2115 result = GetRef( aPath, false );
2116 }
2117 else if( isUnitFunction )
2118 {
2119 // Return only the unit letter (e.g., "A")
2120 if( pinUnit > 0 )
2121 result = SubReference( pinUnit, false );
2122 else
2123 result = wxEmptyString;
2124 }
2125
2126 *token = result;
2127 return true;
2128 }
2129 else if( token->StartsWith( wxT( "PIN_NAME" ) ) )
2130 {
2131 *token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
2132 return true;
2133 }
2134 else if( token->StartsWith( wxT( "PIN_BASE_NAME" ) ) )
2135 {
2136 *token = pin->GetBaseName();
2137 return true;
2138 }
2139 else if( token->StartsWith( wxT( "PIN_ALT_LIST" ) ) )
2140 {
2141 // Build list of alternate names only (no base name)
2142 wxString altList;
2143
2144 const std::map<wxString, SCH_PIN::ALT>& alts = pin->GetAlternates();
2145
2146 for( const auto& [altName, altDef] : alts )
2147 {
2148 if( !altList.IsEmpty() )
2149 altList += wxT( ", " );
2150 altList += altName;
2151 }
2152
2153 *token = altList;
2154 return true;
2155 }
2156
2157 SCH_CONNECTION* conn = pin->Connection( aPath );
2158
2159 if( !conn )
2160 {
2161 *token = wxEmptyString;
2162 }
2163 else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
2164 {
2165 wxString netName = conn->LocalName();
2166 if( netName.Lower().StartsWith( wxT( "unconnected" ) ) )
2167 *token = wxT( "NC" );
2168 else
2169 *token = netName;
2170 }
2171 else if( token->StartsWith( wxT( "NET_NAME" ) ) )
2172 {
2173 *token = conn->Name();
2174 }
2175 else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
2176 {
2177 *token = pin->GetEffectiveNetClass( aPath )->GetName();
2178 }
2179
2180 return true;
2181 }
2182 }
2183
2184 // If pin not found in current unit, search all units (auto-resolution)
2185 for( const SCH_PIN* pin : altPinsToSearch )
2186 {
2187 if( pin->GetNumber() == pinNumber )
2188 {
2189 // For PIN_BASE_NAME and PIN_ALT_LIST, we can use library data
2190 if( token->StartsWith( wxT( "PIN_BASE_NAME" ) ) )
2191 {
2192 *token = pin->GetBaseName();
2193 return true;
2194 }
2195 else if( token->StartsWith( wxT( "PIN_ALT_LIST" ) ) )
2196 {
2197 // Build list of alternate names only (no base name)
2198 wxString altList;
2199
2200 const std::map<wxString, SCH_PIN::ALT>& alts = pin->GetAlternates();
2201
2202 for( const auto& [altName, altDef] : alts )
2203 {
2204 if( !altList.IsEmpty() )
2205 altList += wxT( ", " );
2206 altList += altName;
2207 }
2208
2209 *token = altList;
2210 return true;
2211 }
2212
2213 // For net-related functions, find which sheet path has this pin's unit
2214 int pinUnit = pin->GetUnit();
2215
2216 // Search all sheets for a symbol with our reference and the correct unit
2217 // This is needed because each unit of a multi-unit symbol is a separate object
2218 SCH_SHEET_PATH targetPath;
2219 SCH_SYMBOL* targetSymbol = nullptr;
2220
2221 if( Schematic() )
2222 {
2223 for( const SCH_SHEET_PATH& sheetPath : Schematic()->Hierarchy() )
2224 {
2225 for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
2226 {
2227 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2228
2229 // Check if this symbol has the same reference designator and the correct unit
2230 if( symbol->GetRef( &sheetPath, false ) == GetRef( aPath, false )
2231 && symbol->GetUnitSelection( &sheetPath ) == pinUnit )
2232 {
2233 targetPath = sheetPath; // Copy the sheet path
2234 targetSymbol = symbol;
2235 break;
2236 }
2237 }
2238
2239 if( targetSymbol )
2240 break;
2241 }
2242 }
2243
2244 if( !targetSymbol )
2245 {
2246 // Unit not placed on any sheet
2247 *token = wxString::Format( wxT( "<Unit %s not placed>" ), SubReference( pinUnit, false ) );
2248 return true;
2249 }
2250
2251 // Get the pin from the actual instance symbol we found
2252 // Match by pin number, not by pointer, since the library pins are different objects
2253 SCH_PIN* instancePin = nullptr;
2254
2255 for( SCH_PIN* candidate : targetSymbol->GetPins( &targetPath ) )
2256 {
2257 if( candidate->GetNumber() == pinNumber )
2258 {
2259 instancePin = candidate;
2260 break;
2261 }
2262 }
2263
2264 if( !instancePin )
2265 {
2266 *token = wxEmptyString;
2267 return true;
2268 }
2269
2270 // PIN_NAME doesn't need connection data, just instance pin
2271 if( token->StartsWith( wxT( "PIN_NAME" ) ) )
2272 {
2273 *token = instancePin->GetAlt().IsEmpty() ? instancePin->GetName() : instancePin->GetAlt();
2274 return true;
2275 }
2276
2277 // Now get the connection from the correct sheet path
2278 SCH_CONNECTION* conn = instancePin->Connection( &targetPath );
2279
2280 if( !conn )
2281 {
2282 *token = wxEmptyString;
2283 }
2284 else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
2285 {
2286 wxString netName = conn->LocalName();
2287 if( netName.Lower().StartsWith( wxT( "unconnected" ) ) )
2288 *token = wxT( "NC" );
2289 else
2290 *token = netName;
2291 }
2292 else if( token->StartsWith( wxT( "NET_NAME" ) ) )
2293 {
2294 *token = conn->Name();
2295 }
2296 else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
2297 {
2298 *token = instancePin->GetEffectiveNetClass( &targetPath )->GetName();
2299 }
2300
2301 return true;
2302 }
2303 }
2304
2305 // If we got here, no pin was found - report unresolved
2306 *token = wxString::Format( wxT( "<Unresolved: pin %s>" ), pinNumber );
2307 return true;
2308 }
2309
2310 // See if parent can resolve it (this will recurse to ancestors)
2311 if( aPath->Last() && aPath->Last()->ResolveTextVar( aPath, token, aDepth + 1 ) )
2312 return true;
2313
2314 return false;
2315}
2316
2317
2318void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
2319{
2320 if( aSheetPath )
2321 {
2322 KIID_PATH path = aSheetPath->Path();
2323
2324 for( SCH_SYMBOL_INSTANCE& instance : m_instances )
2325 {
2326 if( instance.m_Path == path )
2327 {
2328 if( instance.m_Reference.IsEmpty() || aResetPrefix )
2329 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
2330 else
2331 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
2332 }
2333 }
2334 }
2335 else
2336 {
2337 for( SCH_SYMBOL_INSTANCE& instance : m_instances )
2338 {
2339 if( instance.m_Reference.IsEmpty() || aResetPrefix )
2340 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
2341 else
2342 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
2343 }
2344 }
2345
2346 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2347 pin->ClearDefaultNetName( aSheetPath );
2348
2349 // Only modify the REFERENCE field text when clearing ALL annotations (aSheetPath is NULL).
2350 // When clearing for a specific sheet path, we must preserve the field text because it serves
2351 // as a fallback for GetRef() when instances for other sheet paths are looked up.
2352 // See issue #20173: modifying field text here corrupts references in shared screens.
2353 if( !aSheetPath )
2354 {
2355 wxString currentReference = GetField( FIELD_T::REFERENCE )->GetText();
2356
2357 if( currentReference.IsEmpty() || aResetPrefix )
2359 else
2361 }
2362}
2363
2364
2366{
2367 // An empty sheet path is illegal, at a minimum the root sheet UUID must be present.
2368 wxCHECK( aSheetPath.size() > 0, false );
2369
2370 for( const SCH_SYMBOL_INSTANCE& instance : m_instances )
2371 {
2372 // if aSheetPath is found, nothing to do:
2373 if( instance.m_Path == aSheetPath )
2374 return false;
2375 }
2376
2377 // This entry does not exist: add it, with its last-used reference
2378 AddHierarchicalReference( aSheetPath, GetField( FIELD_T::REFERENCE )->GetText(), m_unit );
2379 return true;
2380}
2381
2382
2383void SCH_SYMBOL::SetOrientation( int aOrientation )
2384{
2385 TRANSFORM temp = TRANSFORM();
2386 bool transform = false;
2387
2388 switch( aOrientation )
2389 {
2390 case SYM_ORIENT_0:
2391 case SYM_NORMAL: // default transform matrix
2393 break;
2394
2395 case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
2396 temp.x1 = 0;
2397 temp.y1 = 1;
2398 temp.x2 = -1;
2399 temp.y2 = 0;
2400 transform = true;
2401 break;
2402
2403 case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
2404 temp.x1 = 0;
2405 temp.y1 = -1;
2406 temp.x2 = 1;
2407 temp.y2 = 0;
2408 transform = true;
2409 break;
2410
2411 case SYM_MIRROR_Y: // Mirror Y (incremental transform)
2412 temp.x1 = -1;
2413 temp.y1 = 0;
2414 temp.x2 = 0;
2415 temp.y2 = 1;
2416 transform = true;
2417 break;
2418
2419 case SYM_MIRROR_X: // Mirror X (incremental transform)
2420 temp.x1 = 1;
2421 temp.y1 = 0;
2422 temp.x2 = 0;
2423 temp.y2 = -1;
2424 transform = true;
2425 break;
2426
2427 case SYM_ORIENT_90:
2430 break;
2431
2432 case SYM_ORIENT_180:
2436 break;
2437
2438 case SYM_ORIENT_270:
2441 break;
2442
2443 case( SYM_ORIENT_0 + SYM_MIRROR_X ):
2446 break;
2447
2448 case( SYM_ORIENT_0 + SYM_MIRROR_Y ):
2451 break;
2452
2457 break;
2458
2459 case( SYM_ORIENT_90 + SYM_MIRROR_X ):
2462 break;
2463
2464 case( SYM_ORIENT_90 + SYM_MIRROR_Y ):
2467 break;
2468
2473 break;
2474
2475 case( SYM_ORIENT_180 + SYM_MIRROR_X ):
2478 break;
2479
2480 case( SYM_ORIENT_180 + SYM_MIRROR_Y ):
2483 break;
2484
2489 break;
2490
2491 case( SYM_ORIENT_270 + SYM_MIRROR_X ):
2494 break;
2495
2496 case( SYM_ORIENT_270 + SYM_MIRROR_Y ):
2499 break;
2500
2505 break;
2506
2507 default:
2508 transform = false;
2509 wxFAIL_MSG( "Invalid schematic symbol orientation type." );
2510 break;
2511 }
2512
2513 if( transform )
2514 {
2515 /* The new matrix transform is the old matrix transform modified by the
2516 * requested transformation, which is the temp transform (rot,
2517 * mirror ..) in order to have (in term of matrix transform):
2518 * transform coord = new_m_transform * coord
2519 * where transform coord is the coord modified by new_m_transform from
2520 * the initial value coord.
2521 * new_m_transform is computed (from old_m_transform and temp) to
2522 * have:
2523 * transform coord = old_m_transform * temp
2524 */
2525 TRANSFORM newTransform;
2526
2527 newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
2528 newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
2529 newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
2530 newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
2531 m_transform = newTransform;
2532 }
2533}
2534
2535
2537{
2538 /*
2539 * This is slow, but also a bizarre algorithm. I don't feel like unteasing the algorithm right
2540 * now, so let's just cache it for the moment.
2541 */
2544
2545 int rotate_values[] = { SYM_ORIENT_0,
2557
2558 // Try to find the current transform option:
2559 TRANSFORM transform = m_transform;
2560 SCH_SYMBOL temp( *this );
2561 temp.SetParentGroup( nullptr );
2562
2563 for( int type_rotate : rotate_values )
2564 {
2565 temp.SetOrientation( type_rotate );
2566
2567 if( transform == temp.GetTransform() )
2568 {
2570 return type_rotate;
2571 }
2572 }
2573
2574 // Error: orientation not found in list (should not happen)
2575 wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
2576
2577 return SYM_NORMAL;
2578}
2579
2580
2581#if defined( DEBUG )
2582
2583void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const
2584{
2585 // for now, make it look like XML:
2586 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << " ref=\""
2587 << TO_UTF8( GetField( FIELD_T::REFERENCE )->GetName() ) << '"' << " chipName=\""
2588 << GetLibId().Format().wx_str() << '"' << m_pos << " layer=\"" << m_layer << '"'
2589 << ">\n";
2590
2591 // skip the reference, it's been output already.
2592 for( int i = 1; i < (int) GetFields().size(); ++i )
2593 {
2594 const wxString& value = GetFields()[i].GetText();
2595
2596 if( !value.IsEmpty() )
2597 {
2598 NestedSpace( nestLevel + 1, os ) << "<field" << " name=\"" << TO_UTF8( GetFields()[i].GetName() ) << '"'
2599 << " value=\"" << TO_UTF8( value ) << "\"/>\n";
2600 }
2601 }
2602
2603 NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
2604}
2605
2606#endif
2607
2608
2609BOX2I SCH_SYMBOL::doGetBoundingBox( bool aIncludePins, bool aIncludeFields ) const
2610{
2611 BOX2I bBox;
2612
2613 if( m_part )
2614 bBox = m_part->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, false );
2615 else
2616 bBox = LIB_SYMBOL::GetDummy()->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, false );
2617
2618 bBox = m_transform.TransformCoordinate( bBox );
2619 bBox.Normalize();
2620
2621 bBox.Offset( m_pos );
2622
2623 if( aIncludeFields )
2624 {
2625 for( const SCH_FIELD& field : m_fields )
2626 {
2627 if( field.IsVisible() )
2628 bBox.Merge( field.GetBoundingBox() );
2629 }
2630 }
2631
2632 return bBox;
2633}
2634
2635
2637{
2638 try
2639 {
2640 return doGetBoundingBox( false, false );
2641 }
2642 catch( const boost::bad_pointer& e )
2643 {
2644 wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ), e.what() ) );
2645 return BOX2I();
2646 }
2647}
2648
2649
2651{
2652 return doGetBoundingBox( true, false );
2653}
2654
2655
2657{
2658 return doGetBoundingBox( true, true );
2659}
2660
2661
2662void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2663{
2664 wxString msg;
2665
2666 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
2667 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
2668 wxString currentVariant = Schematic() ? Schematic()->GetCurrentVariant() : wxString();
2669
2670 auto addExcludes = [&]()
2671 {
2672 wxArrayString msgs;
2673
2674 if( GetExcludedFromSim() )
2675 msgs.Add( _( "Simulation" ) );
2676
2677 if( GetExcludedFromBOM() )
2678 msgs.Add( _( "BOM" ) );
2679
2680 if( GetExcludedFromBoard() )
2681 msgs.Add( _( "Board" ) );
2682
2683 if( GetDNP( currentSheet, currentVariant ) )
2684 msgs.Add( _( "DNP" ) );
2685
2686 msg = wxJoin( msgs, '|' );
2687 msg.Replace( '|', wxS( ", " ) );
2688
2689 if( !msg.empty() )
2690 aList.emplace_back( _( "Exclude from" ), msg );
2691 };
2692
2693 // part and alias can differ if alias is not the root
2694 if( m_part )
2695 {
2696 if( m_part.get() != LIB_SYMBOL::GetDummy() )
2697 {
2698 if( m_part->IsPower() )
2699 {
2700 // Don't use GetShownText(); we want to see the variable references here
2701 aList.emplace_back( _( "Power symbol" ),
2702 KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) );
2703 }
2704 else
2705 {
2706 aList.emplace_back( _( "Reference" ), UnescapeString( GetRef( currentSheet ) ) );
2707
2708 // Don't use GetShownText(); we want to see the variable references here
2709 aList.emplace_back( _( "Value" ),
2710 KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) );
2711 addExcludes();
2712 aList.emplace_back( _( "Name" ), KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) );
2713 }
2714
2715#if 0 // Display symbol flags, for debug only
2716 aList.emplace_back( _( "flags" ), wxString::Format( "%X", GetEditFlags() ) );
2717#endif
2718
2719 if( !m_part->IsRoot() )
2720 {
2721 msg = _( "Missing parent" );
2722
2723 std::shared_ptr<LIB_SYMBOL> parent = m_part->GetParent().lock();
2724
2725 if( parent )
2726 msg = parent->GetName();
2727
2728 aList.emplace_back( _( "Derived from" ), UnescapeString( msg ) );
2729 }
2730 else if( !m_lib_id.GetLibNickname().empty() )
2731 {
2732 aList.emplace_back( _( "Library" ), m_lib_id.GetLibNickname() );
2733 }
2734 else
2735 {
2736 aList.emplace_back( _( "Library" ), _( "Undefined!!!" ) );
2737 }
2738
2739 // Display the current associated footprint, if exists.
2740 // Don't use GetShownText(); we want to see the variable references here
2741 msg = KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::FOOTPRINT )->GetText() );
2742
2743 if( msg.IsEmpty() )
2744 msg = _( "<Unknown>" );
2745
2746 aList.emplace_back( _( "Footprint" ), msg );
2747
2748 // Display description of the symbol, and keywords found in lib
2749 aList.emplace_back( _( "Description" ) + wxT( ": " ) + GetField( FIELD_T::DESCRIPTION )->GetText(),
2750 _( "Keywords" ) + wxT( ": " ) + m_part->GetKeyWords() );
2751 }
2752 }
2753 else
2754 {
2755 aList.emplace_back( _( "Reference" ), GetRef( currentSheet ) );
2756
2757 // Don't use GetShownText(); we want to see the variable references here
2758 aList.emplace_back( _( "Value" ), KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) );
2759 addExcludes();
2760 aList.emplace_back( _( "Name" ), KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) );
2761
2762 wxString libNickname = GetLibId().GetLibNickname();
2763
2764 if( libNickname.empty() )
2765 msg = _( "No library defined!" );
2766 else
2767 msg.Printf( _( "Symbol not found in %s!" ), libNickname );
2768
2769 aList.emplace_back( _( "Library" ), msg );
2770 }
2771}
2772
2773
2778
2779
2781{
2782 std::unique_ptr<LIB_SYMBOL>& libSymbolRef = GetLibSymbolRef();
2783
2784 if( !libSymbolRef )
2785 return nullptr;
2786
2788}
2789
2790
2792{
2793 int dx = m_pos.x;
2794
2796 MIRROR( m_pos.x, aCenter );
2797 dx -= m_pos.x; // dx,0 is the move vector for this transform
2798
2799 for( SCH_FIELD& field : m_fields )
2800 {
2801 // Move the fields to the new position because the symbol itself has moved.
2802 VECTOR2I pos = field.GetTextPos();
2803 pos.x -= dx;
2804 field.SetTextPos( pos );
2805 }
2806}
2807
2808
2810{
2811 int dy = m_pos.y;
2812
2814 MIRROR( m_pos.y, aCenter );
2815 dy -= m_pos.y; // 0,dy is the move vector for this transform
2816
2817 for( SCH_FIELD& field : m_fields )
2818 {
2819 // Move the fields to the new position because the symbol itself has moved.
2820 VECTOR2I pos = field.GetTextPos();
2821 pos.y -= dy;
2822 field.SetTextPos( pos );
2823 }
2824}
2825
2826
2827void SCH_SYMBOL::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
2828{
2829 VECTOR2I prev = m_pos;
2830
2831 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
2832
2834
2835 for( SCH_FIELD& field : m_fields )
2836 {
2837 // Move the fields to the new position because the symbol itself has moved.
2838 VECTOR2I pos = field.GetTextPos();
2839 pos.x -= prev.x - m_pos.x;
2840 pos.y -= prev.y - m_pos.y;
2841 field.SetTextPos( pos );
2842 }
2843}
2844
2845
2846bool SCH_SYMBOL::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
2847{
2848 if( aSearchData.searchMetadata )
2849 {
2850 if( EDA_ITEM::Matches( GetSchSymbolLibraryName(), aSearchData ) )
2851 return true;
2852
2853 if( EDA_ITEM::Matches( GetShownDescription(), aSearchData ) )
2854 return true;
2855
2856 if( EDA_ITEM::Matches( GetShownKeyWords(), aSearchData ) )
2857 return true;
2858 }
2859
2860 for( SCH_ITEM& drawItem : GetLibSymbolRef()->GetDrawItems() )
2861 {
2862 if( drawItem.Matches( aSearchData, aAuxData ) )
2863 return true;
2864 }
2865
2866 // Symbols are searchable via the child field and pin item text.
2867 return false;
2868}
2869
2870
2871void SCH_SYMBOL::GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList )
2872{
2873 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2874 {
2875 SCH_PIN* lib_pin = pin->GetLibPin();
2876
2877 if( lib_pin && lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
2878 continue;
2879
2880 DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
2881 aItemList.push_back( item );
2882 }
2883}
2884
2885
2886bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
2887 std::vector<DANGLING_END_ITEM>& aItemListByPos, const SCH_SHEET_PATH* aPath )
2888{
2889 bool changed = false;
2890
2891 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2892 {
2893 bool previousState = pin->IsDangling();
2894 pin->SetIsDangling( true );
2895
2896 VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
2897
2898 auto lower = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, pos );
2899 bool do_break = false;
2900
2901 for( auto it = lower; it < aItemListByPos.end() && it->GetPosition() == pos; it++ )
2902 {
2903 DANGLING_END_ITEM& each_item = *it;
2904
2905 // Some people like to stack pins on top of each other in a symbol to indicate
2906 // internal connection. While technically connected, it is not particularly useful
2907 // to display them that way, so skip any pins that are in the same symbol as this
2908 // one.
2909 if( each_item.GetParent() == this )
2910 continue;
2911
2912 switch( each_item.GetType() )
2913 {
2914 case PIN_END:
2915 case LABEL_END:
2916 case SHEET_LABEL_END:
2917 case WIRE_END:
2918 case NO_CONNECT_END:
2919 case JUNCTION_END:
2920 pin->SetIsDangling( false );
2921 do_break = true;
2922 break;
2923
2924 default: break;
2925 }
2926
2927 if( do_break )
2928 break;
2929 }
2930
2931 changed = ( changed || ( previousState != pin->IsDangling() ) );
2932 }
2933
2934 return changed;
2935}
2936
2937
2939{
2940 if( ( aPin == nullptr ) || ( aPin->Type() != SCH_PIN_T ) )
2941 return VECTOR2I( 0, 0 );
2942
2943 return m_transform.TransformCoordinate( aPin->GetPosition() ) + m_pos;
2944}
2945
2946
2947bool SCH_SYMBOL::HasConnectivityChanges( const SCH_ITEM* aItem, const SCH_SHEET_PATH* aInstance ) const
2948{
2949 // Do not compare to ourself.
2950 if( aItem == this )
2951 return false;
2952
2953 const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( aItem );
2954
2955 // Don't compare against a different SCH_ITEM.
2956 wxCHECK( symbol, false );
2957
2958 // The move algorithm marks any pins that are being moved without something attached
2959 // (during the move) as dangling. We always need to recheck connectivity in this case
2960 // or we will not notice changes when the user places the symbol back in the same position
2961 // it started.
2962 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2963 {
2964 if( pin->IsDangling() )
2965 return true;
2966 }
2967
2968 if( GetPosition() != symbol->GetPosition() )
2969 return true;
2970
2971 if( GetLibId() != symbol->GetLibId() )
2972 return true;
2973
2974 if( GetUnitSelection( aInstance ) != symbol->GetUnitSelection( aInstance ) )
2975 return true;
2976
2977 if( GetRef( aInstance ) != symbol->GetRef( aInstance ) )
2978 return true;
2979
2980 // Power symbol value field changes are connectivity changes.
2981 if( IsPower() && ( GetValue( true, aInstance, false ) != symbol->GetValue( true, aInstance, false ) ) )
2982 return true;
2983
2984 if( m_pins.size() != symbol->m_pins.size() )
2985 return true;
2986
2987 for( size_t i = 0; i < m_pins.size(); i++ )
2988 {
2989 if( m_pins[i]->HasConnectivityChanges( symbol->m_pins[i].get() ) )
2990 return true;
2991 }
2992
2993 return false;
2994}
2995
2996
2997std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
2998{
2999 std::vector<VECTOR2I> retval;
3000
3001 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
3002 {
3003 // Collect only pins attached to the current unit and convert.
3004 // others are not associated to this symbol instance
3005 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
3006 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle();
3007
3008 if( pin_unit > 0 && pin_unit != GetUnit() )
3009 continue;
3010
3011 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
3012 continue;
3013
3014 retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos );
3015 }
3016
3017 return retval;
3018}
3019
3020
3022{
3023 if( m_part )
3024 {
3025 // Calculate the position relative to the symbol.
3026 VECTOR2I libPosition = aPosition - m_pos;
3027
3028 return m_part->LocateDrawItem( m_unit, m_bodyStyle, aType, libPosition, m_transform );
3029 }
3030
3031 return nullptr;
3032}
3033
3034
3035wxString SCH_SYMBOL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
3036{
3037 return wxString::Format( _( "Symbol %s [%s]" ),
3039 KIUI::EllipsizeMenuText( GetLibId().GetLibItemName() ) );
3040}
3041
3042
3043INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
3044{
3045 for( KICAD_T scanType : aScanTypes )
3046 {
3047 if( scanType == SCH_LOCATE_ANY_T || ( scanType == SCH_SYMBOL_T )
3048 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
3049 {
3050 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
3051 return INSPECT_RESULT::QUIT;
3052 }
3053
3054 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
3055 {
3056 for( SCH_FIELD& field : m_fields )
3057 {
3058 if( INSPECT_RESULT::QUIT == aInspector( &field, (void*) this ) )
3059 return INSPECT_RESULT::QUIT;
3060 }
3061 }
3062
3063 if( scanType == SCH_FIELD_LOCATE_REFERENCE_T )
3064 {
3065 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::REFERENCE ), (void*) this ) )
3066 return INSPECT_RESULT::QUIT;
3067 }
3068
3069 if( scanType == SCH_FIELD_LOCATE_VALUE_T
3070 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
3071 {
3072 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::VALUE ), (void*) this ) )
3073 return INSPECT_RESULT::QUIT;
3074 }
3075
3076 if( scanType == SCH_FIELD_LOCATE_FOOTPRINT_T )
3077 {
3078 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::FOOTPRINT ), (void*) this ) )
3079 return INSPECT_RESULT::QUIT;
3080 }
3081
3082 if( scanType == SCH_FIELD_LOCATE_DATASHEET_T )
3083 {
3084 if( INSPECT_RESULT::QUIT == aInspector( GetField( FIELD_T::DATASHEET ), (void*) this ) )
3085 return INSPECT_RESULT::QUIT;
3086 }
3087
3088 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_PIN_T )
3089 {
3090 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
3091 {
3092 // Collect only pins attached to the current unit and convert.
3093 // others are not associated to this symbol instance
3094 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
3095 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle();
3096
3097 if( pin_unit > 0 && pin_unit != GetUnit() )
3098 continue;
3099
3100 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
3101 continue;
3102
3103 if( INSPECT_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
3104 return INSPECT_RESULT::QUIT;
3105 }
3106 }
3107 }
3108
3110}
3111
3112
3113bool SCH_SYMBOL::operator<( const SCH_ITEM& aItem ) const
3114{
3115 if( Type() != aItem.Type() )
3116 return Type() < aItem.Type();
3117
3118 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( &aItem );
3119
3121
3122 if( rect.GetArea() != symbol->GetBodyAndPinsBoundingBox().GetArea() )
3123 return rect.GetArea() < symbol->GetBodyAndPinsBoundingBox().GetArea();
3124
3125 if( m_pos.x != symbol->m_pos.x )
3126 return m_pos.x < symbol->m_pos.x;
3127
3128 if( m_pos.y != symbol->m_pos.y )
3129 return m_pos.y < symbol->m_pos.y;
3130
3131 return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
3132}
3133
3134
3135bool SCH_SYMBOL::operator==( const SCH_SYMBOL& aSymbol ) const
3136{
3137 std::vector<SCH_FIELD*> fields, otherFields;
3138
3139 GetFields( fields, false );
3140 aSymbol.GetFields( otherFields, false );
3141
3142 if( fields.size() != otherFields.size() )
3143 return false;
3144
3145 for( int ii = 0; ii < (int) fields.size(); ii++ )
3146 {
3147 if( fields[ii]->GetId() == FIELD_T::REFERENCE )
3148 continue;
3149
3150 if( fields[ii]->GetText().Cmp( otherFields[ii]->GetText() ) != 0 )
3151 return false;
3152 }
3153
3154 return true;
3155}
3156
3157
3158bool SCH_SYMBOL::operator!=( const SCH_SYMBOL& aSymbol ) const
3159{
3160 return !( *this == aSymbol );
3161}
3162
3163
3165{
3166 wxCHECK_MSG( Type() == aSymbol.Type(), *this,
3167 wxT( "Cannot assign object type " ) + aSymbol.GetClass() + wxT( " to type " ) + GetClass() );
3168
3169 if( &aSymbol != this )
3170 {
3171 SYMBOL::operator=( aSymbol );
3172
3173 m_lib_id = aSymbol.m_lib_id;
3174 m_part.reset( aSymbol.m_part ? new LIB_SYMBOL( *aSymbol.m_part ) : nullptr );
3175 m_pos = aSymbol.m_pos;
3176 m_unit = aSymbol.m_unit;
3177 m_bodyStyle = aSymbol.m_bodyStyle;
3178 m_transform = aSymbol.m_transform;
3179
3180 m_instances = aSymbol.m_instances;
3181
3182 m_fields = aSymbol.m_fields; // std::vector's assignment operator
3183
3184 // Reparent fields after assignment to new symbol.
3185 for( SCH_FIELD& field : m_fields )
3186 field.SetParent( this );
3187
3188 UpdatePins();
3189 }
3190
3191 return *this;
3192}
3193
3194
3195bool SCH_SYMBOL::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
3196{
3197 BOX2I bBox = GetBodyBoundingBox();
3198 bBox.Inflate( aAccuracy / 2 );
3199
3200 if( bBox.Contains( aPosition ) )
3201 return true;
3202
3203 return false;
3204}
3205
3206
3207bool SCH_SYMBOL::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
3208{
3210 return false;
3211
3212 BOX2I rect = aRect;
3213
3214 rect.Inflate( aAccuracy / 2 );
3215
3216 if( aContained )
3217 return rect.Contains( GetBodyBoundingBox() );
3218
3219 return rect.Intersects( GetBodyBoundingBox() );
3220}
3221
3222
3223bool SCH_SYMBOL::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
3224{
3226 return false;
3227
3228 return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
3229}
3230
3231
3232bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
3233{
3234 VECTOR2I new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_pos );
3235
3236 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
3237 {
3238 if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
3239 continue;
3240
3241 // Collect only pins attached to the current unit and convert.
3242 // others are not associated to this symbol instance
3243 if( pin->GetUnit() > 0 && pin->GetUnit() != GetUnit() )
3244 continue;
3245
3246 if( pin->GetBodyStyle() > 0 && pin->GetBodyStyle() != GetBodyStyle() )
3247 continue;
3248
3249 if( pin->GetLocalPosition() == new_pos )
3250 return true;
3251 }
3252
3253 return false;
3254}
3255
3256
3258{
3259 return m_isInNetlist;
3260}
3261
3262
3263void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle,
3264 const VECTOR2I& aOffset, bool aDimmed )
3265{
3266 if( aBackground )
3267 return;
3268
3269 if( m_part )
3270 {
3271 std::vector<SCH_PIN*> libPins = m_part->GetGraphicalPins( GetUnit(), GetBodyStyle() );
3272
3273 // Copy the source so we can re-orient and translate it.
3274 LIB_SYMBOL tempSymbol( *m_part );
3275 std::vector<SCH_PIN*> tempPins = tempSymbol.GetGraphicalPins( GetUnit(), GetBodyStyle() );
3276
3277 // Copy the pin info from the symbol to the temp pins
3278 for( unsigned i = 0; i < tempPins.size(); ++i )
3279 {
3280 SCH_PIN* symbolPin = GetPin( libPins[i] );
3281 SCH_PIN* tempPin = tempPins[i];
3282
3283 if( !symbolPin )
3284 continue;
3285
3286 tempPin->SetName( symbolPin->GetShownName() );
3287 tempPin->SetType( symbolPin->GetType() );
3288 tempPin->SetShape( symbolPin->GetShape() );
3289
3290 if( symbolPin->IsDangling() )
3291 tempPin->SetFlags( IS_DANGLING );
3292 }
3293
3294 for( SCH_ITEM& item : tempSymbol.GetDrawItems() )
3295 {
3296 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( &item ) )
3297 {
3298 // Use SCH_FIELD's text resolver
3299 SCH_FIELD dummy( this, FIELD_T::USER );
3300 dummy.SetText( text->GetText() );
3301 text->SetText( dummy.GetShownText( false ) );
3302 }
3303 }
3304
3305 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
3306 TRANSFORM savedTransform = renderSettings->m_Transform;
3307 renderSettings->m_Transform = GetTransform();
3308 aPlotter->StartBlock( nullptr );
3309
3310 wxString variant = Schematic()->GetCurrentVariant();
3311 SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
3312 bool dnp = GetDNP( sheet, variant );
3313
3314 for( bool local_background : { true, false } )
3315 {
3316 tempSymbol.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(), m_pos, dnp );
3317
3318 for( SCH_FIELD field : m_fields )
3319 {
3320 field.ClearRenderCache();
3321 field.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(), m_pos, dnp );
3322
3323 if( IsSymbolLikePowerLocalLabel() && field.GetId() == FIELD_T::VALUE
3324 && ( field.IsVisible() || field.IsForceVisible() ) )
3325 {
3326 PlotLocalPowerIconShape( aPlotter );
3327 }
3328 }
3329 }
3330
3331 if( dnp )
3332 PlotDNP( aPlotter );
3333
3334 // Plot attributes to a hypertext menu
3335 if( aPlotOpts.m_PDFPropertyPopups )
3336 {
3337 std::vector<wxString> properties;
3338
3339 for( const SCH_FIELD& field : GetFields() )
3340 {
3341 wxString text_field = field.GetShownText( sheet, false, 0, variant );
3342
3343 if( text_field.IsEmpty() )
3344 continue;
3345
3346 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), field.GetName(), text_field ) );
3347 }
3348
3349 if( !m_part->GetKeyWords().IsEmpty() )
3350 {
3351 properties.emplace_back(
3352 wxString::Format( wxT( "!%s = %s" ), _( "Keywords" ), m_part->GetKeyWords() ) );
3353 }
3354
3355 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
3356 }
3357
3358 aPlotter->EndBlock( nullptr );
3359 renderSettings->m_Transform = savedTransform;
3360
3361 if( !m_part->IsPower() )
3362 aPlotter->Bookmark( GetBoundingBox(), GetRef( sheet ), _( "Symbols" ) );
3363 }
3364}
3365
3366
3367void SCH_SYMBOL::PlotDNP( PLOTTER* aPlotter ) const
3368{
3369 BOX2I bbox = GetBodyBoundingBox();
3371 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
3372 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
3373 int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
3374
3375 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
3376 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
3377 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
3378
3379 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
3380 aPlotter->SetColor( renderSettings->GetLayerColor( LAYER_DNP_MARKER ) );
3381
3382 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, nullptr );
3383
3384 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
3385 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ), strokeWidth, nullptr );
3386}
3387
3388
3392static void plotLocalPowerIcon( PLOTTER* aPlotter, const VECTOR2D& aPos, double aSize, bool aRotate )
3393{
3394 double lineWidth = aSize / 10.0;
3395
3396 std::vector<SCH_SHAPE> shapeList;
3397 SCH_SYMBOL::BuildLocalPowerIconShape( shapeList, aPos, aSize, lineWidth, aRotate );
3398 int tolerance = 100; // approx error to approximate a Bezier curve by segments
3399
3400 for( const SCH_SHAPE& shape : shapeList )
3401 {
3402 // Currently there are only 2 shapes: BEZIER and CIRCLE
3403 FILL_T filled = shape.GetFillMode() == FILL_T::NO_FILL ? FILL_T::NO_FILL : FILL_T::FILLED_SHAPE;
3404
3405 if( shape.GetShape() == SHAPE_T::BEZIER )
3406 aPlotter->BezierCurve( shape.GetStart(), shape.GetBezierC1(), shape.GetBezierC2(), shape.GetEnd(),
3407 tolerance, lineWidth );
3408 else if( shape.GetShape() == SHAPE_T::CIRCLE )
3409 aPlotter->Circle( shape.getCenter(), shape.GetRadius() * 2, filled, lineWidth );
3410 }
3411}
3412
3413
3415{
3416 const SCH_FIELD* field = GetField( FIELD_T::VALUE );
3417
3418 // Plot the local power pin indicator icon shape
3419 BOX2I bbox = field->GetBoundingBox();
3420
3421 // Calculate the text orientation according to the parent orientation.
3422 EDA_ANGLE orient = field->GetTextAngle();
3423
3424 if( GetTransform().y1 )
3425 {
3426 // Rotate symbol 90 degrees.
3427 if( orient.IsHorizontal() )
3428 orient = ANGLE_VERTICAL;
3429 else
3430 orient = ANGLE_HORIZONTAL;
3431 }
3432
3433 bool rotated = !orient.IsHorizontal();
3434
3435 VECTOR2D pos;
3436 double size = bbox.GetHeight() / 1.5;
3437
3438 if( rotated )
3439 {
3440 pos = VECTOR2D( bbox.GetRight() - bbox.GetWidth() / 6.0, bbox.GetBottom() + bbox.GetWidth() / 2.0 );
3441 size = bbox.GetWidth() / 1.5;
3442 }
3443 else
3444 {
3445 pos = VECTOR2D( bbox.GetLeft() - bbox.GetHeight() / 2.0, bbox.GetBottom() - bbox.GetHeight() / 6.0 );
3446 }
3447
3448 // TODO: build and plot icon shape
3449 plotLocalPowerIcon( aPlotter, pos, size, rotated );
3450}
3451
3452
3453void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter, bool aDnp ) const
3454{
3455 if( m_part )
3456 {
3457 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
3458 TRANSFORM savedTransform = renderSettings->m_Transform;
3459 renderSettings->m_Transform = GetTransform();
3460
3461 std::vector<SCH_PIN*> libPins = m_part->GetGraphicalPins( GetUnit(), GetBodyStyle() );
3462
3463 // Copy the source to stay const
3464 LIB_SYMBOL tempSymbol( *m_part );
3465 std::vector<SCH_PIN*> tempPins = tempSymbol.GetGraphicalPins( GetUnit(), GetBodyStyle() );
3466 SCH_PLOT_OPTS plotOpts;
3467
3468 // Copy the pin info from the symbol to the temp pins
3469 for( unsigned i = 0; i < tempPins.size(); ++i )
3470 {
3471 SCH_PIN* symbolPin = GetPin( libPins[i] );
3472 SCH_PIN* tempPin = tempPins[i];
3473
3474 if( !symbolPin )
3475 continue;
3476
3477 tempPin->SetName( symbolPin->GetShownName() );
3478 tempPin->SetType( symbolPin->GetType() );
3479 tempPin->SetShape( symbolPin->GetShape() );
3480 tempPin->Plot( aPlotter, false, plotOpts, GetUnit(), GetBodyStyle(), m_pos, aDnp );
3481 }
3482
3483 renderSettings->m_Transform = savedTransform;
3484 }
3485}
3486
3487
3489{
3490 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
3491 {
3492 if( pin->IsBrightened() )
3493 return true;
3494 }
3495
3496 return false;
3497}
3498
3499
3501{
3502 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
3503 pin->ClearBrightened();
3504}
3505
3506
3507/*
3508 * When modified at the schematic level, we still store the values of these flags in the
3509 * associated m_part. If m_part now diverges from other usages, a new derived LIB_SYMBOL
3510 * will be created and stored locally in the schematic.
3511 */
3513{
3514 return m_part && m_part->GetShowPinNames();
3515}
3516
3517
3519{
3520 if( m_part )
3521 m_part->SetShowPinNames( aShow );
3522}
3523
3524
3526{
3527 return m_part && m_part->GetShowPinNumbers();
3528}
3529
3530
3532{
3533 if( m_part )
3534 m_part->SetShowPinNumbers( aShow );
3535}
3536
3537
3539{
3540 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
3541 {
3542 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
3543 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle();
3544
3545 if( pin_unit > 0 && pin_unit != GetUnit() )
3546 continue;
3547
3548 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
3549 continue;
3550
3551 if( pin->IsPointClickableAnchor( aPos ) )
3552 return true;
3553 }
3554
3555 return false;
3556}
3557
3558
3560{
3561 // return true if the symbol is equivalent to a global label:
3562 // It is a Power symbol
3563 // It has only one pin type Power input
3564
3566 return false;
3567
3568 std::vector<SCH_PIN*> pin_list = GetAllLibPins();
3569
3570 if( pin_list.size() != 1 )
3571 return false;
3572
3573 return pin_list[0]->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN;
3574}
3575
3576
3578{
3579 // return true if the symbol is equivalent to a local label:
3580 // It is a Power symbol
3581 // It has only one pin type Power input
3582
3584 return false;
3585
3586 std::vector<SCH_PIN*> pin_list = GetAllLibPins();
3587
3588 if( pin_list.size() != 1 )
3589 return false;
3590
3591 return pin_list[0]->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN;
3592}
3593
3594
3596{
3597 if( !m_part )
3598 return false;
3599
3600 return m_part->IsLocalPower();
3601}
3602
3603
3605{
3606 if( !m_part )
3607 return false;
3608
3609 return m_part->IsGlobalPower();
3610}
3611
3612
3614{
3615 return IsLocalPower() || IsGlobalPower();
3616}
3617
3618
3620{
3621 wxCHECK( m_part, false );
3622
3623 return m_part->IsNormal();
3624}
3625
3626
3627std::unordered_set<wxString> SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const
3628{
3629 std::unordered_set<wxString> componentClass;
3630
3631 auto getComponentClassFields = [&]( const std::vector<SCH_FIELD>& fields )
3632 {
3633 for( const SCH_FIELD& field : fields )
3634 {
3635 if( field.GetCanonicalName() == wxT( "Component Class" ) )
3636 {
3637 if( field.GetShownText( aPath, false ) != wxEmptyString )
3638 componentClass.insert( field.GetShownText( aPath, false ) );
3639 }
3640 }
3641 };
3642
3643 // First get component classes set on the symbol itself
3644 getComponentClassFields( m_fields );
3645
3646 // Now get component classes set on any enclosing rule areas
3647 for( const SCH_RULE_AREA* ruleArea : m_rule_areas_cache )
3648 {
3649 for( const SCH_DIRECTIVE_LABEL* label : ruleArea->GetDirectives() )
3650 {
3651 getComponentClassFields( label->GetFields() );
3652 }
3653 }
3654
3655 return componentClass;
3656}
3657
3658
3659std::optional<SCH_SYMBOL_VARIANT> SCH_SYMBOL::GetVariant( const SCH_SHEET_PATH& aInstance,
3660 const wxString& aVariantName ) const
3661{
3662 SCH_SYMBOL_INSTANCE instance;
3663
3664 if( !GetInstance( instance, aInstance.Path() ) || !instance.m_Variants.contains( aVariantName ) )
3665 return std::nullopt;
3666
3667 return instance.m_Variants.find( aVariantName )->second;
3668}
3669
3670
3671void SCH_SYMBOL::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SYMBOL_VARIANT& aVariant )
3672{
3673 SCH_SYMBOL_INSTANCE* instance = getInstance( aInstance );
3674
3675 // The instance path must already exist.
3676 if( !instance )
3677 return;
3678
3679 instance->m_Variants.insert( std::make_pair( aVariant.m_Name, aVariant ) );
3680}
3681
3682
3683void SCH_SYMBOL::DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantName )
3684{
3685 SCH_SYMBOL_INSTANCE* instance = getInstance( aPath );
3686
3687 // The instance path must already exist.
3688 if( !instance || !instance->m_Variants.contains( aVariantName ) )
3689 return;
3690
3691 instance->m_Variants.erase( aVariantName );
3692}
3693
3694
3695void SCH_SYMBOL::RenameVariant( const KIID_PATH& aPath, const wxString& aOldName,
3696 const wxString& aNewName )
3697{
3698 SCH_SYMBOL_INSTANCE* instance = getInstance( aPath );
3699
3700 // The instance path must already exist and contain the old variant.
3701 if( !instance || !instance->m_Variants.contains( aOldName ) )
3702 return;
3703
3704 // Get the variant data, update the name, and re-insert with new key
3705 SCH_SYMBOL_VARIANT variant = instance->m_Variants[aOldName];
3706 variant.m_Name = aNewName;
3707 instance->m_Variants.erase( aOldName );
3708 instance->m_Variants.insert( std::make_pair( aNewName, variant ) );
3709}
3710
3711
3712void SCH_SYMBOL::CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
3713 const wxString& aNewVariant )
3714{
3715 SCH_SYMBOL_INSTANCE* instance = getInstance( aPath );
3716
3717 // The instance path must already exist and contain the source variant.
3718 if( !instance || !instance->m_Variants.contains( aSourceVariant ) )
3719 return;
3720
3721 // Copy the variant data with a new name
3722 SCH_SYMBOL_VARIANT variant = instance->m_Variants[aSourceVariant];
3723 variant.m_Name = aNewVariant;
3724 instance->m_Variants.insert( std::make_pair( aNewVariant, variant ) );
3725}
3726
3727
3728bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
3729{
3730 if( Type() != aOther.Type() )
3731 return false;
3732
3733 const SCH_SYMBOL& symbol = static_cast<const SCH_SYMBOL&>( aOther );
3734
3735 if( GetLibId() != symbol.GetLibId() )
3736 return false;
3737
3738 if( GetPosition() != symbol.GetPosition() )
3739 return false;
3740
3741 if( GetUnit() != symbol.GetUnit() )
3742 return false;
3743
3744 if( GetBodyStyle() != symbol.GetBodyStyle() )
3745 return false;
3746
3747 if( GetTransform() != symbol.GetTransform() )
3748 return false;
3749
3750 if( GetFields() != symbol.GetFields() )
3751 return false;
3752
3753 if( m_pins.size() != symbol.m_pins.size() )
3754 return false;
3755
3756 if( m_excludedFromSim != symbol.m_excludedFromSim )
3757 return false;
3758
3759 if( m_excludedFromBOM != symbol.m_excludedFromBOM )
3760 return false;
3761
3762 if( m_DNP != symbol.m_DNP )
3763 return false;
3764
3766 return false;
3767
3769 return false;
3770
3771 for( unsigned i = 0; i < m_pins.size(); ++i )
3772 {
3773 if( *m_pins[i] != *symbol.m_pins[i] )
3774 return false;
3775 }
3776
3777#if 0
3778 // This has historically been a compare of the current instance, rather than a compare
3779 // of all instances. Probably better to keep it that way for now.
3780 if( m_instanceReferences != symbol.m_instanceReferences )
3781 return false;
3782#endif
3783
3784 return true;
3785}
3786
3787
3788double SCH_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
3789{
3790 if( Type() != aOther.Type() )
3791 return 0.0;
3792
3793 const SCH_SYMBOL& symbol = static_cast<const SCH_SYMBOL&>( aOther );
3794
3795 if( GetLibId() != symbol.GetLibId() )
3796 return 0.0;
3797
3798 if( GetPosition() == symbol.GetPosition() )
3799 return 1.0;
3800
3801 return 0.0;
3802}
3803
3804
3805void SCH_SYMBOL::BuildLocalPowerIconShape( std::vector<SCH_SHAPE>& aShapeList, const VECTOR2D& aPos, double aSize,
3806 double aLineWidth, bool aHorizontal )
3807{
3808 SCH_LAYER_ID layer = LAYER_DEVICE; //dummy param
3809
3810 double x_right = aSize / 1.6180339887;
3811 double x_middle = x_right / 2.0;
3812
3813 VECTOR2D bottomPt = VECTOR2D{ x_middle, 0 };
3814 VECTOR2D leftPt = VECTOR2D{ 0, 2.0 * -aSize / 3.0 };
3815 VECTOR2D rightPt = VECTOR2D{ x_right, 2.0 * -aSize / 3.0 };
3816
3817 VECTOR2D bottomAnchorPt = VECTOR2D{ x_middle, -aSize / 4.0 };
3818 VECTOR2D leftSideAnchorPt1 = VECTOR2D{ 0, -aSize / 2.5 };
3819 VECTOR2D leftSideAnchorPt2 = VECTOR2D{ 0, -aSize * 1.15 };
3820 VECTOR2D rightSideAnchorPt1 = VECTOR2D{ x_right, -aSize / 2.5 };
3821 VECTOR2D rightSideAnchorPt2 = VECTOR2D{ x_right, -aSize * 1.15 };
3822
3823 aShapeList.emplace_back( SHAPE_T::BEZIER, layer, aLineWidth, FILL_T::NO_FILL );
3824 aShapeList.back().SetStart( bottomPt );
3825 aShapeList.back().SetBezierC1( bottomAnchorPt );
3826 aShapeList.back().SetBezierC2( leftSideAnchorPt1 );
3827 aShapeList.back().SetEnd( leftPt );
3828
3829
3830 aShapeList.emplace_back( SHAPE_T::BEZIER, layer, aLineWidth, FILL_T::NO_FILL );
3831 aShapeList.back().SetStart( leftPt );
3832 aShapeList.back().SetBezierC1( leftSideAnchorPt2 );
3833 aShapeList.back().SetBezierC2( rightSideAnchorPt2 );
3834 aShapeList.back().SetEnd( rightPt );
3835
3836 aShapeList.emplace_back( SHAPE_T::BEZIER, layer, aLineWidth, FILL_T::NO_FILL );
3837 aShapeList.back().SetStart( rightPt );
3838 aShapeList.back().SetBezierC1( rightSideAnchorPt1 );
3839 aShapeList.back().SetBezierC2( bottomAnchorPt );
3840 aShapeList.back().SetEnd( bottomPt );
3841
3842 aShapeList.emplace_back( SHAPE_T::CIRCLE, layer, 0, FILL_T::FILLED_SHAPE );
3843 aShapeList.back().SetCenter( ( leftPt + rightPt ) / 2.0 );
3844 aShapeList.back().SetRadius( aSize / 15.0 );
3845
3846 for( SCH_SHAPE& shape : aShapeList )
3847 {
3848 if( aHorizontal )
3849 shape.Rotate( VECTOR2I( 0, 0 ), true );
3850
3851 shape.Move( aPos );
3852 }
3853}
3854
3855
3857{
3858 for( SCH_SYMBOL_INSTANCE& instance : m_instances )
3859 {
3860 if( instance.m_Path == aSheetPath )
3861 return &instance;
3862 }
3863
3864 return nullptr;
3865}
3866
3867
3869{
3870 for( const SCH_SYMBOL_INSTANCE& instance : m_instances )
3871 {
3872 if( instance.m_Path == aSheetPath )
3873 return &instance;
3874 }
3875
3876 return nullptr;
3877}
3878
3879
3880static struct SCH_SYMBOL_DESC
3881{
3883 {
3885 .Map( SYMBOL_ANGLE_0, wxS( "0" ) )
3886 .Map( SYMBOL_ANGLE_90, wxS( "90" ) )
3887 .Map( SYMBOL_ANGLE_180, wxS( "180" ) )
3888 .Map( SYMBOL_ANGLE_270, wxS( "270" ) );
3889
3893
3900
3907
3908 auto hasLibPart = []( INSPECTABLE* aItem ) -> bool
3909 {
3910 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3911 return symbol->GetLibSymbolRef() != nullptr;
3912
3913 return false;
3914 };
3915
3916 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Pin numbers" ), &SYMBOL::SetShowPinNumbers,
3918 .SetAvailableFunc( hasLibPart );
3919
3920 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Pin names" ), &SYMBOL::SetShowPinNames,
3922 .SetAvailableFunc( hasLibPart );
3923
3924 const wxString groupFields = _HKI( "Fields" );
3925
3928 groupFields );
3931 groupFields );
3932 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Library Link" ),
3933 NO_SETTER( SCH_SYMBOL, wxString ),
3935 groupFields );
3936 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Library Description" ),
3937 NO_SETTER( SCH_SYMBOL, wxString ),
3939 groupFields );
3940 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Keywords" ), NO_SETTER( SCH_SYMBOL, wxString ),
3942 groupFields );
3943
3944 auto multiUnit = [=]( INSPECTABLE* aItem ) -> bool
3945 {
3946 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3947 return symbol->IsMultiUnit();
3948
3949 return false;
3950 };
3951
3952 auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool
3953 {
3954 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3955 return symbol->IsMultiBodyStyle();
3956
3957 return false;
3958 };
3959
3962 .SetAvailableFunc( multiUnit )
3964 []( INSPECTABLE* aItem )
3965 {
3966 wxPGChoices choices;
3967
3968 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3969 {
3970 for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
3971 choices.Add( symbol->GetUnitDisplayName( ii, false ), ii );
3972 }
3973
3974 return choices;
3975 } );
3976
3979 .SetAvailableFunc( multiBodyStyle )
3981 []( INSPECTABLE* aItem )
3982 {
3983 wxPGChoices choices;
3984
3985 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3986 {
3987 for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ )
3988 choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
3989 }
3990
3991 return choices;
3992 } );
3993
3994 const wxString groupAttributes = _HKI( "Attributes" );
3995
3996 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Simulation" ),
3999 groupAttributes );
4000 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Bill of Materials" ),
4003 groupAttributes );
4004 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Board" ),
4007 groupAttributes );
4008 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude From Position Files" ),
4011 groupAttributes );
4012 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Do not Populate" ),
4015 groupAttributes );
4016 }
4018
4019
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 coord_type GetLeft() const
Definition box2.h:228
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr coord_type GetRight() const
Definition box2.h:217
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
constexpr coord_type GetBottom() const
Definition box2.h:222
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:939
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition sch_item.h:97
DANGLING_END_T GetType() const
Definition sch_item.h:133
const EDA_ITEM * GetParent() const
Definition sch_item.h:132
bool IsHorizontal() const
Definition eda_angle.h:142
The base class for create windows for drawing purpose.
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:154
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:148
const KIID m_Uuid
Definition eda_item.h:522
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:533
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:407
virtual void SetParentGroup(EDA_GROUP *aGroup)
Definition eda_item.h:116
bool IsSelected() const
Definition eda_item.h:128
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:534
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:41
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:147
void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:590
void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:608
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:38
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxString AsString() const
Definition kiid.cpp:365
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
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition lib_symbol.h:202
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:712
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.
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Definition netclass.cpp:328
A singleton reporter that reports to nowhere.
Definition reporter.h:216
Base plotter engine class.
Definition plotter.h:136
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width)=0
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition plotter.h:528
virtual void BezierCurve(const VECTOR2I &aStart, const VECTOR2I &aControl1, const VECTOR2I &aControl2, const VECTOR2I &aEnd, int aTolerance, int aLineThickness)
Generic fallback: Cubic Bezier curve rendered as a polyline.
Definition plotter.cpp:232
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition plotter.h:590
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:540
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:517
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:599
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
wxString GetCurrentVariant() const
Return the current variant being edited.
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:187
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
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:116
FIELD_T GetId() const
Definition sch_field.h:120
void ImportValues(const SCH_FIELD &aSource)
Copy parameters from a SCH_FIELD source.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetText(const wxString &aText) override
int m_unit
Definition sch_item.h:779
int m_bodyStyle
Definition sch_item.h:780
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:727
void SetPrivate(bool aPrivate)
Definition sch_item.h:253
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:254
int GetBodyStyle() const
Definition sch_item.h:248
friend class LIB_SYMBOL
Definition sch_item.h:798
int GetUnit() const
Definition sch_item.h:239
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:509
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:782
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:795
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:56
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:473
SCH_LAYER_ID m_layer
Definition sch_item.h:778
ALT GetAlt(const wxString &aAlt)
Definition sch_pin.h:174
void SetName(const wxString &aName)
Definition sch_pin.cpp:423
const wxString & GetName() const
Definition sch_pin.cpp:405
bool IsDangling() const override
Definition sch_pin.cpp:465
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:1352
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition sch_pin.h:96
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:258
const wxString & GetShownName() const
Definition sch_pin.cpp:581
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:335
const wxString & GetNumber() const
Definition sch_pin.h:124
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:280
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:315
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool GetExcludedFromBOM() const
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
bool GetExcludedFromSim() const
bool GetExcludedFromBoard() const
bool GetDNP() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
size_t size() const
Forwarded method from std::vector.
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:76
wxString GetUnitDisplayName(int aUnit, bool aLabel) const override
Return the display name for a given unit aUnit.
SCH_SYMBOL & operator=(const SCH_SYMBOL &aItem)
int GetUnitProp() const
Definition sch_symbol.h:518
size_t GetFullPinCount() const
std::vector< SCH_SYMBOL_INSTANCE > m_instances
Define the hierarchical path and reference of the symbol.
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.
wxString GetDescription() const override
std::unordered_map< SCH_PIN *, SCH_PIN * > m_pinMap
Library pin pointer : SCH_PIN indices.
void SetMirrorX(bool aMirror)
Definition sch_symbol.h:322
bool IsSymbolLikePowerGlobalLabel() const
VECTOR2I m_pos
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:167
LIB_ID m_lib_id
Name and library the symbol was loaded from, i.e. 74xx:74LS00.
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:452
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:535
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:305
int GetY() const
Definition sch_symbol.h:873
SCH_SYMBOL_INSTANCE * getInstance(const KIID_PATH &aPath)
wxString SubReference(int aUnit, bool aAddSeparator=true) const
wxString GetClass() const override
Return the class name.
Definition sch_symbol.h:115
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
void SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
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:339
void SetBodyStyleProp(const wxString &aBodyStyle) override
Definition sch_symbol.h:540
int GetX() const
Definition sch_symbol.h:870
std::vector< SCH_PIN * > GetPins() const override
bool GetExcludedFromPosFilesProp() const
Definition sch_symbol.h:767
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
wxString GetFieldText(const wxString &aFieldName, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString) const
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:742
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
wxString GetShownKeyWords(int aDepth=0) const override
bool IsInNetlist() const
std::optional< SCH_SYMBOL_VARIANT > GetVariant(const SCH_SHEET_PATH &aInstance, const wxString &aVariantName) const
bool GetExcludedFromBoardProp() const
Definition sch_symbol.h:752
void ClearBrightenedPins()
void SetY(int aY)
Definition sch_symbol.h:874
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.
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
bool GetExcludedFromSimProp() const
Definition sch_symbol.h:737
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:334
wxString GetRefProp() const
Definition sch_symbol.h:504
wxString GetBodyStyleDescription(int aBodyStyle, bool aLabel) const override
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instances), if this entry does not already exist.
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:727
static std::unordered_map< TRANSFORM, int > s_transformToOrientationCache
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
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.
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, const wxString &aVariantName=wxEmptyString) const override
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void RenameVariant(const KIID_PATH &aPath, const wxString &aOldName, const wxString &aNewName)
void SetOrientationProp(SYMBOL_ORIENTATION_PROP aAngle)
Orientation/mirroring access for property manager.
Definition sch_symbol.h:296
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.
bool HasDeMorganBodyStyles() const override
std::vector< SCH_FIELD > m_fields
Variable length list of fields.
std::vector< SCH_PIN * > GetAllLibPins() const
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, const wxString &aVariantName=wxEmptyString) 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:712
void PlotPins(PLOTTER *aPlotter, bool aDnp) const
Plot just the symbol pins.
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:867
std::unique_ptr< LIB_SYMBOL > m_part
A flattened copy of the LIB_SYMBOL from the PROJECT object's libraries.
int GetNextFieldOrdinal() const
Return the next ordinal for a user field for this symbol.
void SetExcludedFromPosFiles(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
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 SyncOtherUnits(const SCH_SHEET_PATH &aSourceSheet, SCH_COMMIT &aCommit, PROPERTY_BASE *aProperty, const wxString &aVariantName=wxEmptyString)
Keep fields other than the reference, include/exclude flags, and alternate pin assignments in sync in...
void Init(const VECTOR2I &pos=VECTOR2I(0, 0))
void SetExcludedFromPosFilesProp(bool aEnable)
Definition sch_symbol.h:772
wxString GetShownDescription(int aDepth=0) const override
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
bool operator<(const SCH_ITEM &aItem) const override
static void BuildLocalPowerIconShape(std::vector< SCH_SHAPE > &aShapeList, const VECTOR2D &aPos, double aSize, double aLineWidth, bool aHorizontal)
Build the local power pin indicator icon shape, at coordinate aPos.
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
void SetValueProp(const wxString &aValue)
void SetUnitProp(int aUnit)
Definition sch_symbol.h:529
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
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 GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
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:351
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
void SetDNPProp(bool aEnable)
Definition sch_symbol.h:714
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
std::vector< SCH_PIN * > GetPinsByNumber(const wxString &aNumber) const
Find all symbol pins with the given number.
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:871
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.
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:511
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:239
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:722
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
void SetExcludedFromBoardProp(bool aEnable)
Definition sch_symbol.h:757
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.
void PlotLocalPowerIconShape(PLOTTER *aPlotter) const
Plot the local power pin indicator icon shape.
bool IsNormal() const override
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:184
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.
void DeleteVariant(const KIID_PATH &aPath, const wxString &aVariantName)
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
void SetExcludedFromBoard(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void CopyVariant(const KIID_PATH &aPath, const wxString &aSourceVariant, const wxString &aNewVariant)
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
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:278
bool m_excludedFromPosFiles
Definition symbol.h:277
SYMBOL(KICAD_T idType)
Definition symbol.h:65
bool m_excludedFromSim
Definition symbol.h:274
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition symbol.h:174
const TRANSFORM & GetTransform() const
Definition symbol.h:247
virtual void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition symbol.h:168
bool m_excludedFromBOM
Definition symbol.h:275
bool m_excludedFromBoard
Definition symbol.h:276
virtual bool GetShowPinNames() const
Definition symbol.h:169
SYMBOL & operator=(const SYMBOL &aItem)
Definition symbol.h:93
virtual bool GetShowPinNumbers() const
Definition symbol.h:175
TRANSFORM m_transform
The rotation/mirror transformation.
Definition symbol.h:267
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
std::map< wxString, wxString > m_Fields
bool m_ExcludedFromPosFiles
bool m_ExcludedFromSim
bool m_ExcludedFromBoard
#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_VERTICAL
Definition eda_angle.h:408
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:407
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
RECURSE_MODE
Definition eda_item.h:51
INSPECT_RESULT
Definition eda_item.h:45
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:92
#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
FILL_T
Definition eda_shape.h:56
@ NO_FILL
Definition eda_shape.h:57
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:58
a few functions useful in geometry calculations.
const wxChar *const traceSchSymbolRef
Flag to enable debug output of schematic symbol reference resolution.
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:365
int NextFieldOrdinal(const std::vector< SCH_FIELD > &aFields)
Definition sch_field.h:354
@ NO_CONNECT_END
Definition sch_item.h:88
@ SHEET_LABEL_END
Definition sch_item.h:87
@ LABEL_END
Definition sch_item.h:84
@ JUNCTION_END
Definition sch_item.h:82
@ PIN_END
Definition sch_item.h:83
@ WIRE_END
Definition sch_item.h:80
@ BASE
Definition sch_item.h:60
std::string toUTFTildaText(const wxString &txt)
Convert a wxString to UTF8 and replace any control characters with a ~, where a control character is ...
static void plotLocalPowerIcon(PLOTTER *aPlotter, const VECTOR2D &aPos, double aSize, bool aRotate)
plot a local power pin indicator icon.
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:89
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)
std::string path
KIBIS_MODEL * model
KIBIS_PIN * pin
wxString result
Test unit parsing edge cases and error handling.
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