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