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