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