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