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(),
535 pins.GetEnd().y - bbox.GetEnd().y ) );
536
537 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
538 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
539 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
540
541 GRFilledSegment( DC, bbox.GetOrigin(), bbox.GetEnd(),
543 dnp_color );
544
545 GRFilledSegment( DC, bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
546 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
548 dnp_color );
549 }
550}
551
552
554 const KIID_PATH& aSheetPath, bool aTestFromEnd ) const
555{
556 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
557 {
558 if( !aTestFromEnd )
559 {
560 if( instance.m_Path == aSheetPath )
561 {
562 aInstance = instance;
563 return true;
564 }
565 }
566 else if( instance.m_Path.EndsWith( aSheetPath ) )
567 {
568 aInstance = instance;
569 return true;
570 }
571 }
572
573 return false;
574}
575
576
577void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
578{
579 RemoveInstance( aInstancePath.Path() );
580}
581
582
583void SCH_SYMBOL::RemoveInstance( const KIID_PATH& aInstancePath )
584{
585 // Search for an existing path and remove it if found (should not occur)
586 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
587 {
588 if( m_instanceReferences[ii].m_Path == aInstancePath )
589 {
590 wxLogTrace( traceSchSheetPaths, wxS( "Removing symbol instance:\n"
591 " sheet path %s\n"
592 " reference %s, unit %d from symbol %s." ),
593 aInstancePath.AsString(),
594 m_instanceReferences[ii].m_Reference,
595 m_instanceReferences[ii].m_Unit,
596 m_Uuid.AsString() );
597
598 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
599 ii--;
600 }
601 }
602}
603
604
605void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef, int aUnit )
606{
607 // Search for an existing path and remove it if found (should not occur)
608 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
609 {
610 if( m_instanceReferences[ii].m_Path == aPath )
611 {
612 wxLogTrace( traceSchSheetPaths, wxS( "Removing symbol instance:\n"
613 " sheet path %s\n"
614 " reference %s, unit %d from symbol %s." ),
615 aPath.AsString(),
616 m_instanceReferences[ii].m_Reference,
617 m_instanceReferences[ii].m_Unit,
618 m_Uuid.AsString() );
619
620 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
621 ii--;
622 }
623 }
624
625 SCH_SYMBOL_INSTANCE instance;
626 instance.m_Path = aPath;
627 instance.m_Reference = aRef;
628 instance.m_Unit = aUnit;
629
630 wxLogTrace( traceSchSheetPaths, wxS( "Adding symbol '%s' instance:\n"
631 " sheet path '%s'\n"
632 " reference '%s'\n"
633 " unit %d\n" ),
635 aPath.AsString(),
636 aRef,
637 aUnit );
638
639 m_instanceReferences.push_back( instance );
640
641 // This should set the default instance to the first saved instance data for each symbol
642 // when importing sheets.
643 if( m_instanceReferences.size() == 1 )
644 {
645 m_fields[ REFERENCE_FIELD ].SetText( aRef );
646 m_unit = aUnit;
647 }
648}
649
650
652{
653 KIID_PATH searchPath( aInstance.m_Path );
654
655 std::vector<SCH_SYMBOL_INSTANCE>::iterator resultIt;
656
657 do
658 {
659 resultIt = std::find_if( m_instanceReferences.begin(), m_instanceReferences.end(),
660 [searchPath]( const auto& it )
661 {
662 return it.m_Path == searchPath;
663 } );
664
665 if( resultIt != m_instanceReferences.end() )
666 {
667 wxLogTrace( traceSchSheetPaths, wxS( "Removing symbol instance:\n"
668 " sheet path %s\n"
669 " reference %s, unit %d from symbol %s." ),
670 aInstance.m_Path.AsString(),
671 resultIt->m_Reference,
672 resultIt->m_Unit,
673 m_Uuid.AsString() );
674
675 // Instance data should be unique by path. Double check just in case there was
676 // some buggy code in the past.
677 resultIt = m_instanceReferences.erase( resultIt );
678 }
679 }
680 while( resultIt != m_instanceReferences.end() );
681
682 SCH_SYMBOL_INSTANCE instance = aInstance;
683
684 wxLogTrace( traceSchSheetPaths, wxS( "Adding symbol '%s' instance:\n"
685 " sheet path '%s'\n"
686 " reference '%s'\n"
687 " unit %d\n" ),
689 instance.m_Path.AsString(),
690 instance.m_Reference,
691 instance.m_Unit );
692
693 m_instanceReferences.push_back( instance );
694
695 // This should set the default instance to the first saved instance data for each symbol
696 // when importing sheets.
697 if( m_instanceReferences.size() == 1 )
698 {
699 m_fields[ REFERENCE_FIELD ].SetText( instance.m_Reference );
700 m_unit = instance.m_Unit;
701 }
702}
703
704
705const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
706{
707 KIID_PATH path = sheet->Path();
708 wxString ref;
709 wxString subRef;
710
711 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
712 {
713 if( instance.m_Path == path )
714 {
715 ref = instance.m_Reference;
716 subRef = SubReference( instance.m_Unit );
717 break;
718 }
719 }
720
721 // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
722 // use this as a default for this path. This will happen if we load a version 1 schematic
723 // file. It will also mean that multiple instances of the same sheet by default all have
724 // the same symbol references, but perhaps this is best.
725 if( ref.IsEmpty() && !GetField( REFERENCE_FIELD )->GetText().IsEmpty() )
726 ref = GetField( REFERENCE_FIELD )->GetText();
727
728 if( ref.IsEmpty() )
730
731 if( aIncludeUnit && GetUnitCount() > 1 )
732 ref += subRef;
733
734 return ref;
735}
736
737
738void SCH_SYMBOL::SetRefProp( const wxString& aRef )
739{
740 FIELD_VALIDATOR validator( REFERENCE_FIELD );
741
742 if( validator.DoValidate( aRef, nullptr ) )
743 SetRef( &Schematic()->CurrentSheet(), aRef );
744}
745
746
747void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
748{
749 KIID_PATH path = sheet->Path();
750 bool found = false;
751
752 // check to see if it is already there before inserting it
754 {
755 if( instance.m_Path == path )
756 {
757 found = true;
758 instance.m_Reference = ref;
759 break;
760 }
761 }
762
763 if( !found )
765
766 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
767 pin->ClearDefaultNetName( sheet );
768
769 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
770 m_fields[ REFERENCE_FIELD ].SetText( ref );
771
772 // Reinit the m_prefix member if needed
774
775 if( m_prefix.IsEmpty() )
776 m_prefix = wxT( "U" );
777
778 // Power symbols have references starting with # and are not included in netlists
779 m_isInNetlist = ! ref.StartsWith( wxT( "#" ) );
780}
781
782
783bool SCH_SYMBOL::IsAnnotated( const SCH_SHEET_PATH* aSheet ) const
784{
785 KIID_PATH path = aSheet->Path();
786
787 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
788 {
789 if( instance.m_Path == path )
790 return instance.m_Reference.Last() != '?';
791 }
792
793 return false;
794}
795
796
798{
799 wxString refDesignator = GetField( REFERENCE_FIELD )->GetText();
800
801 refDesignator.Replace( "~", " " );
802
803 wxString prefix = refDesignator;
804
805 while( prefix.Length() )
806 {
807 wxUniCharRef last = prefix.Last();
808
809 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
810 prefix.RemoveLast();
811 else
812 break;
813 }
814
815 // Avoid a prefix containing trailing/leading spaces
816 prefix.Trim( true );
817 prefix.Trim( false );
818
819 if( !prefix.IsEmpty() )
820 SetPrefix( prefix );
821}
822
823
824wxString SCH_SYMBOL::SubReference( int aUnit, bool aAddSeparator ) const
825{
826 if( SCHEMATIC* schematic = Schematic() )
827 return schematic->Settings().SubReference( aUnit, aAddSeparator );
828
829 return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
830}
831
832
834{
835 KIID_PATH path = aSheet->Path();
836
837 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
838 {
839 if( instance.m_Path == path )
840 return instance.m_Unit;
841 }
842
843 // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
844 // version 1 schematic file.
845 return m_unit;
846}
847
848
849void SCH_SYMBOL::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
850{
851 KIID_PATH path = aSheet->Path();
852
853 // check to see if it is already there before inserting it
855 {
856 if( instance.m_Path == path )
857 {
858 instance.m_Unit = aUnitSelection;
859 return;
860 }
861 }
862
863 // didn't find it; better add it
865}
866
867
868void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
869{
871 instance.m_Unit = aUnitSelection;
872}
873
874
875const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aPath,
876 bool aAllowExtraText ) const
877{
878 if( aResolve )
879 return GetField( VALUE_FIELD )->GetShownText( aPath, aAllowExtraText );
880
881 return GetField( VALUE_FIELD )->GetText();
882}
883
884
885void SCH_SYMBOL::SetValueFieldText( const wxString& aValue )
886{
887 m_fields[ VALUE_FIELD ].SetText( aValue );
888}
889
890
891const wxString SCH_SYMBOL::GetFootprintFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
892 bool aAllowExtraText ) const
893{
894 if( aResolve )
895 return GetField( FOOTPRINT_FIELD )->GetShownText( aPath, aAllowExtraText );
896
897 return GetField( FOOTPRINT_FIELD )->GetText();
898}
899
900
901void SCH_SYMBOL::SetFootprintFieldText( const wxString& aFootprint )
902{
903 m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
904}
905
906
908{
909 return &m_fields[aFieldType];
910}
911
912
914{
915 return &m_fields[aFieldType];
916}
917
918
920{
921 for( SCH_FIELD& field : m_fields )
922 {
923 if( field.GetId() == aFieldId )
924 return &field;
925 }
926
927 return nullptr;
928}
929
930
931SCH_FIELD* SCH_SYMBOL::GetFieldByName( const wxString& aFieldName )
932{
933 for( SCH_FIELD& field : m_fields )
934 {
935 if( field.GetName() == aFieldName )
936 return &field;
937 }
938
939 return nullptr;
940}
941
942
943const SCH_FIELD* SCH_SYMBOL::GetFieldByName( const wxString& aFieldName ) const
944{
945 for( const SCH_FIELD& field : m_fields )
946 {
947 if( field.GetName() == aFieldName )
948 return &field;
949 }
950
951 return nullptr;
952}
953
954
955void SCH_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
956{
957 for( SCH_FIELD& field : m_fields )
958 {
959 if( aVisibleOnly )
960 {
961 if( !field.IsVisible() || field.GetText().IsEmpty() )
962 continue;
963 }
964
965 aVector.push_back( &field );
966 }
967}
968
969
971{
972 m_fields.push_back( aField );
973 return &m_fields.back();
974}
975
976
977void SCH_SYMBOL::RemoveField( const wxString& aFieldName )
978{
979 for( unsigned ii = 0; ii < m_fields.size(); ++ii )
980 {
981 if( m_fields[ii].IsMandatory() )
982 continue;
983
984 if( aFieldName == m_fields[ii].GetName( false ) )
985 {
986 m_fields.erase( m_fields.begin() + ii );
987 return;
988 }
989 }
990}
991
992
993SCH_FIELD* SCH_SYMBOL::FindField( const wxString& aFieldName, bool aIncludeDefaultFields,
994 bool aCaseInsensitive )
995{
996 for( SCH_FIELD& field : m_fields )
997 {
998 if( field.IsMandatory() && !aIncludeDefaultFields )
999 continue;
1000
1001 if( aCaseInsensitive )
1002 {
1003 if( aFieldName.Upper() == field.GetName( false ).Upper() )
1004 return &field;
1005 }
1006 else
1007 {
1008 if( aFieldName == field.GetName( false ) )
1009 return &field;
1010 }
1011 }
1012
1013 return nullptr;
1014}
1015
1016
1017void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef,
1018 bool aUpdateOtherFields, bool aResetRef, bool aResetOtherFields )
1019{
1020 if( m_part )
1021 {
1022 std::vector<SCH_FIELD*> fields;
1023 m_part->GetFields( fields );
1024
1025 for( const SCH_FIELD* libField : fields )
1026 {
1027 int id = libField->GetId();
1028 SCH_FIELD* schField;
1029
1030 if( libField->IsMandatory() )
1031 {
1032 schField = GetFieldById( id );
1033 }
1034 else
1035 {
1036 schField = FindField( libField->GetCanonicalName() );
1037
1038 if( !schField )
1039 {
1040 SCH_FIELD newField( VECTOR2I( 0, 0 ), GetNextFieldId(), this,
1041 libField->GetCanonicalName() );
1042 schField = AddField( newField );
1043 }
1044 }
1045
1046 schField->SetPrivate( libField->IsPrivate() );
1047
1048 if( aUpdateStyle )
1049 {
1050 schField->ImportValues( *libField );
1051 schField->SetTextPos( m_pos + libField->GetTextPos() );
1052 }
1053
1054 if( id == REFERENCE_FIELD && aPath )
1055 {
1056 if( aResetRef )
1057 SetRef( aPath, m_part->GetReferenceField().GetText() );
1058 else if( aUpdateRef )
1059 SetRef( aPath, libField->GetText() );
1060 }
1061 else if( id == VALUE_FIELD )
1062 {
1063 SetValueFieldText( UnescapeString( libField->GetText() ) );
1064 }
1065 else if( id == FOOTPRINT_FIELD )
1066 {
1067 if( aResetOtherFields || aUpdateOtherFields )
1068 SetFootprintFieldText( libField->GetText() );
1069 }
1070 else if( id == DATASHEET_FIELD )
1071 {
1072 if( aResetOtherFields )
1073 schField->SetText( GetDatasheet() ); // alias-specific value
1074 else if( aUpdateOtherFields )
1075 schField->SetText( libField->GetText() );
1076 }
1077 else
1078 {
1079 if( aResetOtherFields || aUpdateOtherFields )
1080 schField->SetText( libField->GetText() );
1081 }
1082 }
1083 }
1084}
1085
1086
1087void SCH_SYMBOL::SyncOtherUnits( const SCH_SHEET_PATH& aSourceSheet, SCH_COMMIT& aCommit,
1088 PROPERTY_BASE* aProperty )
1089{
1090 bool updateValue = true;
1091 bool updateExclFromBOM = true;
1092 bool updateExclFromBoard = true;
1093 bool updateDNP = true;
1094 bool updateOtherFields = true;
1095 bool updatePins = true;
1096
1097 if( aProperty )
1098 {
1099 updateValue = aProperty->Name() == _HKI( "Value" );
1100 updateExclFromBoard = aProperty->Name() == _HKI( "Exclude From Board" );
1101 updateExclFromBOM = aProperty->Name() == _HKI( "Exclude From Bill of Materials" );
1102 updateDNP = aProperty->Name() == _HKI( "Do not Populate" );
1103 updateOtherFields = false;
1104 updatePins = false;
1105 }
1106
1107 if( !updateValue
1108 && !updateExclFromBOM
1109 && !updateExclFromBoard
1110 && !updateDNP
1111 && !updateOtherFields
1112 && !updatePins )
1113 {
1114 return;
1115 }
1116
1117 // Keep fields other than the reference, include/exclude flags, and alternate pin assignments
1118 // in sync in multi-unit parts.
1119 if( GetUnitCount() > 1 && IsAnnotated( &aSourceSheet ) )
1120 {
1121 wxString ref = GetRef( &aSourceSheet );
1122
1123 for( SCH_SHEET_PATH& sheet : Schematic()->Hierarchy() )
1124 {
1125 SCH_SCREEN* screen = sheet.LastScreen();
1126 std::vector<SCH_SYMBOL*> otherUnits;
1127
1128 CollectOtherUnits( ref, m_unit, m_lib_id, sheet, &otherUnits );
1129
1130 for( SCH_SYMBOL* otherUnit : otherUnits )
1131 {
1132 aCommit.Modify( otherUnit, screen );
1133
1134 if( updateValue )
1135 otherUnit->SetValueFieldText( GetField( VALUE_FIELD )->GetText() );
1136
1137 if( updateOtherFields )
1138 {
1139 otherUnit->SetFootprintFieldText( GetField( FOOTPRINT_FIELD )->GetText() );
1140
1141 for( size_t ii = DATASHEET_FIELD; ii < m_fields.size(); ++ii )
1142 {
1143 SCH_FIELD* otherField = otherUnit->FindField( m_fields[ii].GetName() );
1144
1145 if( otherField )
1146 {
1147 otherField->SetText( m_fields[ii].GetText() );
1148 }
1149 else
1150 {
1151 SCH_FIELD newField( m_fields[ii] );
1152 const_cast<KIID&>( newField.m_Uuid ) = KIID();
1153
1154 newField.Offset( -GetPosition() );
1155 newField.Offset( otherUnit->GetPosition() );
1156
1157 newField.SetParent( otherUnit );
1158 otherUnit->AddField( newField );
1159 }
1160 }
1161
1162 for( size_t ii = otherUnit->GetFields().size() - 1; ii > DATASHEET_FIELD; ii-- )
1163 {
1164 SCH_FIELD& otherField = otherUnit->GetFields().at( ii );
1165
1166 if( !FindField( otherField.GetName() ) )
1167 otherUnit->GetFields().erase( otherUnit->GetFields().begin() + ii );
1168 }
1169 }
1170
1171 if( updateExclFromBOM )
1172 otherUnit->SetExcludedFromBOM( m_excludedFromBOM );
1173
1174 if( updateExclFromBoard )
1175 otherUnit->SetExcludedFromBoard( m_excludedFromBoard );
1176
1177 if( updateDNP )
1178 otherUnit->SetDNP( m_DNP );
1179
1180 if( updatePins )
1181 {
1182 for( const std::unique_ptr<SCH_PIN>& model_pin : m_pins )
1183 {
1184 SCH_PIN* src_pin = otherUnit->GetPin( model_pin->GetNumber() );
1185
1186 if( src_pin )
1187 src_pin->SetAlt( model_pin->GetAlt() );
1188 }
1189 }
1190 }
1191 }
1192 }
1193}
1194
1195
1196void SCH_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
1197{
1198 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1199 aFunction( pin.get() );
1200
1201 for( SCH_FIELD& field : m_fields )
1202 aFunction( &field );
1203}
1204
1205
1206SCH_PIN* SCH_SYMBOL::GetPin( const wxString& aNumber ) const
1207{
1208 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1209 {
1210 if( pin->GetNumber() == aNumber )
1211 return pin.get();
1212 }
1213
1214 return nullptr;
1215}
1216
1217
1218const SCH_PIN* SCH_SYMBOL::GetPin( const VECTOR2I& aPos ) const
1219{
1220 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1221 {
1222 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
1223 : GetUnit();
1224 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
1225 : GetBodyStyle();
1226
1227 if( pin_unit > 0 && pin_unit != GetUnit() )
1228 continue;
1229
1230 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
1231 continue;
1232
1233 if( pin->IsPointClickableAnchor( aPos ) )
1234 return pin.get();
1235 }
1236
1237 return nullptr;
1238}
1239
1240
1241std::vector<SCH_PIN*> SCH_SYMBOL::GetLibPins() const
1242{
1243 if( m_part )
1244 return m_part->GetPins( m_unit, m_bodyStyle );
1245
1246 return std::vector<SCH_PIN*>();
1247}
1248
1249
1250std::vector<SCH_PIN*> SCH_SYMBOL::GetAllLibPins() const
1251{
1252 if( m_part )
1253 return m_part->GetPins();
1254
1255 return std::vector<SCH_PIN*>();
1256}
1257
1258
1260{
1261 return m_part ? m_part->GetPinCount() : 0;
1262}
1263
1264
1266{
1267 auto it = m_pinMap.find( aLibPin );
1268
1269 if( it != m_pinMap.end() )
1270 return it->second;
1271
1272 wxFAIL_MSG_AT( "Pin not found", __FILE__, __LINE__, __FUNCTION__ );
1273 return nullptr;
1274}
1275
1276
1277std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
1278{
1279 std::vector<SCH_PIN*> pins;
1280
1281 if( aSheet == nullptr )
1282 {
1283 wxCHECK_MSG( Schematic(), pins, "Can't call GetPins on a symbol with no schematic" );
1284
1285 aSheet = &Schematic()->CurrentSheet();
1286 }
1287
1288 int unit = GetUnitSelection( aSheet );
1289
1290 for( const std::unique_ptr<SCH_PIN>& p : m_pins )
1291 {
1292 if( unit && p->GetLibPin() && p->GetLibPin()->GetUnit()
1293 && ( p->GetLibPin()->GetUnit() != unit ) )
1294 {
1295 continue;
1296 }
1297
1298 pins.push_back( p.get() );
1299 }
1300
1301 return pins;
1302}
1303
1304
1305std::vector<SCH_PIN*> SCH_SYMBOL::GetPins() const
1306{
1307 return GetPins( nullptr );
1308}
1309
1310
1312{
1313 SCH_ITEM::SwapFlags( aItem );
1314
1315 wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T,
1316 wxT( "Cannot swap data with invalid symbol." ) );
1317
1318 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
1319
1320 std::swap( m_lib_id, symbol->m_lib_id );
1321
1322 m_pins.swap( symbol->m_pins ); // std::vector's swap()
1323
1324 for( std::unique_ptr<SCH_PIN>& pin : symbol->m_pins )
1325 pin->SetParent( symbol );
1326
1327 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1328 pin->SetParent( this );
1329
1330 LIB_SYMBOL* libSymbol = symbol->m_part.release();
1331 symbol->m_part = std::move( m_part );
1332 symbol->UpdatePins();
1333 m_part.reset( libSymbol );
1334 UpdatePins();
1335
1336 std::swap( m_pos, symbol->m_pos );
1337 std::swap( m_unit, symbol->m_unit );
1338 std::swap( m_bodyStyle, symbol->m_bodyStyle );
1339
1340 m_fields.swap( symbol->m_fields ); // std::vector's swap()
1341
1342 for( SCH_FIELD& field : symbol->m_fields )
1343 field.SetParent( symbol );
1344
1345 for( SCH_FIELD& field : m_fields )
1346 field.SetParent( this );
1347
1348 TRANSFORM tmp = m_transform;
1349
1350 m_transform = symbol->m_transform;
1351 symbol->m_transform = tmp;
1352
1353 std::swap( m_excludedFromSim, symbol->m_excludedFromSim );
1354 std::swap( m_excludedFromBOM, symbol->m_excludedFromBOM );
1355 std::swap( m_DNP, symbol->m_DNP );
1356 std::swap( m_excludedFromBoard, symbol->m_excludedFromBoard );
1357
1358 std::swap( m_instanceReferences, symbol->m_instanceReferences );
1359 std::swap( m_schLibSymbolName, symbol->m_schLibSymbolName );
1360}
1361
1362
1363void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
1364{
1365 for( const SCH_FIELD& field : m_fields )
1366 {
1367 if( field.IsPrivate() )
1368 continue;
1369
1370 if( field.IsMandatory() )
1371 aVars->push_back( field.GetCanonicalName().Upper() );
1372 else
1373 aVars->push_back( field.GetName() );
1374 }
1375
1376 aVars->push_back( wxT( "OP" ) );
1377 aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
1378 aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
1379 aVars->push_back( wxT( "UNIT" ) );
1380 aVars->push_back( wxT( "SHORT_REFERENCE" ) );
1381 aVars->push_back( wxT( "SYMBOL_LIBRARY" ) );
1382 aVars->push_back( wxT( "SYMBOL_NAME" ) );
1383 aVars->push_back( wxT( "SYMBOL_DESCRIPTION" ) );
1384 aVars->push_back( wxT( "SYMBOL_KEYWORDS" ) );
1385 aVars->push_back( wxT( "EXCLUDE_FROM_BOM" ) );
1386 aVars->push_back( wxT( "EXCLUDE_FROM_BOARD" ) );
1387 aVars->push_back( wxT( "EXCLUDE_FROM_SIM" ) );
1388 aVars->push_back( wxT( "DNP" ) );
1389 aVars->push_back( wxT( "SHORT_NET_NAME(<pin_number>)" ) );
1390 aVars->push_back( wxT( "NET_NAME(<pin_number>)" ) );
1391 aVars->push_back( wxT( "NET_CLASS(<pin_number>)" ) );
1392 aVars->push_back( wxT( "PIN_NAME(<pin_number>)" ) );
1393}
1394
1395
1396bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
1397{
1398 static wxRegEx operatingPoint( wxT( "^"
1399 "OP"
1400 "(:[^.]*)?" // pin
1401 "(.([0-9])?([a-zA-Z]*))?" // format
1402 "$" ) );
1403
1404 wxCHECK( aPath, false );
1405
1406 SCHEMATIC* schematic = Schematic();
1407
1408 if( !schematic )
1409 return false;
1410
1411 if( operatingPoint.Matches( *token ) )
1412 {
1413 wxString pin( operatingPoint.GetMatch( *token, 1 ).Lower() );
1414 wxString precisionStr( operatingPoint.GetMatch( *token, 3 ) );
1415 wxString range( operatingPoint.GetMatch( *token, 4 ) );
1416 int precision = 3;
1417
1418 if( !precisionStr.IsEmpty() )
1419 precision = precisionStr[0] - '0';
1420
1421 if( range.IsEmpty() )
1422 range = wxS( "~A" );
1423
1424 SIM_LIB_MGR simLibMgr( &schematic->Prj() );
1425 NULL_REPORTER devnull;
1426 SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast<SCH_SYMBOL&>( *this ),
1427 devnull ).model;
1428 SPICE_ITEM spiceItem;
1429 spiceItem.refName = GetRef( aPath );
1430
1431 wxString spiceRef = model.SpiceGenerator().ItemName( spiceItem );
1432 spiceRef = spiceRef.Lower();
1433
1434 if( pin.IsEmpty() )
1435 {
1436 *token = schematic->GetOperatingPoint( spiceRef, precision, range );
1437 return true;
1438 }
1439 else if( pin == wxS( ":power" ) )
1440 {
1441 if( range.IsEmpty() )
1442 range = wxS( "~W" );
1443
1444 *token = schematic->GetOperatingPoint( spiceRef + wxS( ":power" ), precision, range );
1445 return true;
1446 }
1447 else
1448 {
1449 pin = pin.SubString( 1, -1 ); // Strip ':' from front
1450
1451 for( const std::reference_wrapper<const SIM_MODEL_PIN>& modelPin : model.GetPins() )
1452 {
1453 SCH_PIN* symbolPin = GetPin( modelPin.get().symbolPinNumber );
1454
1455 if( pin == symbolPin->GetName().Lower() || pin == symbolPin->GetNumber().Lower() )
1456 {
1457 if( model.GetPins().size() == 2 )
1458 {
1459 *token = schematic->GetOperatingPoint( spiceRef, precision, range );
1460 }
1461 else
1462 {
1463 wxString signalName = spiceRef + wxS( ":" ) + modelPin.get().modelPinName;
1464 *token = schematic->GetOperatingPoint( signalName, precision, range );
1465 }
1466
1467 return true;
1468 }
1469 }
1470 }
1471
1472 *token = wxS( "?" );
1473 return true;
1474 }
1475
1476 if( token->Contains( ':' ) )
1477 {
1478 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
1479 return true;
1480 }
1481
1482 wxString upperToken = token->Upper();
1483
1484 for( const SCH_FIELD& field : m_fields )
1485 {
1486 wxString fieldName = field.IsMandatory() ? field.GetCanonicalName()
1487 : field.GetName();
1488
1489 wxString textToken = field.GetText();
1490 textToken.Replace( " ", wxEmptyString );
1491 wxString tokenString = "${" + fieldName + "}";
1492
1493 // If the field data is just a reference to the field, don't resolve
1494 if( textToken.IsSameAs( tokenString, false ) )
1495 return true;
1496
1497 if( token->IsSameAs( fieldName, false ) )
1498 {
1499 if( field.GetId() == REFERENCE_FIELD )
1500 *token = GetRef( aPath, true );
1501 else
1502 *token = field.GetShownText( aPath, false, aDepth + 1 );
1503
1504 return true;
1505 }
1506 }
1507
1508 // Consider missing simulation fields as empty, not un-resolved
1509 if( token->IsSameAs( wxT( "SIM.DEVICE" ) )
1510 || token->IsSameAs( wxT( "SIM.TYPE" ) )
1511 || token->IsSameAs( wxT( "SIM.PINS" ) )
1512 || token->IsSameAs( wxT( "SIM.PARAMS" ) )
1513 || token->IsSameAs( wxT( "SIM.LIBRARY" ) )
1514 || token->IsSameAs( wxT( "SIM.NAME" ) ) )
1515 {
1516 *token = wxEmptyString;
1517 return true;
1518 }
1519
1520 for( const TEMPLATE_FIELDNAME& templateFieldname :
1522 {
1523 if( token->IsSameAs( templateFieldname.m_Name )
1524 || token->IsSameAs( templateFieldname.m_Name.Upper() ) )
1525 {
1526 // If we didn't find it in the fields list then it isn't set on this symbol.
1527 // Just return an empty string.
1528 *token = wxEmptyString;
1529 return true;
1530 }
1531 }
1532
1533 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
1534 {
1535 wxString footprint = GetFootprintFieldText( true, aPath, false );
1536
1537 wxArrayString parts = wxSplit( footprint, ':' );
1538
1539 if( parts.Count() > 0 )
1540 *token = parts[ 0 ];
1541 else
1542 *token = wxEmptyString;
1543
1544 return true;
1545 }
1546 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
1547 {
1548 wxString footprint = GetFootprintFieldText( true, aPath, false );
1549
1550 wxArrayString parts = wxSplit( footprint, ':' );
1551
1552 if( parts.Count() > 1 )
1553 *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
1554 else
1555 *token = wxEmptyString;
1556
1557 return true;
1558 }
1559 else if( token->IsSameAs( wxT( "UNIT" ) ) )
1560 {
1561 *token = SubReference( GetUnitSelection( aPath ) );
1562 return true;
1563 }
1564 else if( token->IsSameAs( wxT( "SHORT_REFERENCE" ) ) )
1565 {
1566 *token = GetRef( aPath, false );
1567 return true;
1568 }
1569 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
1570 {
1572 return true;
1573 }
1574 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
1575 {
1577 return true;
1578 }
1579 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
1580 {
1581 *token = GetDescription();
1582 return true;
1583 }
1584 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
1585 {
1586 *token = GetKeyWords();
1587 return true;
1588 }
1589 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
1590 {
1591 *token = wxEmptyString;
1592
1593 if( aPath->GetExcludedFromBOM() || this->GetExcludedFromBOM() )
1594 *token = _( "Excluded from BOM" );
1595
1596 return true;
1597 }
1598 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
1599 {
1600 *token = wxEmptyString;
1601
1602 if( aPath->GetExcludedFromBoard() || this->GetExcludedFromBoard() )
1603 *token = _( "Excluded from board" );
1604
1605 return true;
1606 }
1607 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
1608 {
1609 *token = wxEmptyString;
1610
1611 if( aPath->GetExcludedFromSim() || this->GetExcludedFromSim() )
1612 *token = _( "Excluded from simulation" );
1613
1614 return true;
1615 }
1616 else if( token->IsSameAs( wxT( "DNP" ) ) )
1617 {
1618 *token = wxEmptyString;
1619
1620 if( aPath->GetDNP() || this->GetDNP() )
1621 *token = _( "DNP" );
1622
1623 return true;
1624 }
1625 else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) )
1626 || token->StartsWith( wxT( "NET_NAME(" ) )
1627 || token->StartsWith( wxT( "NET_CLASS(" ) )
1628 || token->StartsWith( wxT( "PIN_NAME(" ) ) )
1629 {
1630 wxString pinNumber = token->AfterFirst( '(' );
1631 pinNumber = pinNumber.BeforeLast( ')' );
1632
1633 for( SCH_PIN* pin : GetPins( aPath ) )
1634 {
1635 if( pin->GetNumber() == pinNumber )
1636 {
1637 if( token->StartsWith( wxT( "PIN_NAME" ) ) )
1638 {
1639 *token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
1640 return true;
1641 }
1642
1643 SCH_CONNECTION* conn = pin->Connection( aPath );
1644
1645 if( !conn )
1646 *token = wxEmptyString;
1647 else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
1648 *token = conn->LocalName();
1649 else if( token->StartsWith( wxT( "NET_NAME" ) ) )
1650 *token = conn->Name();
1651 else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
1652 *token = pin->GetEffectiveNetClass( aPath )->GetName();
1653
1654 return true;
1655 }
1656 }
1657 }
1658
1659 // See if parent can resolve it (this will recurse to ancestors)
1660 if( aPath->Last() && aPath->Last()->ResolveTextVar( aPath, token, aDepth + 1 ) )
1661 return true;
1662
1663 return false;
1664}
1665
1666
1667void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1668{
1669 if( aSheetPath )
1670 {
1671 KIID_PATH path = aSheetPath->Path();
1672
1673 for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1674 {
1675 if( instance.m_Path == path )
1676 {
1677 if( instance.m_Reference.IsEmpty() || aResetPrefix )
1678 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1679 else
1680 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1681 }
1682 }
1683 }
1684 else
1685 {
1686 for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1687 {
1688 if( instance.m_Reference.IsEmpty() || aResetPrefix)
1689 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1690 else
1691 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1692 }
1693 }
1694
1695 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1696 pin->ClearDefaultNetName( aSheetPath );
1697
1698 // These 2 changes do not work in complex hierarchy.
1699 // When a clear annotation is made, the calling function must call a
1700 // UpdateAllScreenReferences for the active sheet.
1701 // But this call cannot made here.
1702 wxString currentReference = m_fields[REFERENCE_FIELD].GetText();
1703
1704 if( currentReference.IsEmpty() || aResetPrefix )
1706 else
1707 m_fields[REFERENCE_FIELD].SetText( UTIL::GetRefDesUnannotated( currentReference ) );
1708}
1709
1710
1712{
1713 // An empty sheet path is illegal, at a minimum the root sheet UUID must be present.
1714 wxCHECK( aSheetPath.size() > 0, false );
1715
1716 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1717 {
1718 // if aSheetPath is found, nothing to do:
1719 if( instance.m_Path == aSheetPath )
1720 return false;
1721 }
1722
1723 // This entry does not exist: add it, with its last-used reference
1724 AddHierarchicalReference( aSheetPath, m_fields[REFERENCE_FIELD].GetText(), m_unit );
1725 return true;
1726}
1727
1728
1729void SCH_SYMBOL::SetOrientation( int aOrientation )
1730{
1731 TRANSFORM temp = TRANSFORM();
1732 bool transform = false;
1733
1734 switch( aOrientation )
1735 {
1736 case SYM_ORIENT_0:
1737 case SYM_NORMAL: // default transform matrix
1739 break;
1740
1741 case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
1742 temp.x1 = 0;
1743 temp.y1 = 1;
1744 temp.x2 = -1;
1745 temp.y2 = 0;
1746 transform = true;
1747 break;
1748
1749 case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1750 temp.x1 = 0;
1751 temp.y1 = -1;
1752 temp.x2 = 1;
1753 temp.y2 = 0;
1754 transform = true;
1755 break;
1756
1757 case SYM_MIRROR_Y: // Mirror Y (incremental transform)
1758 temp.x1 = -1;
1759 temp.y1 = 0;
1760 temp.x2 = 0;
1761 temp.y2 = 1;
1762 transform = true;
1763 break;
1764
1765 case SYM_MIRROR_X: // Mirror X (incremental transform)
1766 temp.x1 = 1;
1767 temp.y1 = 0;
1768 temp.x2 = 0;
1769 temp.y2 = -1;
1770 transform = true;
1771 break;
1772
1773 case SYM_ORIENT_90:
1776 break;
1777
1778 case SYM_ORIENT_180:
1782 break;
1783
1784 case SYM_ORIENT_270:
1787 break;
1788
1789 case ( SYM_ORIENT_0 + SYM_MIRROR_X ):
1792 break;
1793
1794 case ( SYM_ORIENT_0 + SYM_MIRROR_Y ):
1797 break;
1798
1803 break;
1804
1805 case ( SYM_ORIENT_90 + SYM_MIRROR_X ):
1808 break;
1809
1810 case ( SYM_ORIENT_90 + SYM_MIRROR_Y ):
1813 break;
1814
1819 break;
1820
1821 case ( SYM_ORIENT_180 + SYM_MIRROR_X ):
1824 break;
1825
1826 case ( SYM_ORIENT_180 + SYM_MIRROR_Y ):
1829 break;
1830
1835 break;
1836
1837 case ( SYM_ORIENT_270 + SYM_MIRROR_X ):
1840 break;
1841
1842 case ( SYM_ORIENT_270 + SYM_MIRROR_Y ):
1845 break;
1846
1851 break;
1852
1853 default:
1854 transform = false;
1855 wxFAIL_MSG( "Invalid schematic symbol orientation type." );
1856 break;
1857 }
1858
1859 if( transform )
1860 {
1861 /* The new matrix transform is the old matrix transform modified by the
1862 * requested transformation, which is the temp transform (rot,
1863 * mirror ..) in order to have (in term of matrix transform):
1864 * transform coord = new_m_transform * coord
1865 * where transform coord is the coord modified by new_m_transform from
1866 * the initial value coord.
1867 * new_m_transform is computed (from old_m_transform and temp) to
1868 * have:
1869 * transform coord = old_m_transform * temp
1870 */
1871 TRANSFORM newTransform;
1872
1873 newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1874 newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1875 newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1876 newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1877 m_transform = newTransform;
1878 }
1879}
1880
1881
1883{
1884 /*
1885 * This is slow, but also a bizarre algorithm. I don't feel like unteasing the algorithm right
1886 * now, so let's just cache it for the moment.
1887 */
1890
1891 int rotate_values[] =
1892 {
1905 };
1906
1907 // Try to find the current transform option:
1908 TRANSFORM transform = m_transform;
1909 SCH_SYMBOL temp( *this );
1910
1911 for( int type_rotate : rotate_values )
1912 {
1913 temp.SetOrientation( type_rotate );
1914
1915 if( transform == temp.GetTransform() )
1916 {
1918 return type_rotate;
1919 }
1920 }
1921
1922 // Error: orientation not found in list (should not happen)
1923 wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
1924
1925 return SYM_NORMAL;
1926}
1927
1928
1929#if defined(DEBUG)
1930
1931void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const
1932{
1933 // for now, make it look like XML:
1934 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1935 << " ref=\"" << TO_UTF8( GetField( REFERENCE_FIELD )->GetName() )
1936 << '"' << " chipName=\""
1937 << GetLibId().Format().wx_str() << '"' << m_pos
1938 << " layer=\"" << m_layer
1939 << '"' << ">\n";
1940
1941 // skip the reference, it's been output already.
1942 for( int i = 1; i < GetFieldCount(); ++i )
1943 {
1944 const wxString& value = GetFields()[i].GetText();
1945
1946 if( !value.IsEmpty() )
1947 {
1948 NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
1949 << TO_UTF8( GetFields()[i].GetName() )
1950 << '"' << " value=\""
1951 << TO_UTF8( value ) << "\"/>\n";
1952 }
1953 }
1954
1955 NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
1956}
1957
1958#endif
1959
1960
1961BOX2I SCH_SYMBOL::doGetBoundingBox( bool aIncludePins, bool aIncludeFields ) const
1962{
1963 BOX2I bBox;
1964
1965 if( m_part )
1966 bBox = m_part->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, false );
1967 else
1969 false );
1970
1971 bBox = m_transform.TransformCoordinate( bBox );
1972 bBox.Normalize();
1973
1974 bBox.Offset( m_pos );
1975
1976 if( aIncludeFields )
1977 {
1978 for( const SCH_FIELD& field : m_fields )
1979 {
1980 if( field.IsVisible() )
1981 bBox.Merge( field.GetBoundingBox() );
1982 }
1983 }
1984
1985 return bBox;
1986}
1987
1988
1990{
1991 try
1992 {
1993 return doGetBoundingBox( false, false );
1994 }
1995 catch( const boost::bad_pointer& e )
1996 {
1997 wxFAIL_MSG( wxString::Format( wxT( "Boost pointer exception occurred: %s" ), e.what() ) );
1998 return BOX2I();
1999 }
2000}
2001
2002
2004{
2005 return doGetBoundingBox( true, false );
2006}
2007
2008
2010{
2011 return doGetBoundingBox( true, true );
2012}
2013
2014
2015void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2016{
2017 wxString msg;
2018
2019 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
2020 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
2021
2022 auto addExcludes =
2023 [&]()
2024 {
2025 wxArrayString msgs;
2026
2027 if( GetExcludedFromSim() )
2028 msgs.Add( _( "Simulation" ) );
2029
2030 if( GetExcludedFromBOM() )
2031 msgs.Add( _( "BOM" ) );
2032
2033 if( GetExcludedFromBoard() )
2034 msgs.Add( _( "Board" ) );
2035
2036 if( GetDNP() )
2037 msgs.Add( _( "DNP" ) );
2038
2039 msg = wxJoin( msgs, '|' );
2040 msg.Replace( '|', wxS( ", " ) );
2041
2042 if( !msg.empty() )
2043 aList.emplace_back( _( "Exclude from" ), msg );
2044 };
2045
2046 // part and alias can differ if alias is not the root
2047 if( m_part )
2048 {
2049 if( m_part.get() != LIB_SYMBOL::GetDummy() )
2050 {
2051 if( m_part->IsPower() )
2052 {
2053 // Don't use GetShownText(); we want to see the variable references here
2054 aList.emplace_back( _( "Power symbol" ),
2056 GetField( VALUE_FIELD )->GetText() ) );
2057 }
2058 else
2059 {
2060 aList.emplace_back( _( "Reference" ),
2061 UnescapeString( GetRef( currentSheet ) ) );
2062
2063 // Don't use GetShownText(); we want to see the variable references here
2064 aList.emplace_back( _( "Value" ),
2066 GetField( VALUE_FIELD )->GetText() ) );
2067 addExcludes();
2068 aList.emplace_back( _( "Name" ),
2070 GetLibId().GetLibItemName() ) );
2071 }
2072
2073#if 0 // Display symbol flags, for debug only
2074 aList.emplace_back( _( "flags" ), wxString::Format( "%X", GetEditFlags() ) );
2075#endif
2076
2077 if( !m_part->IsRoot() )
2078 {
2079 msg = _( "Missing parent" );
2080
2081 std::shared_ptr< LIB_SYMBOL > parent = m_part->GetParent().lock();
2082
2083 if( parent )
2084 msg = parent->GetName();
2085
2086 aList.emplace_back( _( "Derived from" ), UnescapeString( msg ) );
2087 }
2088 else if( !m_lib_id.GetLibNickname().empty() )
2089 {
2090 aList.emplace_back( _( "Library" ), m_lib_id.GetLibNickname() );
2091 }
2092 else
2093 {
2094 aList.emplace_back( _( "Library" ), _( "Undefined!!!" ) );
2095 }
2096
2097 // Display the current associated footprint, if exists.
2098 // Don't use GetShownText(); we want to see the variable references here
2099 msg = KIUI::EllipsizeStatusText( aFrame, GetField( FOOTPRINT_FIELD )->GetText() );
2100
2101 if( msg.IsEmpty() )
2102 msg = _( "<Unknown>" );
2103
2104 aList.emplace_back( _( "Footprint" ), msg );
2105
2106 // Display description of the symbol, and keywords found in lib
2107 aList.emplace_back( _( "Description" ) + wxT( ": " )
2108 + GetField( DESCRIPTION_FIELD )->GetText(),
2109 _( "Keywords" ) + wxT( ": " ) + m_part->GetKeyWords() );
2110 }
2111 }
2112 else
2113 {
2114 aList.emplace_back( _( "Reference" ), GetRef( currentSheet ) );
2115
2116 // Don't use GetShownText(); we want to see the variable references here
2117 aList.emplace_back( _( "Value" ),
2119 GetField( VALUE_FIELD )->GetText() ) );
2120 addExcludes();
2121 aList.emplace_back( _( "Name" ),
2122 KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) );
2123
2124 wxString libNickname = GetLibId().GetLibNickname();
2125
2126 if( libNickname.empty() )
2127 msg = _( "No library defined!" );
2128 else
2129 msg.Printf( _( "Symbol not found in %s!" ), libNickname );
2130
2131 aList.emplace_back( _( "Library" ), msg );
2132 }
2133}
2134
2135
2137{
2138 return BITMAPS::add_component;
2139}
2140
2141
2143{
2144 int dx = m_pos.x;
2145
2147 MIRROR( m_pos.x, aCenter );
2148 dx -= m_pos.x; // dx,0 is the move vector for this transform
2149
2150 for( SCH_FIELD& field : m_fields )
2151 {
2152 // Move the fields to the new position because the symbol itself has moved.
2153 VECTOR2I pos = field.GetTextPos();
2154 pos.x -= dx;
2155 field.SetTextPos( pos );
2156 }
2157}
2158
2159
2161{
2162 int dy = m_pos.y;
2163
2165 MIRROR( m_pos.y, aCenter );
2166 dy -= m_pos.y; // 0,dy is the move vector for this transform
2167
2168 for( SCH_FIELD& field : m_fields )
2169 {
2170 // Move the fields to the new position because the symbol itself has moved.
2171 VECTOR2I pos = field.GetTextPos();
2172 pos.y -= dy;
2173 field.SetTextPos( pos );
2174 }
2175}
2176
2177
2178void SCH_SYMBOL::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
2179{
2180 VECTOR2I prev = m_pos;
2181
2182 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
2183
2185
2186 for( SCH_FIELD& field : m_fields )
2187 {
2188 // Move the fields to the new position because the symbol itself has moved.
2189 VECTOR2I pos = field.GetTextPos();
2190 pos.x -= prev.x - m_pos.x;
2191 pos.y -= prev.y - m_pos.y;
2192 field.SetTextPos( pos );
2193 }
2194}
2195
2196
2197bool SCH_SYMBOL::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
2198{
2199 for( SCH_ITEM& drawItem : GetLibSymbolRef()->GetDrawItems() )
2200 {
2201 if( drawItem.Matches( aSearchData, aAuxData ) )
2202 return true;
2203 }
2204
2205 // Symbols are searchable via the child field and pin item text.
2206 return false;
2207}
2208
2209
2210void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
2211{
2212 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2213 {
2214 SCH_PIN* lib_pin = pin->GetLibPin();
2215
2216 if( lib_pin && lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
2217 continue;
2218
2219 DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
2220 aItemList.push_back( item );
2221 }
2222}
2223
2224
2225bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
2226 std::vector<DANGLING_END_ITEM>& aItemListByPos,
2227 const SCH_SHEET_PATH* aPath )
2228{
2229 bool changed = false;
2230
2231 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2232 {
2233 bool previousState = pin->IsDangling();
2234 pin->SetIsDangling( true );
2235
2236 VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
2237
2238 auto lower = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, pos );
2239 bool do_break = false;
2240
2241 for( auto it = lower; it < aItemListByPos.end() && it->GetPosition() == pos; it++ )
2242 {
2243 DANGLING_END_ITEM& each_item = *it;
2244
2245 // Some people like to stack pins on top of each other in a symbol to indicate
2246 // internal connection. While technically connected, it is not particularly useful
2247 // to display them that way, so skip any pins that are in the same symbol as this
2248 // one.
2249 if( each_item.GetParent() == this )
2250 continue;
2251
2252 switch( each_item.GetType() )
2253 {
2254 case PIN_END:
2255 case LABEL_END:
2256 case SHEET_LABEL_END:
2257 case WIRE_END:
2258 case NO_CONNECT_END:
2259 case JUNCTION_END:
2260 pin->SetIsDangling( false );
2261 do_break = true;
2262 break;
2263
2264 default:
2265 break;
2266 }
2267
2268 if( do_break )
2269 break;
2270 }
2271
2272 changed = ( changed || ( previousState != pin->IsDangling() ) );
2273 }
2274
2275 return changed;
2276}
2277
2278
2280{
2281 if( ( aPin == nullptr ) || ( aPin->Type() != SCH_PIN_T ) )
2282 return VECTOR2I( 0, 0 );
2283
2285}
2286
2287
2289 const SCH_SHEET_PATH* aInstance ) const
2290{
2291 // Do not compare to ourself.
2292 if( aItem == this )
2293 return false;
2294
2295 const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( aItem );
2296
2297 // Don't compare against a different SCH_ITEM.
2298 wxCHECK( symbol, false );
2299
2300 // The move algorithm marks any pins that are being moved without something attached
2301 // (during the move) as dangling. We always need to recheck connectivity in this case
2302 // or we will not notice changes when the user places the symbol back in the same position
2303 // it started.
2304 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2305 {
2306 if( pin->IsDangling() )
2307 return true;
2308 }
2309
2310 if( GetPosition() != symbol->GetPosition() )
2311 return true;
2312
2313 if( GetLibId() != symbol->GetLibId() )
2314 return true;
2315
2316 if( GetUnitSelection( aInstance ) != symbol->GetUnitSelection( aInstance ) )
2317 return true;
2318
2319 if( GetRef( aInstance ) != symbol->GetRef( aInstance ) )
2320 return true;
2321
2322 // Power symbol value field changes are connectivity changes.
2323 if( IsPower()
2324 && ( GetValue( true, aInstance, false ) != symbol->GetValue( true, aInstance, false ) ) )
2325 return true;
2326
2327 if( m_pins.size() != symbol->m_pins.size() )
2328 return true;
2329
2330 for( size_t i = 0; i < m_pins.size(); i++ )
2331 {
2332 if( m_pins[i]->HasConnectivityChanges( symbol->m_pins[i].get() ) )
2333 return true;
2334 }
2335
2336 return false;
2337}
2338
2339
2340std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
2341{
2342 std::vector<VECTOR2I> retval;
2343
2344 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2345 {
2346 // Collect only pins attached to the current unit and convert.
2347 // others are not associated to this symbol instance
2348 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2349 : GetUnit();
2350 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2351 : GetBodyStyle();
2352
2353 if( pin_unit > 0 && pin_unit != GetUnit() )
2354 continue;
2355
2356 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2357 continue;
2358
2359 retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos );
2360 }
2361
2362 return retval;
2363}
2364
2365
2367{
2368 if( m_part )
2369 {
2370 // Calculate the position relative to the symbol.
2371 VECTOR2I libPosition = aPosition - m_pos;
2372
2373 return m_part->LocateDrawItem( m_unit, m_bodyStyle, aType, libPosition, m_transform );
2374 }
2375
2376 return nullptr;
2377}
2378
2379
2380wxString SCH_SYMBOL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2381{
2382 return wxString::Format( _( "Symbol %s [%s]" ),
2384 KIUI::EllipsizeMenuText( GetLibId().GetLibItemName() ) );
2385}
2386
2387
2388INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData,
2389 const std::vector<KICAD_T>& aScanTypes )
2390{
2391 for( KICAD_T scanType : aScanTypes )
2392 {
2393 if( scanType == SCH_LOCATE_ANY_T
2394 || ( scanType == SCH_SYMBOL_T )
2395 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
2396 {
2397 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
2398 return INSPECT_RESULT::QUIT;
2399 }
2400
2401 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
2402 {
2403 for( SCH_FIELD& field : m_fields )
2404 {
2405 if( INSPECT_RESULT::QUIT == aInspector( &field, (void*) this ) )
2406 return INSPECT_RESULT::QUIT;
2407 }
2408 }
2409
2410 if( scanType == SCH_FIELD_LOCATE_REFERENCE_T )
2411 {
2412 if( INSPECT_RESULT::QUIT == aInspector( GetField( REFERENCE_FIELD ), (void*) this ) )
2413 return INSPECT_RESULT::QUIT;
2414 }
2415
2416 if( scanType == SCH_FIELD_LOCATE_VALUE_T
2417 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
2418 {
2419 if( INSPECT_RESULT::QUIT == aInspector( GetField( VALUE_FIELD ), (void*) this ) )
2420 return INSPECT_RESULT::QUIT;
2421 }
2422
2423 if( scanType == SCH_FIELD_LOCATE_FOOTPRINT_T )
2424 {
2425 if( INSPECT_RESULT::QUIT == aInspector( GetField( FOOTPRINT_FIELD ), (void*) this ) )
2426 return INSPECT_RESULT::QUIT;
2427 }
2428
2429 if( scanType == SCH_FIELD_LOCATE_DATASHEET_T )
2430 {
2431 if( INSPECT_RESULT::QUIT == aInspector( GetField( DATASHEET_FIELD ), (void*) this ) )
2432 return INSPECT_RESULT::QUIT;
2433 }
2434
2435 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_PIN_T )
2436 {
2437 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2438 {
2439 // Collect only pins attached to the current unit and convert.
2440 // others are not associated to this symbol instance
2441 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2442 : GetUnit();
2443 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2444 : GetBodyStyle();
2445
2446 if( pin_unit > 0 && pin_unit != GetUnit() )
2447 continue;
2448
2449 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2450 continue;
2451
2452 if( INSPECT_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
2453 return INSPECT_RESULT::QUIT;
2454 }
2455 }
2456 }
2457
2458 return INSPECT_RESULT::CONTINUE;
2459}
2460
2461
2462bool SCH_SYMBOL::operator <( const SCH_ITEM& aItem ) const
2463{
2464 if( Type() != aItem.Type() )
2465 return Type() < aItem.Type();
2466
2467 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( &aItem );
2468
2470
2471 if( rect.GetArea() != symbol->GetBodyAndPinsBoundingBox().GetArea() )
2472 return rect.GetArea() < symbol->GetBodyAndPinsBoundingBox().GetArea();
2473
2474 if( m_pos.x != symbol->m_pos.x )
2475 return m_pos.x < symbol->m_pos.x;
2476
2477 if( m_pos.y != symbol->m_pos.y )
2478 return m_pos.y < symbol->m_pos.y;
2479
2480 return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
2481}
2482
2483
2484bool SCH_SYMBOL::operator==( const SCH_SYMBOL& aSymbol ) const
2485{
2486 if( GetFieldCount() != aSymbol.GetFieldCount() )
2487 return false;
2488
2489 for( int ii = 0; ii < GetFieldCount(); ii++ )
2490 {
2491 if( ii == REFERENCE_FIELD )
2492 continue;
2493
2494 if( GetFields()[ii].GetText().Cmp( aSymbol.GetFields()[ii].GetText() ) != 0 )
2495 return false;
2496 }
2497
2498 return true;
2499}
2500
2501
2502bool SCH_SYMBOL::operator!=( const SCH_SYMBOL& aSymbol ) const
2503{
2504 return !( *this == aSymbol );
2505}
2506
2507
2509{
2510 wxCHECK_MSG( Type() == aSymbol.Type(), *this,
2511 wxT( "Cannot assign object type " ) + aSymbol.GetClass() + wxT( " to type " ) +
2512 GetClass() );
2513
2514 if( &aSymbol != this )
2515 {
2516 SYMBOL::operator=( aSymbol );
2517
2518 m_lib_id = aSymbol.m_lib_id;
2519 m_part.reset( aSymbol.m_part ? new LIB_SYMBOL( *aSymbol.m_part ) : nullptr );
2520 m_pos = aSymbol.m_pos;
2521 m_unit = aSymbol.m_unit;
2522 m_bodyStyle = aSymbol.m_bodyStyle;
2523 m_transform = aSymbol.m_transform;
2524
2526
2527 m_fields = aSymbol.m_fields; // std::vector's assignment operator
2528
2529 // Reparent fields after assignment to new symbol.
2530 for( SCH_FIELD& field : m_fields )
2531 field.SetParent( this );
2532
2533 UpdatePins();
2534 }
2535
2536 return *this;
2537}
2538
2539
2540bool SCH_SYMBOL::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2541{
2542 BOX2I bBox = GetBodyBoundingBox();
2543 bBox.Inflate( aAccuracy / 2 );
2544
2545 if( bBox.Contains( aPosition ) )
2546 return true;
2547
2548 return false;
2549}
2550
2551
2552bool SCH_SYMBOL::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2553{
2555 return false;
2556
2557 BOX2I rect = aRect;
2558
2559 rect.Inflate( aAccuracy / 2 );
2560
2561 if( aContained )
2562 return rect.Contains( GetBodyBoundingBox() );
2563
2564 return rect.Intersects( GetBodyBoundingBox() );
2565}
2566
2567
2568bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
2569{
2571
2572 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2573 {
2574 if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
2575 continue;
2576
2577 // Collect only pins attached to the current unit and convert.
2578 // others are not associated to this symbol instance
2579 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2580 : GetUnit();
2581 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2582 : GetBodyStyle();
2583
2584 if( pin_unit > 0 && pin_unit != GetUnit() )
2585 continue;
2586
2587 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2588 continue;
2589
2590 if( pin->GetLocalPosition() == new_pos )
2591 return true;
2592 }
2593
2594 return false;
2595}
2596
2597
2599{
2600 return m_isInNetlist;
2601}
2602
2603
2604void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
2605 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
2606{
2607 if( aBackground )
2608 return;
2609
2610 if( m_part )
2611 {
2612 std::vector<SCH_PIN*> libPins = m_part->GetPins( GetUnit(), GetBodyStyle() );
2613
2614 // Copy the source so we can re-orient and translate it.
2615 LIB_SYMBOL tempSymbol( *m_part );
2616 std::vector<SCH_PIN*> tempPins = tempSymbol.GetPins( GetUnit(), GetBodyStyle() );
2617
2618 // Copy the pin info from the symbol to the temp pins
2619 for( unsigned i = 0; i < tempPins.size(); ++ i )
2620 {
2621 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2622 SCH_PIN* tempPin = tempPins[ i ];
2623
2624 tempPin->SetName( symbolPin->GetShownName() );
2625 tempPin->SetType( symbolPin->GetType() );
2626 tempPin->SetShape( symbolPin->GetShape() );
2627
2628 if( symbolPin->IsDangling() )
2629 tempPin->SetFlags( IS_DANGLING );
2630 }
2631
2632 for( SCH_ITEM& item : tempSymbol.GetDrawItems() )
2633 {
2634 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( &item ) )
2635 {
2636 // Use SCH_FIELD's text resolver
2637 SCH_FIELD dummy( this, -1 );
2638 dummy.SetText( text->GetText() );
2639 text->SetText( dummy.GetShownText( false ) );
2640 }
2641 }
2642
2643 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
2644 TRANSFORM savedTransform = renderSettings->m_Transform;
2645 renderSettings->m_Transform = GetTransform();
2646 aPlotter->StartBlock( nullptr );
2647
2648 for( bool local_background : { true, false } )
2649 {
2650 tempSymbol.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(),
2651 m_pos, GetDNP() );
2652
2653 for( SCH_FIELD field : m_fields )
2654 {
2655 field.ClearRenderCache();
2656 field.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(),
2657 m_pos, GetDNP() );
2658 }
2659 }
2660
2661 if( m_DNP )
2662 PlotDNP( aPlotter );
2663
2664 SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
2665
2666 // Plot attributes to a hypertext menu
2667 if( aPlotOpts.m_PDFPropertyPopups )
2668 {
2669 std::vector<wxString> properties;
2670
2671 for( const SCH_FIELD& field : GetFields() )
2672 {
2673 wxString text_field = field.GetShownText( sheet, false);
2674
2675 if( text_field.IsEmpty() )
2676 continue;
2677
2678 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2679 field.GetName(), text_field ) );
2680 }
2681
2682 if( !m_part->GetKeyWords().IsEmpty() )
2683 {
2684 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2685 _( "Keywords" ),
2686 m_part->GetKeyWords() ) );
2687 }
2688
2689 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
2690 }
2691
2692 aPlotter->EndBlock( nullptr );
2693 renderSettings->m_Transform = savedTransform;
2694
2695 if( !m_part->IsPower() )
2696 aPlotter->Bookmark( GetBoundingBox(), GetRef( sheet ), _( "Symbols" ) );
2697 }
2698}
2699
2700
2701void SCH_SYMBOL::PlotDNP( PLOTTER* aPlotter ) const
2702{
2703 BOX2I bbox = GetBodyBoundingBox();
2705 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(),
2706 pins.GetEnd().x - bbox.GetEnd().x ),
2707 std::max( bbox.GetY() - pins.GetY(),
2708 pins.GetEnd().y - bbox.GetEnd().y ) );
2709 int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
2710
2711 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
2712 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
2713 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
2714
2715 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
2716 aPlotter->SetColor( renderSettings->GetLayerColor( LAYER_DNP_MARKER ) );
2717
2718 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, FILLED, nullptr );
2719
2720 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
2721 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
2722 strokeWidth, FILLED, nullptr );
2723}
2724
2725
2726void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter ) const
2727{
2728 if( m_part )
2729 {
2730 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
2731 TRANSFORM savedTransform = renderSettings->m_Transform;
2732 renderSettings->m_Transform = GetTransform();
2733
2734 std::vector<SCH_PIN*> libPins = m_part->GetPins( GetUnit(), GetBodyStyle() );
2735
2736 // Copy the source to stay const
2737 LIB_SYMBOL tempSymbol( *m_part );
2738 std::vector<SCH_PIN*> tempPins = tempSymbol.GetPins( GetUnit(), GetBodyStyle() );
2739 SCH_PLOT_OPTS plotOpts;
2740
2741 // Copy the pin info from the symbol to the temp pins
2742 for( unsigned i = 0; i < tempPins.size(); ++ i )
2743 {
2744 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2745 SCH_PIN* tempPin = tempPins[ i ];
2746
2747 tempPin->SetName( symbolPin->GetShownName() );
2748 tempPin->SetType( symbolPin->GetType() );
2749 tempPin->SetShape( symbolPin->GetShape() );
2750 tempPin->Plot( aPlotter, false, plotOpts, GetUnit(), GetBodyStyle(), m_pos, GetDNP() );
2751 }
2752
2753 renderSettings->m_Transform = savedTransform;
2754 }
2755}
2756
2757
2759{
2760 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2761 {
2762 if( pin->IsBrightened() )
2763 return true;
2764 }
2765
2766 return false;
2767}
2768
2769
2771{
2772 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
2773 pin->ClearBrightened();
2774}
2775
2776
2777/*
2778 * When modified at the schematic level, we still store the values of these flags in the
2779 * associated m_part. If m_part now diverges from other usages, a new derived LIB_SYMBOL
2780 * will be created and stored locally in the schematic.
2781 */
2783{
2784 return m_part && m_part->GetShowPinNames();
2785}
2786
2787
2789{
2790 if( m_part )
2791 m_part->SetShowPinNames( aShow );
2792}
2793
2794
2796{
2797 return m_part && m_part->GetShowPinNumbers();
2798}
2799
2800
2802{
2803 if( m_part )
2804 m_part->SetShowPinNumbers( aShow );
2805}
2806
2807
2809{
2810 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2811 {
2812 int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit()
2813 : GetUnit();
2814 int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle()
2815 : GetBodyStyle();
2816
2817 if( pin_unit > 0 && pin_unit != GetUnit() )
2818 continue;
2819
2820 if( pin_bodyStyle > 0 && pin_bodyStyle != GetBodyStyle() )
2821 continue;
2822
2823 if( pin->IsPointClickableAnchor( aPos ) )
2824 return true;
2825 }
2826
2827 return false;
2828}
2829
2830
2832{
2833 // return true if the symbol is equivalent to a global label:
2834 // It is a Power symbol
2835 // It has only one pin type Power input
2836
2837 if( !GetLibSymbolRef() || !GetLibSymbolRef()->IsPower() )
2838 return false;
2839
2840 std::vector<SCH_PIN*> pin_list = GetAllLibPins();
2841
2842 if( pin_list.size() != 1 )
2843 return false;
2844
2845 return pin_list[0]->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN;
2846}
2847
2848
2850{
2851 if( !m_part )
2852 return false;
2853
2854 return m_part->IsPower();
2855}
2856
2857
2859{
2860 wxCHECK( m_part, false );
2861
2862 return m_part->IsNormal();
2863}
2864
2865
2866std::unordered_set<wxString> SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const
2867{
2868 std::unordered_set<wxString> componentClass;
2869
2870 auto getComponentClassFields = [&]( const auto& fields )
2871 {
2872 for( const SCH_FIELD& field : fields )
2873 {
2874 if( field.GetCanonicalName() == wxT( "Component Class" ) )
2875 {
2876 if( field.GetShownText( aPath, false ) != wxEmptyString )
2877 componentClass.insert( field.GetShownText( aPath, false ) );
2878 }
2879 }
2880 };
2881
2882 // First get component classes set on the symbol itself
2883 getComponentClassFields( m_fields );
2884
2885 // Now get component classes set on any enclosing rule areas
2886 for( const SCH_RULE_AREA* ruleArea : m_rule_areas_cache )
2887 {
2888 for( const SCH_DIRECTIVE_LABEL* label : ruleArea->GetDirectives() )
2889 {
2890 getComponentClassFields( label->GetFields() );
2891 }
2892 }
2893
2894 return componentClass;
2895}
2896
2897
2898bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
2899{
2900 if( Type() != aOther.Type() )
2901 return false;
2902
2903 const SCH_SYMBOL& symbol = static_cast<const SCH_SYMBOL&>( aOther );
2904
2905 if( GetLibId() != symbol.GetLibId() )
2906 return false;
2907
2908 if( GetPosition() != symbol.GetPosition() )
2909 return false;
2910
2911 if( GetUnit() != symbol.GetUnit() )
2912 return false;
2913
2914 if( GetBodyStyle() != symbol.GetBodyStyle() )
2915 return false;
2916
2917 if( GetTransform() != symbol.GetTransform() )
2918 return false;
2919
2920 if( GetFields() != symbol.GetFields() )
2921 return false;
2922
2923 if( m_pins.size() != symbol.m_pins.size() )
2924 return false;
2925
2926 for( unsigned i = 0; i < m_pins.size(); ++i )
2927 {
2928 if( *m_pins[i] != *symbol.m_pins[i] )
2929 return false;
2930 }
2931
2932 return true;
2933}
2934
2935
2936double SCH_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
2937{
2938 if( Type() != aOther.Type() )
2939 return 0.0;
2940
2941 const SCH_SYMBOL& symbol = static_cast<const SCH_SYMBOL&>( aOther );
2942
2943 if( GetLibId() != symbol.GetLibId() )
2944 return 0.0;
2945
2946 if( GetPosition() == symbol.GetPosition() )
2947 return 1.0;
2948
2949 return 0.0;
2950}
2951
2952
2953static struct SCH_SYMBOL_DESC
2954{
2956 {
2958 .Map( SYMBOL_ANGLE_0, wxS( "0" ) )
2959 .Map( SYMBOL_ANGLE_90, wxS( "90" ) )
2960 .Map( SYMBOL_ANGLE_180, wxS( "180" ) )
2961 .Map( SYMBOL_ANGLE_270, wxS( "270" ) );
2962
2966
2967 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Position X" ),
2968 &SCH_SYMBOL::SetX, &SCH_SYMBOL::GetX, PROPERTY_DISPLAY::PT_COORD,
2970 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Position Y" ),
2971 &SCH_SYMBOL::SetY, &SCH_SYMBOL::GetY, PROPERTY_DISPLAY::PT_COORD,
2973
2975 _HKI( "Orientation" ),
2977 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Mirror X" ),
2979 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Mirror Y" ),
2981
2982 auto hasLibPart =
2983 []( INSPECTABLE* aItem ) -> bool
2984 {
2985 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
2986 return symbol->GetLibSymbolRef() != nullptr;
2987
2988 return false;
2989 };
2990
2991 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Pin numbers" ),
2993 .SetAvailableFunc( hasLibPart );
2994
2995 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Pin names" ),
2997 .SetAvailableFunc( hasLibPart );
2998
2999 const wxString groupFields = _HKI( "Fields" );
3000
3001 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Reference" ),
3003 groupFields );
3004 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Value" ),
3006 groupFields );
3007 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Library Link" ),
3009 groupFields );
3010 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Library Description" ),
3012 groupFields );
3013 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Keywords" ),
3015 groupFields );
3016
3017 auto multiUnit =
3018 [=]( INSPECTABLE* aItem ) -> bool
3019 {
3020 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3021 return symbol->IsMulti();
3022
3023 return false;
3024 };
3025
3026 auto multiBodyStyle =
3027 [=]( INSPECTABLE* aItem ) -> bool
3028 {
3029 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
3030 return symbol->HasAlternateBodyStyle();
3031
3032 return false;
3033 };
3034
3035 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Unit" ),
3037 .SetAvailableFunc( multiUnit );
3038
3039 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Body Style" ),
3041 .SetAvailableFunc( multiBodyStyle );
3042
3043 const wxString groupAttributes = _HKI( "Attributes" );
3044
3045 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude From Board" ),
3047 groupAttributes );
3048 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude From Simulation" ),
3050 groupAttributes );
3051 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Exclude From Bill of Materials" ),
3053 groupAttributes );
3054 propMgr.AddProperty( new PROPERTY<SYMBOL, bool>( _HKI( "Do not Populate" ),
3056 groupAttributes );
3057 }
3059
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:593
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:857
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:601
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:695
static wxString LetterSubReference(int aUnit, int aFirstId)
Definition: lib_symbol.cpp:481
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.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:338
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:83
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:162
wxString GetOperatingPoint(const wxString &aNetName, int aPrecision, const wxString &aRange)
Definition: schematic.cpp:737
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:98
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:1233
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:1218
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:719
int m_bodyStyle
Definition: sch_item.h:720
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition: sch_item.h:665
void SetPrivate(bool aPrivate)
Definition: sch_item.h:238
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:150
int GetBodyStyle() const
Definition: sch_item.h:236
friend class LIB_SYMBOL
Definition: sch_item.h:738
int GetUnit() const
Definition: sch_item.h:233
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition: sch_item.h:722
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:735
void SwapFlags(SCH_ITEM *aItem)
Swap the non-temp and non-edit flags.
Definition: sch_item.cpp:352
SCH_LAYER_ID m_layer
Definition: sch_item.h:718
void SetAlt(const wxString &aAlt)
Definition: sch_pin.h:153
void SetName(const wxString &aName)
Definition: sch_pin.cpp:402
const wxString & GetName() const
Definition: sch_pin.cpp:384
bool IsDangling() const override
Definition: sch_pin.cpp:416
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:1529
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: sch_pin.h:95
VECTOR2I GetPosition() const override
Definition: sch_pin.cpp:248
wxString GetShownName() const
Definition: sch_pin.cpp:501
void SetType(ELECTRICAL_PINTYPE aType)
Definition: sch_pin.cpp:325
const wxString & GetNumber() const
Definition: sch_pin.h:123
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:270
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:305
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:254
Schematic symbol object.
Definition: sch_symbol.h:77
void SetValueProp(const wxString &aRef)
Definition: sch_symbol.h:520
SCH_SYMBOL & operator=(const SCH_SYMBOL &aItem)
int GetUnitProp() const
Definition: sch_symbol.h:525
size_t GetFullPinCount() const
void UpdatePrefix()
Set the prefix based on the current reference designator.
Definition: sch_symbol.cpp:797
wxString m_prefix
C, R, U, Q etc - the first character(s) which typically indicate what the symbol is.
Definition: sch_symbol.h:879
SCH_FIELD * GetFieldByName(const wxString &aFieldName)
Return a field in this symbol.
Definition: sch_symbol.cpp:931
wxString GetDescription() const override
Definition: sch_symbol.cpp:260
std::unordered_map< SCH_PIN *, SCH_PIN * > m_pinMap
Library pin pointer : SCH_PIN indices.
Definition: sch_symbol.h:900
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:877
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:878
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:738
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:582
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:580
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:788
wxString SubReference(int aUnit, bool aAddSeparator=true) const
Definition: sch_symbol.cpp:824
wxString GetClass() const override
Return the class name.
Definition: sch_symbol.h:116
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:577
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:783
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:885
int GetX() const
Definition: sch_symbol.h:785
std::vector< SCH_PIN * > GetPins() const override
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
Definition: sch_symbol.cpp:977
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:993
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) override
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:955
bool IsInNetlist() const
void SetBodyStyleProp(int aBodyStyle)
Definition: sch_symbol.h:547
void ClearBrightenedPins()
void SetY(int aY)
Definition: sch_symbol.h:789
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:907
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:910
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:287
std::vector< SCH_SYMBOL_INSTANCE > m_instanceReferences
Define the hierarchical path and reference of the symbol.
Definition: sch_symbol.h:907
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const override
Definition: sch_symbol.cpp:875
void SyncOtherUnits(const SCH_SHEET_PATH &aSourceSheet, SCH_COMMIT &aCommit, PROPERTY_BASE *aProperty)
Keep fields other than the reference, include/exclude flags, and alternate pin assignments in sync in...
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:891
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:747
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:891
std::vector< SCH_FIELD > m_fields
Variable length list of fields.
Definition: sch_symbol.h:893
int GetBodyStyleProp() const
Definition: sch_symbol.h:542
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:901
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:605
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:782
std::unique_ptr< LIB_SYMBOL > m_part
A flattened copy of the LIB_SYMBOL from the PROJECT object's libraries.
Definition: sch_symbol.h:895
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:530
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:919
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:553
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:970
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:786
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:897
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:833
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
wxString GetValueProp() const
Definition: sch_symbol.h:515
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:849
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
Return the component classes this symbol belongs in.
std::vector< std::unique_ptr< SCH_PIN > > m_pins
A SCH_PIN for every #LIB_PIN.
Definition: sch_symbol.h:899
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:705
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:225
void SetDNP(bool aDNP)
Definition: symbol.h:191
bool GetExcludedFromBoard() const
Definition: symbol.h:185
bool m_excludedFromSim
Definition: symbol.h:222
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: symbol.h:162
bool GetExcludedFromBOM() const
Definition: symbol.h:179
const TRANSFORM & GetTransform() const
Definition: symbol.h:195
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:223
bool GetDNP() const
Set or clear the 'Do Not Populate' flag.
Definition: symbol.h:190
bool m_excludedFromBoard
Definition: symbol.h:224
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:178
SYMBOL & operator=(const SYMBOL &aItem)
Definition: symbol.h:91
void SetExcludedFromBoard(bool aExcludeFromBoard)
Set or clear exclude from board netlist flag.
Definition: symbol.h:184
virtual bool GetShowPinNumbers() const
Definition: symbol.h:163
TRANSFORM m_transform
The rotation/mirror transformation.
Definition: symbol.h:215
bool GetExcludedFromSim() const override
Definition: symbol.h:173
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:438
@ LAYER_DEVICE
Definition: layer_ids.h:455
@ LAYER_VALUEPART
Definition: layer_ids.h:450
@ LAYER_FIELDS
Definition: layer_ids.h:451
@ LAYER_REFERENCEPART
Definition: layer_ids.h:449
@ LAYER_DNP_MARKER
Definition: layer_ids.h:467
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