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-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <sch_edit_frame.h>
26#include <widgets/msgpanel.h>
27#include <bitmaps.h>
28#include <core/mirror.h>
29#include <lib_pin.h>
30#include <lib_text.h>
31#include <lib_shape.h>
32#include <pgm_base.h>
33#include <sch_symbol.h>
34#include <sch_sheet_path.h>
35#include <schematic.h>
36#include <trace_helpers.h>
37#include <trigo.h>
38#include <refdes_utils.h>
39#include <wx/log.h>
41#include <string_utils.h>
42
43#include <utility>
44#include "plotters/plotter.h"
45
46
47std::unordered_map<TRANSFORM, int> SCH_SYMBOL::s_transformToOrientationCache;
48
49
54std::string toUTFTildaText( const wxString& txt )
55{
56 std::string ret = TO_UTF8( txt );
57
58 for( std::string::iterator it = ret.begin(); it!=ret.end(); ++it )
59 {
60 if( (unsigned char) *it <= ' ' )
61 *it = '~';
62 }
63
64 return ret;
65}
66
67
74{
75 static LIB_SYMBOL* symbol;
76
77 if( !symbol )
78 {
79 symbol = new LIB_SYMBOL( wxEmptyString );
80
82
83 square->MoveTo( VECTOR2I( schIUScale.MilsToIU( -200 ), schIUScale.MilsToIU( 200 ) ) );
84 square->SetEnd( VECTOR2I( schIUScale.MilsToIU( 200 ), schIUScale.MilsToIU( -200 ) ) );
85
86 LIB_TEXT* text = new LIB_TEXT( symbol );
87
88 text->SetTextSize( VECTOR2I( schIUScale.MilsToIU( 150 ), schIUScale.MilsToIU( 150 ) ) );
89 text->SetText( wxString( wxT( "??" ) ) );
90
91 symbol->AddDrawItem( square );
92 symbol->AddDrawItem( text );
93 }
94
95 return symbol;
96}
97
98
100 SCH_ITEM( nullptr, SCH_SYMBOL_T )
101{
102 m_DNP = false;
103 Init( VECTOR2I( 0, 0 ) );
104}
105
106
107SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId,
108 const SCH_SHEET_PATH* aSheet, int aUnit, int aConvert,
109 const VECTOR2I& aPosition, EDA_ITEM* aParent ) :
110 SCH_ITEM( aParent, SCH_SYMBOL_T )
111{
112 Init( aPosition );
113
114 m_unit = aUnit;
115 m_convert = aConvert;
116 m_lib_id = aLibId;
117
118 std::unique_ptr< LIB_SYMBOL > part;
119
120 part = aSymbol.Flatten();
121 part->SetParent();
122 SetLibSymbol( part.release() );
123
124 // Copy fields from the library symbol
125 UpdateFields( aSheet,
126 true, /* update style */
127 false, /* update ref */
128 false, /* update other fields */
129 true, /* reset ref */
130 true /* reset other fields */ );
131
132 m_prefix = UTIL::GetRefDesPrefix( m_part->GetReferenceField().GetText() );
133
134 if( aSheet )
136
137 // Inherit the include in bill of materials and board netlist settings from flattened
138 // library symbol.
139 m_excludedFromSim = m_part->GetExcludedFromSim();
140 m_excludedFromBOM = m_part->GetExcludedFromBOM();
141 m_excludedFromBoard = m_part->GetExcludedFromBoard();
142 m_DNP = false;
143
144}
145
146
147SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet,
148 const PICKED_SYMBOL& aSel, const VECTOR2I& aPosition,
149 EDA_ITEM* aParent ) :
150 SCH_SYMBOL( aSymbol, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, aPosition, aParent )
151{
152 // Set any fields that were modified as part of the symbol selection
153 for( const std::pair<int, wxString>& i : aSel.Fields )
154 {
155 if( i.first == REFERENCE_FIELD )
156 SetRef( aSheet, i.second );
157 else if( SCH_FIELD* field = GetFieldById( i.first ) )
158 field->SetText( i.second );
159 }
160}
161
162
164 SCH_ITEM( aSymbol )
165{
166 m_parent = aSymbol.m_parent;
167 m_pos = aSymbol.m_pos;
168 m_unit = aSymbol.m_unit;
169 m_convert = aSymbol.m_convert;
170 m_lib_id = aSymbol.m_lib_id;
175 m_DNP = aSymbol.m_DNP;
176
177 const_cast<KIID&>( m_Uuid ) = aSymbol.m_Uuid;
178
179 m_transform = aSymbol.m_transform;
180 m_prefix = aSymbol.m_prefix;
182 m_fields = aSymbol.m_fields;
183
184 // Re-parent the fields, which before this had aSymbol as parent
185 for( SCH_FIELD& field : m_fields )
186 field.SetParent( this );
187
188 m_pins.clear();
189
190 // Copy (and re-parent) the pins
191 for( const std::unique_ptr<SCH_PIN>& pin : aSymbol.m_pins )
192 {
193 m_pins.emplace_back( std::make_unique<SCH_PIN>( *pin ) );
194 m_pins.back()->SetParent( this );
195 }
196
197 if( aSymbol.m_part )
198 SetLibSymbol( new LIB_SYMBOL( *aSymbol.m_part ) );
199
202}
203
204
205void SCH_SYMBOL::Init( const VECTOR2I& pos )
206{
208 m_pos = pos;
209 m_unit = 1; // In multi unit chip - which unit to draw.
210 m_convert = LIB_ITEM::LIB_CONVERT::BASE; // De Morgan Handling
211
212 // The rotation/mirror transformation matrix. pos normal
214
215 // construct only the mandatory fields, which are the first 4 only.
216 for( int i = 0; i < MANDATORY_FIELDS; ++i )
217 {
218 m_fields.emplace_back( pos, i, this, TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
219
220 if( i == REFERENCE_FIELD )
221 m_fields.back().SetLayer( LAYER_REFERENCEPART );
222 else if( i == VALUE_FIELD )
223 m_fields.back().SetLayer( LAYER_VALUEPART );
224 else
225 m_fields.back().SetLayer( LAYER_FIELDS );
226 }
227
228 m_prefix = wxString( wxT( "U" ) );
229 m_isInNetlist = true;
230 m_excludedFromSim = false;
231 m_excludedFromBOM = false;
232 m_excludedFromBoard = false;
233}
234
235
237{
238 return new SCH_SYMBOL( *this );
239}
240
241
243{
244 if( !m_part )
245 return true;
246
247 return false;
248}
249
250
251void SCH_SYMBOL::ViewGetLayers( int aLayers[], int& aCount ) const
252{
253 aCount = 8;
254 aLayers[0] = LAYER_DANGLING; // Pins are drawn by their parent symbol, so the parent
255 // symbol needs to draw to LAYER_DANGLING
256 aLayers[1] = LAYER_OP_CURRENTS; // Same for pin operating points
257 aLayers[2] = LAYER_DEVICE;
258 aLayers[3] = LAYER_REFERENCEPART;
259 aLayers[4] = LAYER_VALUEPART;
260 aLayers[5] = LAYER_FIELDS;
261 aLayers[6] = LAYER_DEVICE_BACKGROUND;
262 aLayers[7] = LAYER_SELECTION_SHADOWS;
263}
264
265
267{
268 // If a symbol's anchor is not grid-aligned to its pins then moving from the anchor is
269 // going to end up moving the symbol's pins off-grid.
270
271 // The minimal grid size allowed to place a pin is 25 mils
272 const int min_grid_size = schIUScale.MilsToIU( 25 );
273
274 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
275 {
276 if( ( ( pin->GetPosition().x - m_pos.x ) % min_grid_size ) != 0 )
277 return false;
278
279 if( ( ( pin->GetPosition().y - m_pos.y ) % min_grid_size ) != 0 )
280 return false;
281 }
282
283 return true;
284}
285
286
287void SCH_SYMBOL::SetLibId( const LIB_ID& aLibId )
288{
289 m_lib_id = aLibId;
290}
291
292
294{
295 if( !m_schLibSymbolName.IsEmpty() )
296 return m_schLibSymbolName;
297 else
298 return m_lib_id.Format();
299}
300
301
303{
304 wxCHECK2( ( aLibSymbol == nullptr ) || ( aLibSymbol->IsRoot() ), aLibSymbol = nullptr );
305
306 m_part.reset( aLibSymbol );
307 UpdatePins();
308}
309
310
312{
313 if( m_part )
314 return m_part->GetDescription();
315
316 return wxEmptyString;
317}
318
319
321{
322 if( m_part )
323 return m_part->GetKeyWords();
324
325 return wxEmptyString;
326}
327
328
330{
331 if( m_part )
332 return m_part->GetDatasheetField().GetText();
333
334 return wxEmptyString;
335}
336
337
339{
340 std::map<wxString, wxString> altPinMap;
341 std::map<wxString, std::set<SCH_PIN*>> pinUuidMap;
342 std::set<SCH_PIN*> unassignedSchPins;
343 std::set<LIB_PIN*> unassignedLibPins;
344
345 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
346 {
347 pinUuidMap[ pin->GetNumber() ].insert( pin.get() );
348
349 unassignedSchPins.insert( pin.get() );
350
351 if( !pin->GetAlt().IsEmpty() )
352 altPinMap[ pin->GetNumber() ] = pin->GetAlt();
353 }
354
355 m_pinMap.clear();
356
357 if( !m_part )
358 return;
359
360 std::vector<LIB_PIN*> pins = m_part->GetAllLibPins();
361
362 for( LIB_PIN* libPin : pins )
363 {
364 // NW: Don't filter by unit: this data-structure is used for all instances,
365 // some of which might have different units.
366 if( libPin->GetConvert() && m_convert && m_convert != libPin->GetConvert() )
367 continue;
368
369 SCH_PIN* pin = nullptr;
370
371 auto ii = pinUuidMap.find( libPin->GetNumber() );
372
373 if( ii == pinUuidMap.end() || ii->second.empty() )
374 {
375 unassignedLibPins.insert( libPin );
376 continue;
377 }
378
379 auto it = ii->second.begin();
380 pin = *it;
381 ii->second.erase( it );
382 pin->SetLibPin( libPin );
383 pin->SetPosition( libPin->GetPosition() );
384
385 unassignedSchPins.erase( pin );
386
387 auto iii = altPinMap.find( libPin->GetNumber() );
388
389 if( iii != altPinMap.end() )
390 pin->SetAlt( iii->second );
391
392 m_pinMap[ libPin ] = pin;
393 }
394
395 // Add any pins that were not found in the symbol
396 for( LIB_PIN* libPin : unassignedLibPins )
397 {
398 SCH_PIN* pin = nullptr;
399
400 // First try to re-use an existing pin
401 if( !unassignedSchPins.empty() )
402 {
403 auto it = unassignedSchPins.begin();
404 pin = *it;
405 unassignedSchPins.erase( it );
406 }
407 else
408 {
409 // This is a pin that was not found in the symbol, so create a new one.
410 pin = m_pins.emplace_back( std::make_unique<SCH_PIN>( SCH_PIN( libPin, this ) ) ).get();
411 }
412
413 m_pinMap[ libPin ] = pin;
414 pin->SetLibPin( libPin );
415 pin->SetPosition( libPin->GetPosition() );
416 pin->SetNumber( libPin->GetNumber() );
417
418 auto iii = altPinMap.find( libPin->GetNumber() );
419
420 if( iii != altPinMap.end() )
421 pin->SetAlt( iii->second );
422 }
423
424 // If we have any pins left in the symbol that were not found in the library, remove them.
425 for( auto it1 = m_pins.begin(); it1 != m_pins.end() && !unassignedSchPins.empty(); )
426 {
427 auto it2 = unassignedSchPins.find( it1->get() );
428
429 if( it2 != unassignedSchPins.end() )
430 {
431 it1 = m_pins.erase( it1 );
432 unassignedSchPins.erase( it2 );
433 }
434 else
435 {
436 ++it1;
437 }
438 }
439}
440
441
442void SCH_SYMBOL::SetUnit( int aUnit )
443{
444 UpdateUnit( aUnit );
445}
446
447
448void SCH_SYMBOL::UpdateUnit( int aUnit )
449{
450 m_unit = aUnit;
451}
452
453
454void SCH_SYMBOL::SetConvert( int aConvert )
455{
456 if( m_convert != aConvert )
457 {
458 m_convert = aConvert;
459
460 // The convert may have a different pin layout so the update the pin map.
461 UpdatePins();
462 }
463}
464
465
466void SCH_SYMBOL::SetTransform( const TRANSFORM& aTransform )
467{
468 if( m_transform != aTransform )
469 m_transform = aTransform;
470}
471
472
474{
475 if( m_part )
476 return m_part->GetUnitCount();
477
478 return 0;
479}
480
481
483{
484 wxCHECK( m_part, ( wxString::Format( _( "Unit %s" ), LIB_SYMBOL::SubReference( aUnit ) ) ) );
485
486 return m_part->GetUnitDisplayName( aUnit );
487}
488
489
491{
492 wxCHECK( m_part, false );
493
494 return m_part->HasUnitDisplayName( aUnit );
495}
496
497
498void SCH_SYMBOL::PrintBackground( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
499{
501 opts.transform = m_transform;
502 opts.draw_visible_fields = false;
503 opts.draw_hidden_fields = false;
504
505 if( m_part )
506 m_part->PrintBackground( aSettings, m_pos + aOffset, m_unit, m_convert, opts, GetDNP() );
507}
508
509
510void SCH_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
511{
513 opts.transform = m_transform;
514 opts.draw_visible_fields = false;
515 opts.draw_hidden_fields = false;
516
517 if( m_part )
518 {
519 LIB_PINS libPins;
520 m_part->GetPins( libPins, m_unit, m_convert );
521
522 LIB_SYMBOL tempSymbol( *m_part );
523 LIB_PINS tempPins;
524 tempSymbol.GetPins( tempPins, m_unit, m_convert );
525
526 // Copy the pin info from the symbol to the temp pins
527 for( unsigned i = 0; i < tempPins.size(); ++ i )
528 {
529 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
530 LIB_PIN* tempPin = tempPins[ i ];
531
532 tempPin->SetName( symbolPin->GetShownName() );
533 tempPin->SetType( symbolPin->GetType() );
534 tempPin->SetShape( symbolPin->GetShape() );
535 }
536
537 tempSymbol.Print( aSettings, m_pos + aOffset, m_unit, m_convert, opts, GetDNP() );
538 }
539 else // Use dummy() part if the actual cannot be found.
540 {
541 dummy()->Print( aSettings, m_pos + aOffset, 0, 0, opts, GetDNP() );
542 }
543
544 for( SCH_FIELD& field : m_fields )
545 field.Print( aSettings, aOffset );
546
547 if( m_DNP )
548 {
550 wxDC* DC = aSettings->GetPrintDC();
551 COLOR4D dnp_color = aSettings->GetLayerColor( LAYER_DNP_MARKER );
552
553 GRFilledSegment( DC, bbox.GetOrigin(), bbox.GetEnd(),
555 dnp_color );
556
557 GRFilledSegment( DC, bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
558 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
560 dnp_color );
561 }
562}
563
564
566 const KIID_PATH& aSheetPath, bool aTestFromEnd ) const
567{
568 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
569 {
570 if( !aTestFromEnd )
571 {
572 if( instance.m_Path == aSheetPath )
573 {
574 aInstance = instance;
575 return true;
576 }
577 }
578 else if( instance.m_Path.EndsWith( aSheetPath ) )
579 {
580 aInstance = instance;
581 return true;
582 }
583 }
584
585 return false;
586}
587
588
589void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
590{
591 // Search for an existing path and remove it if found (should not occur)
592 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
593 {
594 if( m_instanceReferences[ii].m_Path == aInstancePath.Path() )
595 {
596 wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
597 " sheet path %s\n"
598 " reference %s, unit %d from symbol %s.",
599 aInstancePath.Path().AsString(),
600 m_instanceReferences[ii].m_Reference,
601 m_instanceReferences[ii].m_Unit,
602 m_Uuid.AsString() );
603
604 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
605 ii--;
606 }
607 }
608}
609
610
611void SCH_SYMBOL::SortInstances( bool (*aSortFunction)( const SCH_SYMBOL_INSTANCE& aLhs,
612 const SCH_SYMBOL_INSTANCE& aRhs ) )
613{
614 std::sort( m_instanceReferences.begin(), m_instanceReferences.end(), aSortFunction );
615}
616
617
618void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef, int aUnit )
619{
620 // Search for an existing path and remove it if found (should not occur)
621 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
622 {
623 if( m_instanceReferences[ii].m_Path == aPath )
624 {
625 wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
626 " sheet path %s\n"
627 " reference %s, unit %d from symbol %s.",
628 aPath.AsString(),
629 m_instanceReferences[ii].m_Reference,
630 m_instanceReferences[ii].m_Unit,
631 m_Uuid.AsString() );
632
633 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
634 ii--;
635 }
636 }
637
638 SCH_SYMBOL_INSTANCE instance;
639 instance.m_Path = aPath;
640 instance.m_Reference = aRef;
641 instance.m_Unit = aUnit;
642
643 wxLogTrace( traceSchSheetPaths,
644 "Adding symbol '%s' instance:\n"
645 " sheet path '%s'\n"
646 " reference '%s'\n"
647 " unit %d\n",
649 aPath.AsString(),
650 aRef,
651 aUnit );
652
653 m_instanceReferences.push_back( instance );
654
655 // This should set the default instance to the first saved instance data for each symbol
656 // when importing sheets.
657 if( m_instanceReferences.size() == 1 )
658 {
659 m_fields[ REFERENCE_FIELD ].SetText( aRef );
660 m_unit = aUnit;
661 }
662}
663
664
666{
667 KIID_PATH searchPath( aInstance.m_Path );
668
669 std::vector<SCH_SYMBOL_INSTANCE>::iterator resultIt;
670
671 do
672 {
673 resultIt = std::find_if( m_instanceReferences.begin(), m_instanceReferences.end(),
674 [searchPath]( const auto& it )
675 {
676 return it.m_Path == searchPath;
677 } );
678
679 if( resultIt != m_instanceReferences.end() )
680 {
681 wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
682 " sheet path %s\n"
683 " reference %s, unit %d from symbol %s.",
684 aInstance.m_Path.AsString(),
685 resultIt->m_Reference,
686 resultIt->m_Unit,
687 m_Uuid.AsString() );
688
689 // Instance data should be unique by path. Double check just in case there was
690 // some buggy code in the past.
691 resultIt = m_instanceReferences.erase( resultIt );
692 }
693 }
694 while( resultIt != m_instanceReferences.end() );
695
696 SCH_SYMBOL_INSTANCE instance = aInstance;
697
698 wxLogTrace( traceSchSheetPaths,
699 "Adding symbol '%s' instance:\n"
700 " sheet path '%s'\n"
701 " reference '%s'\n"
702 " unit %d\n",
704 instance.m_Path.AsString(),
705 instance.m_Reference,
706 instance.m_Unit );
707
708 m_instanceReferences.push_back( instance );
709
710 // This should set the default instance to the first saved instance data for each symbol
711 // when importing sheets.
712 if( m_instanceReferences.size() == 1 )
713 {
714 m_fields[ REFERENCE_FIELD ].SetText( instance.m_Reference );
715 m_unit = instance.m_Unit;
716 }
717}
718
719
720const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
721{
722 KIID_PATH path = sheet->Path();
723 wxString ref;
724 wxString subRef;
725
726 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
727 {
728 if( instance.m_Path == path )
729 {
730 ref = instance.m_Reference;
731 subRef = LIB_SYMBOL::SubReference( instance.m_Unit );
732 break;
733 }
734 }
735
736 // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
737 // use this as a default for this path. This will happen if we load a version 1 schematic
738 // file. It will also mean that multiple instances of the same sheet by default all have
739 // the same symbol references, but perhaps this is best.
740 if( ref.IsEmpty() && !GetField( REFERENCE_FIELD )->GetText().IsEmpty() )
741 {
742 const_cast<SCH_SYMBOL*>( this )->SetRef( sheet, GetField( REFERENCE_FIELD )->GetText() );
743 ref = GetField( REFERENCE_FIELD )->GetText();
744 }
745
746 if( ref.IsEmpty() )
748
749 if( aIncludeUnit && GetUnitCount() > 1 )
750 ref += subRef;
751
752 return ref;
753}
754
755
756bool SCH_SYMBOL::IsReferenceStringValid( const wxString& aReferenceString )
757{
758 return !UTIL::GetRefDesPrefix( aReferenceString ).IsEmpty();
759}
760
761
762void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
763{
764 KIID_PATH path = sheet->Path();
765 bool found = false;
766
767 // check to see if it is already there before inserting it
769 {
770 if( instance.m_Path == path )
771 {
772 found = true;
773 instance.m_Reference = ref;
774 break;
775 }
776 }
777
778 if( !found )
780
781 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
782 pin->ClearDefaultNetName( sheet );
783
784 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
785 m_fields[ REFERENCE_FIELD ].SetText( ref );
786
787 // Reinit the m_prefix member if needed
789
790 if( m_prefix.IsEmpty() )
791 m_prefix = wxT( "U" );
792
793 // Power symbols have references starting with # and are not included in netlists
794 m_isInNetlist = ! ref.StartsWith( wxT( "#" ) );
795}
796
797
799{
800 KIID_PATH path = aSheet->Path();
801
802 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
803 {
804 if( instance.m_Path == path )
805 return instance.m_Reference.Last() != '?';
806 }
807
808 return false;
809}
810
811
813{
814 wxString refDesignator = GetField( REFERENCE_FIELD )->GetText();
815
816 refDesignator.Replace( "~", " " );
817
818 wxString prefix = refDesignator;
819
820 while( prefix.Length() )
821 {
822 wxUniCharRef last = prefix.Last();
823
824 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
825 prefix.RemoveLast();
826 else
827 break;
828 }
829
830 // Avoid a prefix containing trailing/leading spaces
831 prefix.Trim( true );
832 prefix.Trim( false );
833
834 if( !prefix.IsEmpty() )
835 SetPrefix( prefix );
836}
837
838
840{
841 KIID_PATH path = aSheet->Path();
842
843 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
844 {
845 if( instance.m_Path == path )
846 return instance.m_Unit;
847 }
848
849 // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
850 // version 1 schematic file.
851 return m_unit;
852}
853
854
855void SCH_SYMBOL::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
856{
857 KIID_PATH path = aSheet->Path();
858
859 // check to see if it is already there before inserting it
861 {
862 if( instance.m_Path == path )
863 {
864 instance.m_Unit = aUnitSelection;
865 return;
866 }
867 }
868
869 // didn't find it; better add it
871}
872
873
874void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
875{
877 instance.m_Unit = aUnitSelection;
878}
879
880
881const wxString SCH_SYMBOL::GetValueFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
882 bool aAllowExtraText ) const
883{
884 if( aResolve )
885 return GetField( VALUE_FIELD )->GetShownText( aPath, aAllowExtraText );
886
887 return GetField( VALUE_FIELD )->GetText();
888}
889
890
891void SCH_SYMBOL::SetValueFieldText( const wxString& aValue )
892{
893 m_fields[ VALUE_FIELD ].SetText( aValue );
894}
895
896
897const wxString SCH_SYMBOL::GetFootprintFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
898 bool aAllowExtraText ) const
899{
900 if( aResolve )
901 return GetField( FOOTPRINT_FIELD )->GetShownText( aPath, aAllowExtraText );
902
903 return GetField( FOOTPRINT_FIELD )->GetText();
904}
905
906
907void SCH_SYMBOL::SetFootprintFieldText( const wxString& aFootprint )
908{
909 m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
910}
911
912
914{
915 return &m_fields[aFieldType];
916}
917
918
920{
921 return &m_fields[aFieldType];
922}
923
924
926{
927 for( size_t ii = 0; ii < m_fields.size(); ++ii )
928 {
929 if( m_fields[ii].GetId() == aFieldId )
930 return &m_fields[ii];
931 }
932
933 return nullptr;
934}
935
936
937SCH_FIELD* SCH_SYMBOL::GetFieldByName( const wxString& aFieldName )
938{
939 for( size_t ii = 0; ii < m_fields.size(); ++ii )
940 {
941 if( m_fields[ii].GetName() == aFieldName )
942 return &m_fields[ii];
943 }
944
945 return nullptr;
946}
947
948
949const SCH_FIELD* SCH_SYMBOL::GetFieldByName( const wxString& aFieldName ) const
950{
951 for( size_t ii = 0; ii < m_fields.size(); ++ii )
952 {
953 if( m_fields[ii].GetName() == aFieldName )
954 return &m_fields[ii];
955 }
956
957 return nullptr;
958}
959
960
961wxString SCH_SYMBOL::GetFieldText( const wxString& aFieldName ) const
962{
963 for( const SCH_FIELD& field : m_fields )
964 {
965 if( aFieldName == field.GetName() || aFieldName == field.GetCanonicalName() )
966 return field.GetText();
967 }
968
969 return wxEmptyString;
970}
971
972
973void SCH_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
974{
975 for( SCH_FIELD& field : m_fields )
976 {
977 if( aVisibleOnly )
978 {
979 if( !field.IsVisible() || field.GetShownText( nullptr, true ).IsEmpty() )
980 continue;
981 }
982
983 aVector.push_back( &field );
984 }
985}
986
987
989{
990 int newNdx = m_fields.size();
991
992 m_fields.push_back( aField );
993 return &m_fields[newNdx];
994}
995
996
997void SCH_SYMBOL::RemoveField( const wxString& aFieldName )
998{
999 for( unsigned i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
1000 {
1001 if( aFieldName == m_fields[i].GetName( false ) )
1002 {
1003 m_fields.erase( m_fields.begin() + i );
1004 return;
1005 }
1006 }
1007}
1008
1009
1010SCH_FIELD* SCH_SYMBOL::FindField( const wxString& aFieldName, bool aIncludeDefaultFields,
1011 bool aCaseInsensitive )
1012{
1013 unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
1014
1015 for( unsigned i = start; i < m_fields.size(); ++i )
1016 {
1017 if( aCaseInsensitive )
1018 {
1019 if( aFieldName.Upper() == m_fields[i].GetName( false ).Upper() )
1020 return &m_fields[i];
1021 }
1022 else
1023 {
1024 if( aFieldName == m_fields[i].GetName( false ) )
1025 return &m_fields[i];
1026 }
1027 }
1028
1029 return nullptr;
1030}
1031
1032
1033void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef,
1034 bool aUpdateOtherFields, bool aResetRef, bool aResetOtherFields )
1035{
1036 if( m_part )
1037 {
1038 std::vector<LIB_FIELD*> fields;
1039
1040 m_part->GetFields( fields );
1041
1042 for( const LIB_FIELD* libField : fields )
1043 {
1044 int id = libField->GetId();
1045 SCH_FIELD* schField;
1046
1047 if( id >= 0 && id < MANDATORY_FIELDS )
1048 {
1049 schField = GetFieldById( id );
1050 }
1051 else
1052 {
1053 schField = FindField( libField->GetCanonicalName() );
1054
1055 if( !schField )
1056 {
1057 wxString fieldName = libField->GetCanonicalName();
1058 SCH_FIELD newField( VECTOR2I( 0, 0 ), GetFieldCount(), this, fieldName );
1059 schField = AddField( newField );
1060 }
1061 }
1062
1063 if( aUpdateStyle )
1064 {
1065 schField->ImportValues( *libField );
1066 schField->SetTextPos( m_pos + libField->GetTextPos() );
1067 }
1068
1069 if( id == REFERENCE_FIELD && aPath )
1070 {
1071 if( aResetRef )
1072 SetRef( aPath, m_part->GetReferenceField().GetText() );
1073 else if( aUpdateRef )
1074 SetRef( aPath, libField->GetText() );
1075 }
1076 else if( id == VALUE_FIELD )
1077 {
1078 SetValueFieldText( UnescapeString( libField->GetText() ) );
1079 }
1080 else if( id == FOOTPRINT_FIELD )
1081 {
1082 if( aResetOtherFields || aUpdateOtherFields )
1083 SetFootprintFieldText( libField->GetText() );
1084 }
1085 else if( id == DATASHEET_FIELD )
1086 {
1087 if( aResetOtherFields )
1088 schField->SetText( GetDatasheet() ); // alias-specific value
1089 else if( aUpdateOtherFields )
1090 schField->SetText( libField->GetText() );
1091 }
1092 else
1093 {
1094 if( aResetOtherFields || aUpdateOtherFields )
1095 schField->SetText( libField->GetText() );
1096 }
1097 }
1098 }
1099}
1100
1101
1102void SCH_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
1103{
1104 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1105 aFunction( pin.get() );
1106
1107 for( SCH_FIELD& field : m_fields )
1108 aFunction( &field );
1109}
1110
1111
1112SCH_PIN* SCH_SYMBOL::GetPin( const wxString& aNumber ) const
1113{
1114 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1115 {
1116 if( pin->GetNumber() == aNumber )
1117 return pin.get();
1118 }
1119
1120 return nullptr;
1121}
1122
1123
1124void SCH_SYMBOL::GetLibPins( std::vector<LIB_PIN*>& aPinsList ) const
1125{
1126 if( m_part )
1127 m_part->GetPins( aPinsList, m_unit, m_convert );
1128}
1129
1130
1131std::vector<LIB_PIN*> SCH_SYMBOL::GetAllLibPins() const
1132{
1133 std::vector<LIB_PIN*> pinList;
1134
1135 if( m_part )
1136 m_part->GetPins( pinList, 0, 0 );
1137
1138 return pinList;
1139}
1140
1141
1143{
1144 auto it = m_pinMap.find( aLibPin );
1145
1146 if( it != m_pinMap.end() )
1147 return it->second;
1148
1149 wxFAIL_MSG_AT( "Pin not found", __FILE__, __LINE__, __FUNCTION__ );
1150 return nullptr;
1151}
1152
1153
1154std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
1155{
1156 std::vector<SCH_PIN*> pins;
1157
1158 if( aSheet == nullptr )
1159 {
1160 wxCHECK_MSG( Schematic(), pins, "Can't call GetPins on a symbol with no schematic" );
1161
1162 aSheet = &Schematic()->CurrentSheet();
1163 }
1164
1165 int unit = GetUnitSelection( aSheet );
1166
1167 for( const std::unique_ptr<SCH_PIN>& p : m_pins )
1168 {
1169 if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
1170 continue;
1171
1172 pins.push_back( p.get() );
1173 }
1174
1175 return pins;
1176}
1177
1178
1180{
1181 SCH_ITEM::SwapFlags( aItem );
1182
1183 wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T,
1184 wxT( "Cannot swap data with invalid symbol." ) );
1185
1186 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
1187
1188 std::swap( m_lib_id, symbol->m_lib_id );
1189
1190 m_pins.swap( symbol->m_pins ); // std::vector's swap()
1191
1192 for( std::unique_ptr<SCH_PIN>& pin : symbol->m_pins )
1193 pin->SetParent( symbol );
1194
1195 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1196 pin->SetParent( this );
1197
1198 LIB_SYMBOL* libSymbol = symbol->m_part.release();
1199 symbol->m_part = std::move( m_part );
1200 symbol->UpdatePins();
1201 m_part.reset( libSymbol );
1202 UpdatePins();
1203
1204 std::swap( m_pos, symbol->m_pos );
1205 std::swap( m_unit, symbol->m_unit );
1206 std::swap( m_convert, symbol->m_convert );
1207
1208 m_fields.swap( symbol->m_fields ); // std::vector's swap()
1209
1210 for( SCH_FIELD& field : symbol->m_fields )
1211 field.SetParent( symbol );
1212
1213 for( SCH_FIELD& field : m_fields )
1214 field.SetParent( this );
1215
1216 TRANSFORM tmp = m_transform;
1217
1218 m_transform = symbol->m_transform;
1219 symbol->m_transform = tmp;
1220
1221 std::swap( m_excludedFromSim, symbol->m_excludedFromSim );
1222 std::swap( m_excludedFromBOM, symbol->m_excludedFromBOM );
1223 std::swap( m_DNP, symbol->m_DNP );
1224 std::swap( m_excludedFromBoard, symbol->m_excludedFromBoard );
1225
1226 std::swap( m_instanceReferences, symbol->m_instanceReferences );
1227 std::swap( m_schLibSymbolName, symbol->m_schLibSymbolName );
1228}
1229
1230
1231void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
1232{
1233 for( int i = 0; i < MANDATORY_FIELDS; ++i )
1234 aVars->push_back( m_fields[i].GetCanonicalName().Upper() );
1235
1236 for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
1237 aVars->push_back( m_fields[i].GetName() );
1238
1239 aVars->push_back( wxT( "OP" ) );
1240 aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
1241 aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
1242 aVars->push_back( wxT( "UNIT" ) );
1243 aVars->push_back( wxT( "SYMBOL_LIBRARY" ) );
1244 aVars->push_back( wxT( "SYMBOL_NAME" ) );
1245 aVars->push_back( wxT( "SYMBOL_DESCRIPTION" ) );
1246 aVars->push_back( wxT( "SYMBOL_KEYWORDS" ) );
1247 aVars->push_back( wxT( "EXCLUDE_FROM_BOM" ) );
1248 aVars->push_back( wxT( "EXCLUDE_FROM_BOARD" ) );
1249 aVars->push_back( wxT( "EXCLUDE_FROM_SIM" ) );
1250 aVars->push_back( wxT( "DNP" ) );
1251 aVars->push_back( wxT( "SHORT_NET_NAME(<pin_number>)" ) );
1252 aVars->push_back( wxT( "NET_NAME(<pin_number>)" ) );
1253 aVars->push_back( wxT( "NET_CLASS(<pin_number>)" ) );
1254 aVars->push_back( wxT( "PIN_NAME(<pin_number>)" ) );
1255}
1256
1257
1258bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
1259{
1260 static wxRegEx operatingPoint( wxT( "^"
1261 "OP"
1262 "(:[a-zA-Z]*)?" // port
1263 "(.([0-9])?([a-zA-Z]*))?" // format
1264 "$" ) );
1265
1266 SCHEMATIC* schematic = Schematic();
1267
1268 // SCH_SYMBOL object has no context outside a schematic and the instance on a path.
1269 if( !schematic || !aPath )
1270 return false;
1271
1272 if( operatingPoint.Matches( *token ) )
1273 {
1274 wxString port( operatingPoint.GetMatch( *token, 1 ) );
1275 wxString precisionStr( operatingPoint.GetMatch( *token, 3 ) );
1276 wxString range( operatingPoint.GetMatch( *token, 4 ) );
1277
1278 wxString signal = GetRef( aPath ) + port;
1279 int precision = 3;
1280
1281 if( !precisionStr.IsEmpty() )
1282 precision = precisionStr[0] - '0';
1283
1284 if( range.IsEmpty() )
1285 {
1286 if( port == wxS( ":power" ) )
1287 range = wxS( "~W" );
1288 else
1289 range = wxS( "~A" );
1290 }
1291
1292 *token = schematic->GetOperatingPoint( signal.Lower(), precision, range );
1293
1294 return true;
1295 }
1296
1297 if( token->Contains( ':' ) )
1298 {
1299 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
1300 return true;
1301 }
1302
1303 for( int i = 0; i < MANDATORY_FIELDS; ++i )
1304 {
1305 if( token->IsSameAs( m_fields[ i ].GetCanonicalName().Upper() ) )
1306 {
1307 if( i == REFERENCE_FIELD )
1308 *token = GetRef( aPath, true );
1309 else
1310 *token = m_fields[ i ].GetShownText( aPath, false, aDepth + 1 );
1311
1312 return true;
1313 }
1314 }
1315
1316 for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
1317 {
1318 if( token->IsSameAs( m_fields[ i ].GetName() )
1319 || token->IsSameAs( m_fields[ i ].GetName().Upper() ) )
1320 {
1321 *token = m_fields[ i ].GetShownText( aPath, false, aDepth + 1 );
1322 return true;
1323 }
1324 }
1325
1326 for( const TEMPLATE_FIELDNAME& templateFieldname :
1328 {
1329 if( token->IsSameAs( templateFieldname.m_Name )
1330 || token->IsSameAs( templateFieldname.m_Name.Upper() ) )
1331 {
1332 // If we didn't find it in the fields list then it isn't set on this symbol.
1333 // Just return an empty string.
1334 *token = wxEmptyString;
1335 return true;
1336 }
1337 }
1338
1339 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
1340 {
1341 wxString footprint = GetFootprintFieldText( true, aPath, false );
1342
1343 wxArrayString parts = wxSplit( footprint, ':' );
1344
1345 if( parts.Count() > 0 )
1346 *token = parts[ 0 ];
1347 else
1348 *token = wxEmptyString;
1349
1350 return true;
1351 }
1352 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
1353 {
1354 wxString footprint = GetFootprintFieldText( true, aPath, false );
1355
1356 wxArrayString parts = wxSplit( footprint, ':' );
1357
1358 if( parts.Count() > 1 )
1359 *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
1360 else
1361 *token = wxEmptyString;
1362
1363 return true;
1364 }
1365 else if( token->IsSameAs( wxT( "UNIT" ) ) )
1366 {
1367 int unit = GetUnitSelection( aPath );
1368
1369 *token = LIB_SYMBOL::SubReference( unit );
1370 return true;
1371 }
1372 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
1373 {
1375 return true;
1376 }
1377 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
1378 {
1380 return true;
1381 }
1382 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
1383 {
1384 *token = GetDescription();
1385 return true;
1386 }
1387 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
1388 {
1389 *token = GetKeyWords();
1390 return true;
1391 }
1392 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
1393 {
1394 *token = this->GetExcludedFromBOM() ? _( "Excluded from BOM" )
1395 : wxString( wxT( "" ) );
1396 return true;
1397 }
1398 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
1399 {
1400 *token = this->GetExcludedFromBoard() ? _( "Excluded from board" )
1401 : wxString( wxT( "" ) );
1402 return true;
1403 }
1404 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
1405 {
1406 *token = this->GetExcludedFromSim() ? _( "Excluded from simulation" )
1407 : wxString( wxT( "" ) );
1408 return true;
1409 }
1410 else if( token->IsSameAs( wxT( "DNP" ) ) )
1411 {
1412 *token = this->GetDNP() ? _( "DNP" ) : wxString( wxT( "" ) );
1413 return true;
1414 }
1415 else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) )
1416 || token->StartsWith( wxT( "NET_NAME(" ) )
1417 || token->StartsWith( wxT( "NET_CLASS(" ) )
1418 || token->StartsWith( wxT( "PIN_NAME(" ) ) )
1419 {
1420 wxString pinNumber = token->AfterFirst( '(' );
1421 pinNumber = pinNumber.BeforeLast( ')' );
1422
1423 for( SCH_PIN* pin : GetPins( aPath ) )
1424 {
1425 if( pin->GetNumber() == pinNumber )
1426 {
1427 if( token->StartsWith( wxT( "PIN_NAME" ) ) )
1428 {
1429 *token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
1430 return true;
1431 }
1432
1433 SCH_CONNECTION* conn = pin->Connection( aPath );
1434
1435 if( !conn )
1436 *token = wxEmptyString;
1437 else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
1438 *token = conn->LocalName();
1439 else if( token->StartsWith( wxT( "NET_NAME" ) ) )
1440 *token = conn->Name();
1441 else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
1442 *token = pin->GetEffectiveNetClass( aPath )->GetName();
1443
1444 return true;
1445 }
1446 }
1447 }
1448
1449 // See if parent can resolve it (this will recurse to ancestors)
1450 if( aPath->Last() && aPath->Last()->ResolveTextVar( aPath, token, aDepth + 1 ) )
1451 return true;
1452
1453 return false;
1454}
1455
1456
1457void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1458{
1459 if( aSheetPath )
1460 {
1461 KIID_PATH path = aSheetPath->Path();
1462
1463 for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1464 {
1465 if( instance.m_Path == path )
1466 {
1467 if( instance.m_Reference.IsEmpty() || aResetPrefix )
1468 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1469 else
1470 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1471 }
1472 }
1473 }
1474 else
1475 {
1476 for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1477 {
1478 if( instance.m_Reference.IsEmpty() || aResetPrefix)
1479 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1480 else
1481 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1482 }
1483 }
1484
1485 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1486 pin->ClearDefaultNetName( aSheetPath );
1487
1488 // These 2 changes do not work in complex hierarchy.
1489 // When a clear annotation is made, the calling function must call a
1490 // UpdateAllScreenReferences for the active sheet.
1491 // But this call cannot made here.
1492 wxString currentReference = m_fields[REFERENCE_FIELD].GetText();
1493
1494 if( currentReference.IsEmpty() || aResetPrefix )
1496 else
1497 m_fields[REFERENCE_FIELD].SetText( UTIL::GetRefDesUnannotated( currentReference ) );
1498}
1499
1500
1502{
1503 // An empty sheet path is illegal, at a minimum the root sheet UUID must be present.
1504 wxCHECK( aSheetPath.size() > 0, false );
1505
1506 for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
1507 {
1508 // if aSheetPath is found, nothing to do:
1509 if( instance.m_Path == aSheetPath )
1510 return false;
1511 }
1512
1513 // This entry does not exist: add it, with its last-used reference
1514 AddHierarchicalReference( aSheetPath, m_fields[REFERENCE_FIELD].GetText(), m_unit );
1515 return true;
1516}
1517
1518
1519void SCH_SYMBOL::SetOrientation( int aOrientation )
1520{
1521 TRANSFORM temp = TRANSFORM();
1522 bool transform = false;
1523
1524 switch( aOrientation )
1525 {
1526 case SYM_ORIENT_0:
1527 case SYM_NORMAL: // default transform matrix
1528 m_transform.x1 = 1;
1529 m_transform.y2 = -1;
1531 break;
1532
1533 case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
1534 temp.x1 = temp.y2 = 0;
1535 temp.y1 = 1;
1536 temp.x2 = -1;
1537 transform = true;
1538 break;
1539
1540 case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1541 temp.x1 = temp.y2 = 0;
1542 temp.y1 = -1;
1543 temp.x2 = 1;
1544 transform = true;
1545 break;
1546
1547 case SYM_MIRROR_Y: // Mirror Y (incremental rotation)
1548 temp.x1 = -1;
1549 temp.y2 = 1;
1550 temp.y1 = temp.x2 = 0;
1551 transform = true;
1552 break;
1553
1554 case SYM_MIRROR_X: // Mirror X (incremental rotation)
1555 temp.x1 = 1;
1556 temp.y2 = -1;
1557 temp.y1 = temp.x2 = 0;
1558 transform = true;
1559 break;
1560
1561 case SYM_ORIENT_90:
1564 break;
1565
1566 case SYM_ORIENT_180:
1570 break;
1571
1572 case SYM_ORIENT_270:
1575 break;
1576
1577 case ( SYM_ORIENT_0 + SYM_MIRROR_X ):
1580 break;
1581
1582 case ( SYM_ORIENT_0 + SYM_MIRROR_Y ):
1585 break;
1586
1587 case ( SYM_ORIENT_90 + SYM_MIRROR_X ):
1590 break;
1591
1592 case ( SYM_ORIENT_90 + SYM_MIRROR_Y ):
1595 break;
1596
1597 case ( SYM_ORIENT_180 + SYM_MIRROR_X ):
1600 break;
1601
1602 case ( SYM_ORIENT_180 + SYM_MIRROR_Y ):
1605 break;
1606
1607 case ( SYM_ORIENT_270 + SYM_MIRROR_X ):
1610 break;
1611
1612 case ( SYM_ORIENT_270 + SYM_MIRROR_Y ):
1615 break;
1616
1617 default:
1618 transform = false;
1619 wxFAIL_MSG( "Invalid schematic symbol orientation type." );
1620 break;
1621 }
1622
1623 if( transform )
1624 {
1625 /* The new matrix transform is the old matrix transform modified by the
1626 * requested transformation, which is the temp transform (rot,
1627 * mirror ..) in order to have (in term of matrix transform):
1628 * transform coord = new_m_transform * coord
1629 * where transform coord is the coord modified by new_m_transform from
1630 * the initial value coord.
1631 * new_m_transform is computed (from old_m_transform and temp) to
1632 * have:
1633 * transform coord = old_m_transform * temp
1634 */
1635 TRANSFORM newTransform;
1636
1637 newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1638 newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1639 newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1640 newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1641 m_transform = newTransform;
1642 }
1643}
1644
1645
1647{
1648 /*
1649 * This is slow, but also a bizarre algorithm. I don't feel like unteasing the algorithm right
1650 * now, so let's just cache it for the moment.
1651 */
1654
1655 int rotate_values[] =
1656 {
1669 };
1670
1671 // Try to find the current transform option:
1672 TRANSFORM transform = m_transform;
1673 SCH_SYMBOL temp( *this );
1674
1675 for( int type_rotate : rotate_values )
1676 {
1677 temp.SetOrientation( type_rotate );
1678
1679 if( transform == temp.GetTransform() )
1680 {
1682 return type_rotate;
1683 }
1684 }
1685
1686 // Error: orientation not found in list (should not happen)
1687 wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
1688
1689 return SYM_NORMAL;
1690}
1691
1692
1693#if defined(DEBUG)
1694
1695void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const
1696{
1697 // for now, make it look like XML:
1698 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1699 << " ref=\"" << TO_UTF8( GetField( REFERENCE_FIELD )->GetName() )
1700 << '"' << " chipName=\""
1701 << GetLibId().Format() << '"' << m_pos
1702 << " layer=\"" << m_layer
1703 << '"' << ">\n";
1704
1705 // skip the reference, it's been output already.
1706 for( int i = 1; i < GetFieldCount(); ++i )
1707 {
1708 const wxString& value = GetFields()[i].GetText();
1709
1710 if( !value.IsEmpty() )
1711 {
1712 NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
1713 << TO_UTF8( GetFields()[i].GetName() )
1714 << '"' << " value=\""
1715 << TO_UTF8( value ) << "\"/>\n";
1716 }
1717 }
1718
1719 NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
1720}
1721
1722#endif
1723
1724
1725BOX2I SCH_SYMBOL::doGetBoundingBox( bool aIncludePins, bool aIncludeFields ) const
1726{
1727 BOX2I bBox;
1728
1729 if( m_part )
1730 bBox = m_part->GetBodyBoundingBox( m_unit, m_convert, aIncludePins, false );
1731 else
1732 bBox = dummy()->GetBodyBoundingBox( m_unit, m_convert, aIncludePins, false );
1733
1734 int x0 = bBox.GetX();
1735 int xm = bBox.GetRight();
1736
1737 // We must reverse Y values, because matrix orientation
1738 // suppose Y axis normal for the library items coordinates,
1739 // m_transform reverse Y values, but bBox is already reversed!
1740 int y0 = -bBox.GetY();
1741 int ym = -bBox.GetBottom();
1742
1743 // Compute the real Boundary box (rotated, mirrored ...)
1744 int x1 = m_transform.x1 * x0 + m_transform.y1 * y0;
1745 int y1 = m_transform.x2 * x0 + m_transform.y2 * y0;
1746 int x2 = m_transform.x1 * xm + m_transform.y1 * ym;
1747 int y2 = m_transform.x2 * xm + m_transform.y2 * ym;
1748
1749 bBox.SetX( x1 );
1750 bBox.SetY( y1 );
1751 bBox.SetWidth( x2 - x1 );
1752 bBox.SetHeight( y2 - y1 );
1753 bBox.Normalize();
1754
1755 bBox.Offset( m_pos );
1756
1757 if( aIncludeFields )
1758 {
1759 for( const SCH_FIELD& field : m_fields )
1760 {
1761 if( field.IsVisible() )
1762 bBox.Merge( field.GetBoundingBox() );
1763 }
1764 }
1765
1766 return bBox;
1767}
1768
1769
1771{
1772 return doGetBoundingBox( false, false );
1773}
1774
1775
1777{
1778 return doGetBoundingBox( true, false );
1779}
1780
1781
1783{
1784 return doGetBoundingBox( true, true );
1785}
1786
1787
1788void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1789{
1790 wxString msg;
1791
1792 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1793 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
1794
1795 auto addExcludes =
1796 [&]()
1797 {
1798 wxArrayString msgs;
1799
1800 if( GetExcludedFromSim() )
1801 msgs.Add( _( "Simulation" ) );
1802
1803 if( GetExcludedFromBOM() )
1804 msgs.Add( _( "BOM" ) );
1805
1806 if( GetExcludedFromBoard() )
1807 msgs.Add( _( "Board" ) );
1808
1809 if( GetDNP() )
1810 msgs.Add( _( "DNP" ) );
1811
1812 msg = wxJoin( msgs, '|' );
1813 msg.Replace( '|', wxS( ", " ) );
1814
1815 if( !msg.empty() )
1816 aList.emplace_back( _( "Exclude from" ), msg );
1817 };
1818
1819 // part and alias can differ if alias is not the root
1820 if( m_part )
1821 {
1822 if( m_part.get() != dummy() )
1823 {
1824 if( m_part->IsPower() )
1825 {
1826 // Don't use GetShownText(); we want to see the variable references here
1827 aList.emplace_back( _( "Power symbol" ),
1828 KIUI::EllipsizeStatusText( aFrame, GetField( VALUE_FIELD )->GetText() ) );
1829 }
1830 else
1831 {
1832 aList.emplace_back( _( "Reference" ),
1833 UnescapeString( GetRef( currentSheet ) ) );
1834
1835 // Don't use GetShownText(); we want to see the variable references here
1836 aList.emplace_back( _( "Value" ),
1837 KIUI::EllipsizeStatusText( aFrame, GetField( VALUE_FIELD )->GetText() ) );
1838 addExcludes();
1839 aList.emplace_back( _( "Name" ),
1840 KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) );
1841 }
1842
1843#if 0 // Display symbol flags, for debug only
1844 aList.emplace_back( _( "flags" ), wxString::Format( "%X", GetEditFlags() ) );
1845#endif
1846
1847 if( !m_part->IsRoot() )
1848 {
1849 msg = _( "Missing parent" );
1850
1851 std::shared_ptr< LIB_SYMBOL > parent = m_part->GetParent().lock();
1852
1853 if( parent )
1854 msg = parent->GetName();
1855
1856 aList.emplace_back( _( "Derived from" ), UnescapeString( msg ) );
1857 }
1858 else if( !m_lib_id.GetLibNickname().empty() )
1859 {
1860 aList.emplace_back( _( "Library" ), m_lib_id.GetLibNickname() );
1861 }
1862 else
1863 {
1864 aList.emplace_back( _( "Library" ), _( "Undefined!!!" ) );
1865 }
1866
1867 // Display the current associated footprint, if exists.
1868 // Don't use GetShownText(); we want to see the variable references here
1869 msg = KIUI::EllipsizeStatusText( aFrame, GetField( FOOTPRINT_FIELD )->GetText() );
1870
1871 if( msg.IsEmpty() )
1872 msg = _( "<Unknown>" );
1873
1874 aList.emplace_back( _( "Footprint" ), msg );
1875
1876 // Display description of the symbol, and keywords found in lib
1877 aList.emplace_back( _( "Description" ) + wxT( ": " )
1878 + GetField( DESCRIPTION_FIELD )->GetText(),
1879 _( "Keywords" ) + wxT( ": " ) + m_part->GetKeyWords() );
1880 }
1881 }
1882 else
1883 {
1884 aList.emplace_back( _( "Reference" ), GetRef( currentSheet ) );
1885 // Don't use GetShownText(); we want to see the variable references here
1886 aList.emplace_back( _( "Value" ),
1887 KIUI::EllipsizeStatusText( aFrame, GetField( VALUE_FIELD )->GetText() ) );
1888 addExcludes();
1889 aList.emplace_back( _( "Name" ),
1890 KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) );
1891
1892 wxString libNickname = GetLibId().GetLibNickname();
1893
1894 if( libNickname.empty() )
1895 msg = _( "No library defined!" );
1896 else
1897 msg.Printf( _( "Symbol not found in %s!" ), libNickname );
1898
1899 aList.emplace_back( _( "Library" ), msg );
1900 }
1901}
1902
1903
1905{
1906 return BITMAPS::add_component;
1907}
1908
1909
1911{
1912 int dx = m_pos.x;
1913
1915 MIRROR( m_pos.x, aCenter );
1916 dx -= m_pos.x; // dx,0 is the move vector for this transform
1917
1918 for( SCH_FIELD& field : m_fields )
1919 {
1920 // Move the fields to the new position because the symbol itself has moved.
1921 VECTOR2I pos = field.GetTextPos();
1922 pos.x -= dx;
1923 field.SetTextPos( pos );
1924 }
1925}
1926
1927
1929{
1930 int dy = m_pos.y;
1931
1933 MIRROR( m_pos.y, aCenter );
1934 dy -= m_pos.y; // 0,dy is the move vector for this transform
1935
1936 for( SCH_FIELD& field : m_fields )
1937 {
1938 // Move the fields to the new position because the symbol itself has moved.
1939 VECTOR2I pos = field.GetTextPos();
1940 pos.y -= dy;
1941 field.SetTextPos( pos );
1942 }
1943}
1944
1945
1946void SCH_SYMBOL::Rotate( const VECTOR2I& aCenter )
1947{
1948 VECTOR2I prev = m_pos;
1949
1950 RotatePoint( m_pos, aCenter, ANGLE_90 );
1951
1953
1954 for( SCH_FIELD& field : m_fields )
1955 {
1956 // Move the fields to the new position because the symbol itself has moved.
1957 VECTOR2I pos = field.GetTextPos();
1958 pos.x -= prev.x - m_pos.x;
1959 pos.y -= prev.y - m_pos.y;
1960 field.SetTextPos( pos );
1961 }
1962}
1963
1964
1965bool SCH_SYMBOL::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
1966{
1967 // Symbols are searchable via the child field and pin item text.
1968 return false;
1969}
1970
1971
1972void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1973{
1974 for( auto& pin : m_pins )
1975 {
1976 LIB_PIN* lib_pin = pin->GetLibPin();
1977
1978 if( lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
1979 continue;
1980
1981 DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
1982 aItemList.push_back( item );
1983 }
1984}
1985
1986
1987bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
1988 const SCH_SHEET_PATH* aPath )
1989{
1990 bool changed = false;
1991
1992 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1993 {
1994 bool previousState = pin->IsDangling();
1995 pin->SetIsDangling( true );
1996
1997 VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
1998
1999 for( DANGLING_END_ITEM& each_item : aItemList )
2000 {
2001 // Some people like to stack pins on top of each other in a symbol to indicate
2002 // internal connection. While technically connected, it is not particularly useful
2003 // to display them that way, so skip any pins that are in the same symbol as this
2004 // one.
2005 if( each_item.GetParent() == this )
2006 continue;
2007
2008 switch( each_item.GetType() )
2009 {
2010 case PIN_END:
2011 case LABEL_END:
2012 case SHEET_LABEL_END:
2013 case WIRE_END:
2014 case NO_CONNECT_END:
2015 case JUNCTION_END:
2016
2017 if( pos == each_item.GetPosition() )
2018 pin->SetIsDangling( false );
2019
2020 break;
2021
2022 default:
2023 break;
2024 }
2025
2026 if( !pin->IsDangling() )
2027 break;
2028 }
2029
2030 changed = ( changed || ( previousState != pin->IsDangling() ) );
2031 }
2032
2033 return changed;
2034}
2035
2036
2038{
2039 wxCHECK_MSG( Pin != nullptr && Pin->Type() == LIB_PIN_T, VECTOR2I( 0, 0 ),
2040 wxT( "Cannot get physical position of pin." ) );
2041
2043}
2044
2045
2046std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
2047{
2048 std::vector<VECTOR2I> retval;
2049
2050 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2051 {
2052 // Collect only pins attached to the current unit and convert.
2053 // others are not associated to this symbol instance
2054 int pin_unit = pin->GetLibPin()->GetUnit();
2055 int pin_convert = pin->GetLibPin()->GetConvert();
2056
2057 if( pin_unit > 0 && pin_unit != GetUnit() )
2058 continue;
2059
2060 if( pin_convert > 0 && pin_convert != GetConvert() )
2061 continue;
2062
2063 retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos );
2064 }
2065
2066 return retval;
2067}
2068
2069
2071{
2072 if( m_part )
2073 {
2074 // Calculate the position relative to the symbol.
2075 VECTOR2I libPosition = aPosition - m_pos;
2076
2077 return m_part->LocateDrawItem( m_unit, m_convert, aType, libPosition, m_transform );
2078 }
2079
2080 return nullptr;
2081}
2082
2083
2084wxString SCH_SYMBOL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
2085{
2086 return wxString::Format( _( "Symbol %s [%s]" ),
2088 KIUI::EllipsizeMenuText( GetLibId().GetLibItemName() ) );
2089}
2090
2091
2092INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData,
2093 const std::vector<KICAD_T>& aScanTypes )
2094{
2095 for( KICAD_T scanType : aScanTypes )
2096 {
2097 if( scanType == SCH_LOCATE_ANY_T
2098 || ( scanType == SCH_SYMBOL_T )
2099 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
2100 {
2101 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
2102 return INSPECT_RESULT::QUIT;
2103 }
2104
2105 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
2106 {
2107 for( SCH_FIELD& field : m_fields )
2108 {
2109 if( INSPECT_RESULT::QUIT == aInspector( &field, (void*) this ) )
2110 return INSPECT_RESULT::QUIT;
2111 }
2112 }
2113
2114 if( scanType == SCH_FIELD_LOCATE_REFERENCE_T )
2115 {
2116 if( INSPECT_RESULT::QUIT == aInspector( GetField( REFERENCE_FIELD ), (void*) this ) )
2117 return INSPECT_RESULT::QUIT;
2118 }
2119
2120 if( scanType == SCH_FIELD_LOCATE_VALUE_T
2121 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
2122 {
2123 if( INSPECT_RESULT::QUIT == aInspector( GetField( VALUE_FIELD ), (void*) this ) )
2124 return INSPECT_RESULT::QUIT;
2125 }
2126
2127 if( scanType == SCH_FIELD_LOCATE_FOOTPRINT_T )
2128 {
2129 if( INSPECT_RESULT::QUIT == aInspector( GetField( FOOTPRINT_FIELD ), (void*) this ) )
2130 return INSPECT_RESULT::QUIT;
2131 }
2132
2133 if( scanType == SCH_FIELD_LOCATE_DATASHEET_T )
2134 {
2135 if( INSPECT_RESULT::QUIT == aInspector( GetField( DATASHEET_FIELD ), (void*) this ) )
2136 return INSPECT_RESULT::QUIT;
2137 }
2138
2139 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_PIN_T )
2140 {
2141 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2142 {
2143 // Collect only pins attached to the current unit and convert.
2144 // others are not associated to this symbol instance
2145 int pin_unit = pin->GetLibPin()->GetUnit();
2146 int pin_convert = pin->GetLibPin()->GetConvert();
2147
2148 if( pin_unit > 0 && pin_unit != GetUnit() )
2149 continue;
2150
2151 if( pin_convert > 0 && pin_convert != GetConvert() )
2152 continue;
2153
2154 if( INSPECT_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
2155 return INSPECT_RESULT::QUIT;
2156 }
2157 }
2158 }
2159
2160 return INSPECT_RESULT::CONTINUE;
2161}
2162
2163
2164bool SCH_SYMBOL::operator <( const SCH_ITEM& aItem ) const
2165{
2166 if( Type() != aItem.Type() )
2167 return Type() < aItem.Type();
2168
2169 auto symbol = static_cast<const SCH_SYMBOL*>( &aItem );
2170
2172
2173 if( rect.GetArea() != symbol->GetBodyAndPinsBoundingBox().GetArea() )
2174 return rect.GetArea() < symbol->GetBodyAndPinsBoundingBox().GetArea();
2175
2176 if( m_pos.x != symbol->m_pos.x )
2177 return m_pos.x < symbol->m_pos.x;
2178
2179 if( m_pos.y != symbol->m_pos.y )
2180 return m_pos.y < symbol->m_pos.y;
2181
2182 return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
2183}
2184
2185
2186bool SCH_SYMBOL::operator==( const SCH_SYMBOL& aSymbol ) const
2187{
2188 if( GetFieldCount() != aSymbol.GetFieldCount() )
2189 return false;
2190
2191 for( int i = VALUE_FIELD; i < GetFieldCount(); i++ )
2192 {
2193 if( GetFields()[i].GetText().Cmp( aSymbol.GetFields()[i].GetText() ) != 0 )
2194 return false;
2195 }
2196
2197 return true;
2198}
2199
2200
2201bool SCH_SYMBOL::operator!=( const SCH_SYMBOL& aSymbol ) const
2202{
2203 return !( *this == aSymbol );
2204}
2205
2206
2208{
2209 wxCHECK_MSG( Type() == aItem.Type(), *this,
2210 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
2211 GetClass() );
2212
2213 if( &aItem != this )
2214 {
2215 SCH_ITEM::operator=( aItem );
2216
2217 SCH_SYMBOL* c = (SCH_SYMBOL*) &aItem;
2218
2219 m_lib_id = c->m_lib_id;
2220
2221 LIB_SYMBOL* libSymbol = c->m_part ? new LIB_SYMBOL( *c->m_part.get() ) : nullptr;
2222
2223 m_part.reset( libSymbol );
2224 m_pos = c->m_pos;
2225 m_unit = c->m_unit;
2226 m_convert = c->m_convert;
2228
2230
2231 m_fields = c->m_fields; // std::vector's assignment operator
2232
2233 // Reparent fields after assignment to new symbol.
2234 for( SCH_FIELD& field : m_fields )
2235 field.SetParent( this );
2236
2237 UpdatePins();
2238 }
2239
2240 return *this;
2241}
2242
2243
2244bool SCH_SYMBOL::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2245{
2246 BOX2I bBox = GetBodyBoundingBox();
2247 bBox.Inflate( aAccuracy / 2 );
2248
2249 if( bBox.Contains( aPosition ) )
2250 return true;
2251
2252 return false;
2253}
2254
2255
2256bool SCH_SYMBOL::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2257{
2259 return false;
2260
2261 BOX2I rect = aRect;
2262
2263 rect.Inflate( aAccuracy / 2 );
2264
2265 if( aContained )
2266 return rect.Contains( GetBodyBoundingBox() );
2267
2268 return rect.Intersects( GetBodyBoundingBox() );
2269}
2270
2271
2272bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
2273{
2275
2276 for( const auto& pin : m_pins )
2277 {
2278 if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
2279 continue;
2280
2281 // Collect only pins attached to the current unit and convert.
2282 // others are not associated to this symbol instance
2283 int pin_unit = pin->GetLibPin()->GetUnit();
2284 int pin_convert = pin->GetLibPin()->GetConvert();
2285
2286 if( pin_unit > 0 && pin_unit != GetUnit() )
2287 continue;
2288
2289 if( pin_convert > 0 && pin_convert != GetConvert() )
2290 continue;
2291
2292 if( pin->GetLocalPosition() == new_pos )
2293 return true;
2294 }
2295
2296 return false;
2297}
2298
2299
2301{
2302 return m_isInNetlist;
2303}
2304
2305
2306void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground ) const
2307{
2308 if( aBackground )
2309 return;
2310
2311 if( m_part )
2312 {
2313 LIB_PINS libPins;
2314 m_part->GetPins( libPins, GetUnit(), GetConvert() );
2315
2316 // Copy the source so we can re-orient and translate it.
2317 LIB_SYMBOL tempSymbol( *m_part );
2318 LIB_PINS tempPins;
2319 tempSymbol.GetPins( tempPins, GetUnit(), GetConvert() );
2320
2321 // Copy the pin info from the symbol to the temp pins
2322 for( unsigned i = 0; i < tempPins.size(); ++ i )
2323 {
2324 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2325 LIB_PIN* tempPin = tempPins[ i ];
2326
2327 tempPin->SetName( symbolPin->GetShownName() );
2328 tempPin->SetType( symbolPin->GetType() );
2329 tempPin->SetShape( symbolPin->GetShape() );
2330
2331 if( symbolPin->IsDangling() )
2332 tempPin->SetFlags( IS_DANGLING );
2333 }
2334
2335 for( LIB_ITEM& item : tempSymbol.GetDrawItems() )
2336 {
2337 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( &item ) )
2338 {
2339 // Use SCH_FIELD's text resolver
2340 SCH_FIELD dummy( (SCH_ITEM*) this, -1 );
2341 dummy.SetText( text->GetText() );
2342 text->SetText( dummy.GetShownText( false ) );
2343 }
2344 }
2345
2346 TRANSFORM temp = GetTransform();
2347 aPlotter->StartBlock( nullptr );
2348
2349 for( bool local_background : { true, false } )
2350 {
2351 tempSymbol.Plot( aPlotter, GetUnit(), GetConvert(), local_background, m_pos, temp,
2352 GetDNP() );
2353
2354 for( SCH_FIELD field : m_fields )
2355 {
2356 field.ClearRenderCache();
2357 field.Plot( aPlotter, local_background );
2358 }
2359 }
2360
2361 if( m_DNP )
2362 PlotDNP( aPlotter );
2363
2364 // Plot attributes to a hypertext menu
2365 std::vector<wxString> properties;
2366 SCH_SHEET_PATH* sheet = &Schematic()->CurrentSheet();
2367
2368 for( const SCH_FIELD& field : GetFields() )
2369 {
2370 wxString text_field = field.GetShownText( sheet, false);
2371
2372 if( text_field.IsEmpty() )
2373 continue;
2374
2375 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2376 field.GetName(), text_field ) );
2377 }
2378
2379 if( !m_part->GetKeyWords().IsEmpty() )
2380 {
2381 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2382 _( "Keywords" ),
2383 m_part->GetKeyWords() ) );
2384 }
2385
2386 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
2387
2388
2389
2390 aPlotter->EndBlock( nullptr );
2391
2392 if( !m_part->IsPower() )
2393 aPlotter->Bookmark( GetBoundingBox(), GetRef( sheet ), _( "Symbols" ) );
2394 }
2395}
2396
2397
2398void SCH_SYMBOL::PlotDNP( PLOTTER* aPlotter ) const
2399{
2401
2402 COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
2403
2404 aPlotter->SetColor( colors->GetColor( LAYER_DNP_MARKER ) );
2405
2406 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(),
2408 FILLED, nullptr );
2409
2410 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
2411 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
2413 FILLED, nullptr );
2414}
2415
2416
2417void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter ) const
2418{
2419 if( m_part )
2420 {
2421 LIB_PINS libPins;
2422 m_part->GetPins( libPins, GetUnit(), GetConvert() );
2423
2424 // Copy the source to stay const
2425 LIB_SYMBOL tempSymbol( *m_part );
2426 LIB_PINS tempPins;
2427 tempSymbol.GetPins( tempPins, GetUnit(), GetConvert() );
2428
2429 TRANSFORM transform = GetTransform();
2430
2431 // Copy the pin info from the symbol to the temp pins
2432 for( unsigned i = 0; i < tempPins.size(); ++ i )
2433 {
2434 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2435 LIB_PIN* tempPin = tempPins[ i ];
2436
2437 tempPin->SetName( symbolPin->GetShownName() );
2438 tempPin->SetType( symbolPin->GetType() );
2439 tempPin->SetShape( symbolPin->GetShape() );
2440 tempPin->Plot( aPlotter, false, m_pos, transform, GetDNP() );
2441 }
2442 }
2443}
2444
2445
2447{
2448 for( const auto& pin : m_pins )
2449 {
2450 if( pin->IsBrightened() )
2451 return true;
2452 }
2453
2454 return false;
2455}
2456
2457
2459{
2460 for( auto& pin : m_pins )
2461 pin->ClearBrightened();
2462}
2463
2464
2466{
2467 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2468 {
2469 int pin_unit = pin->GetLibPin()->GetUnit();
2470 int pin_convert = pin->GetLibPin()->GetConvert();
2471
2472 if( pin_unit > 0 && pin_unit != GetUnit() )
2473 continue;
2474
2475 if( pin_convert > 0 && pin_convert != GetConvert() )
2476 continue;
2477
2478 if( pin->IsPointClickableAnchor( aPos ) )
2479 return true;
2480 }
2481
2482 return false;
2483}
2484
2485
2487{
2488 // return true if the symbol is equivalent to a global label:
2489 // It is a Power symbol
2490 // It has only one pin type Power input
2491
2492 if( !GetLibSymbolRef() || !GetLibSymbolRef()->IsPower() )
2493 return false;
2494
2495 std::vector<LIB_PIN*> pin_list = GetAllLibPins();
2496
2497 if( pin_list.size() != 1 )
2498 return false;
2499
2500 return pin_list[0]->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN;
2501}
2502
2503
2505{
2506 wxCHECK( m_part, false );
2507
2508 return m_part->IsPower();
2509}
2510
2511
2512static struct SCH_SYMBOL_DESC
2513{
2515 {
2519
2520 const wxString groupAttributes = _HKI( "Attributes" );
2521
2522 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude from board" ),
2524 groupAttributes );
2525 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude from simulation" ),
2527 groupAttributes );
2528 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Exclude from bill of materials" ),
2530 groupAttributes );
2531 propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, bool>( _HKI( "Do not populate" ),
2533 groupAttributes );
2534 }
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
double square(double x)
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:120
const Vec & GetOrigin() const
Definition: box2.h:184
void Offset(coord_type dx, coord_type dy)
Definition: box2.h:225
void SetX(coord_type val)
Definition: box2.h:236
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:270
void SetY(coord_type val)
Definition: box2.h:241
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetY() const
Definition: box2.h:182
coord_type GetWidth() const
Definition: box2.h:188
void SetWidth(coord_type val)
Definition: box2.h:246
const Vec GetEnd() const
Definition: box2.h:186
bool Contains(const Vec &aPoint) const
Definition: box2.h:142
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
coord_type GetX() const
Definition: box2.h:181
coord_type GetRight() const
Definition: box2.h:190
ecoord_type GetArea() const
Return the area of the rectangle.
Definition: box2.h:702
void SetHeight(coord_type val)
Definition: box2.h:251
coord_type GetBottom() const
Definition: box2.h:191
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:589
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
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition: sch_item.h:85
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:85
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:129
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
const KIID m_Uuid
Definition: eda_item.h:482
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:487
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:485
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:398
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxDC * GetPrintDC() const
wxString AsString() const
Definition: kiid.cpp:359
Definition: kiid.h:49
wxString AsString() const
Definition: kiid.cpp:257
Field object used in symbol libraries.
Definition: lib_field.h:62
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
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:68
int GetUnit() const
Definition: lib_item.h:307
@ BASE
Definition: lib_item.h:77
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:72
void SetName(const wxString &aName)
Definition: lib_pin.h:108
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:85
VECTOR2I GetPosition() const override
Definition: lib_pin.h:232
void Plot(PLOTTER *aPlotter, bool aBackground, const VECTOR2I &aOffset, const TRANSFORM &aTransform, bool aDimmed) const override
Plot the draw item using the plot object.
Definition: lib_pin.cpp:1171
Define a library symbol object.
Definition: lib_symbol.h:99
void Plot(PLOTTER *aPlotter, int aUnit, int aConvert, bool aBackground, const VECTOR2I &aOffset, const TRANSFORM &aTransform, bool aDimmed) const
Plot lib symbol to plotter.
Definition: lib_symbol.cpp:891
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition: lib_symbol.h:214
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:544
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Definition: lib_symbol.cpp:770
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:615
void Print(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset, int aMulti, int aConvert, const LIB_SYMBOL_OPTIONS &aOpts, bool aDimmed)
Print symbol.
Definition: lib_symbol.cpp:840
Define a symbol library graphical text item.
Definition: lib_text.h:40
Base plotter engine class.
Definition: plotter.h:104
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:474
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:535
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:463
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:544
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:74
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
TEMPLATES m_TemplateFieldNames
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
wxString GetOperatingPoint(const wxString &aNetName, int aPrecision, const wxString &aRange)
Definition: schematic.cpp:634
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:209
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Definition: schematic.cpp:329
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:52
void ImportValues(const LIB_FIELD &aSource)
Copy parameters from a LIB_FIELD source.
Definition: sch_field.cpp:414
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_field.cpp:188
void SetText(const wxString &aText) override
Definition: sch_field.cpp:982
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:150
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition: sch_item.cpp:71
virtual wxString GetClass() const override
Return the class name.
Definition: sch_item.h:160
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:113
FIELDS_AUTOPLACED m_fieldsAutoplaced
Definition: sch_item.h:512
void SwapFlags(SCH_ITEM *aItem)
Swap the non-temp and non-edit flags.
Definition: sch_item.cpp:267
SCH_LAYER_ID m_layer
Definition: sch_item.h:510
bool IsDangling() const override
Definition: sch_pin.h:103
wxString GetShownName() const
Definition: sch_pin.cpp:94
GRAPHIC_PINSHAPE GetShape() const
Definition: sch_pin.cpp:126
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:117
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
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:236
Schematic symbol object.
Definition: sch_symbol.h:81
void UpdatePrefix()
Set the prefix based on the current reference designator.
Definition: sch_symbol.cpp:812
wxString m_prefix
C, R, U, Q etc - the first character(s) which typically indicate what the symbol is.
Definition: sch_symbol.h:774
SCH_FIELD * GetFieldByName(const wxString &aFieldName)
Return a field in this symbol.
Definition: sch_symbol.cpp:937
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction) override
void GetLibPins(std::vector< LIB_PIN * > &aPinsList) const
Populate a vector with all the pins from the library object.
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:473
bool IsSymbolLikePowerGlobalLabel() const
VECTOR2I m_pos
Definition: sch_symbol.h:768
void Plot(PLOTTER *aPlotter, bool aBackground) const override
Plot the schematic item to aPlotter.
LIB_ID m_lib_id
Name and library the symbol was loaded from, i.e. 74xx:74LS00.
Definition: sch_symbol.h:769
void SetConvert(int aConvert)
Definition: sch_symbol.cpp:454
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
wxString GetDatasheet() const
Return the documentation text for the given part alias.
Definition: sch_symbol.cpp:329
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:287
bool HasBrightenedPins()
std::vector< SCH_FIELD > & GetFields()
Return a vector of fields from the symbol.
Definition: sch_symbol.h:422
void Print(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset) override
Print a symbol.
Definition: sch_symbol.cpp:510
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...
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
LIB_ITEM * GetDrawItem(const VECTOR2I &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the symbol library item at aPosition that is part of this symbol.
int GetUnit() const
Definition: sch_symbol.h:226
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:479
void SetDNP(bool aDNP)
Definition: sch_symbol.h:748
void UpdateUnit(int aUnit)
Change the unit number to aUnit without setting any internal flags.
Definition: sch_symbol.cpp:448
wxString GetClass() const override
Return the class name.
Definition: sch_symbol.h:120
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:589
static bool IsReferenceStringValid(const wxString &aReferenceString)
Test for an acceptable reference string.
Definition: sch_symbol.cpp:756
void PlotPins(PLOTTER *aPlotter) const
Plot just the symbol pins.
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:891
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
Definition: sch_symbol.cpp:997
int m_convert
The alternate body style for symbols that have more than one body style defined.
Definition: sch_symbol.h:771
void SwapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:293
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true, bool aCaseInsensitive=false)
Search for a SCH_FIELD with aFieldName.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:720
bool IsInNetlist() const
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
void ClearBrightenedPins()
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_symbol.cpp:236
void SetExcludedFromSim(bool aExclude) override
Definition: sch_symbol.h:739
bool m_excludedFromSim
True to exclude from simulation.
Definition: sch_symbol.h:797
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:913
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
bool m_excludedFromBoard
True to exclude from netlist when updating board.
Definition: sch_symbol.h:799
static std::unordered_map< TRANSFORM, int > s_transformToOrientationCache
Definition: sch_symbol.h:807
VECTOR2I GetPinPhysicalPosition(const LIB_PIN *Pin) const
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:338
int GetConvert() const
Definition: sch_symbol.h:268
std::vector< SCH_SYMBOL_INSTANCE > m_instanceReferences
Definition: sch_symbol.h:804
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:786
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:762
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
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:897
void PrintBackground(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset) override
Print only the background parts of a symbol (if any)
Definition: sch_symbol.cpp:498
wxString GetDescription() const
Definition: sch_symbol.cpp:311
std::vector< SCH_FIELD > m_fields
Variable length list of fields.
Definition: sch_symbol.h:789
std::unordered_map< LIB_PIN *, SCH_PIN * > m_pinMap
library pin pointer : SCH_PIN's index
Definition: sch_symbol.h:794
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.
int m_unit
The unit for multiple part per package symbols.
Definition: sch_symbol.h:770
void SetFootprintFieldText(const wxString &aFootprint)
Definition: sch_symbol.cpp:907
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
bool GetExcludedFromBOM() const
Definition: sch_symbol.h:741
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
Definition: sch_symbol.cpp:618
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
Definition: sch_symbol.cpp:242
void Rotate(const VECTOR2I &aCenter) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
void SetTransform(const TRANSFORM &aTransform)
Definition: sch_symbol.cpp:466
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:205
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition: sch_symbol.cpp:251
bool GetExcludedFromSim() const override
Definition: sch_symbol.h:738
bool operator<(const SCH_ITEM &aItem) const override
bool m_DNP
True if symbol is set to 'Do Not Populate'.
Definition: sch_symbol.h:800
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
wxString GetKeyWords() const
Definition: sch_symbol.cpp:320
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:925
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
Definition: sch_symbol.cpp:565
TRANSFORM & GetTransform()
Definition: sch_symbol.h:281
bool HasUnitDisplayName(int aUnit)
Return true if the given unit aUnit has a display name set.
Definition: sch_symbol.cpp:490
void SetExcludedFromBOM(bool aIncludeInBOM)
Definition: sch_symbol.h:742
BOX2I doGetBoundingBox(bool aIncludePins, bool aIncludeFields) const
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:988
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList, const SCH_SHEET_PATH *aPath=nullptr) override
Test if the symbol's dangling state has changed for all pins.
const wxString GetValueFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
Definition: sch_symbol.cpp:881
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.
bool IsAnnotated(const SCH_SHEET_PATH *aSheet)
Check if the symbol has a valid annotation (reference) for the given sheet path.
Definition: sch_symbol.cpp:798
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 the netlist.
Definition: sch_symbol.h:796
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:839
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:442
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:173
wxString GetUnitDisplayName(int aUnit)
Return the display name for a given unit aUnit.
Definition: sch_symbol.cpp:482
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:788
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
SCH_SYMBOL & operator=(const SCH_ITEM &aItem)
std::vector< LIB_PIN * > GetAllLibPins() const
bool GetExcludedFromBoard() const
Definition: sch_symbol.h:744
void SetPrefix(const wxString &aPrefix)
Definition: sch_symbol.h:274
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:973
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:855
bool m_excludedFromBOM
True to exclude from bill of materials export.
Definition: sch_symbol.h:798
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:190
std::vector< std::unique_ptr< SCH_PIN > > m_pins
a SCH_PIN for every LIB_PIN (all units)
Definition: sch_symbol.h:793
void SetExcludedFromBoard(bool aIncludeOnBoard)
Definition: sch_symbol.h:745
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:302
BOX2I GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the pins or fields.
void SortInstances(bool(*aSortFunction)(const SCH_SYMBOL_INSTANCE &aLhs, const SCH_SYMBOL_INSTANCE &aRhs))
Definition: sch_symbol.cpp:611
wxString GetFieldText(const wxString &aFieldName) const
Search for a field named aFieldName and returns text associated with this field.
Definition: sch_symbol.cpp:961
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:266
bool IsPower() const
std::unique_ptr< LIB_SYMBOL > m_part
a flattened copy of the LIB_SYMBOL from the PROJECT's libraries.
Definition: sch_symbol.h:791
bool operator==(const SCH_SYMBOL &aSymbol) const
bool GetDNP() const
Definition: sch_symbol.h:747
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:103
#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:178
#define _(s)
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:439
INSPECT_RESULT
Definition: eda_item.h:42
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:78
#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 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_DANGLING
Definition: layer_ids.h:373
@ LAYER_DEVICE
Definition: layer_ids.h:362
@ LAYER_VALUEPART
Definition: layer_ids.h:358
@ LAYER_FIELDS
Definition: layer_ids.h:359
@ LAYER_DEVICE_BACKGROUND
Definition: layer_ids.h:378
@ LAYER_REFERENCEPART
Definition: layer_ids.h:357
@ LAYER_OP_CURRENTS
Definition: layer_ids.h:394
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:387
@ LAYER_DNP_MARKER
Definition: layer_ids.h:374
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:61
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
Message panel definition file.
wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
Definition: ui_common.cpp:219
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:201
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
wxString GetRefDesUnannotated(const wxString &aSource)
Return an unannotated refdes from either a prefix or an existing refdes.
see class PGM_BASE
#define TYPE_HASH(x)
Definition: property.h:64
#define REGISTER_TYPE(x)
Definition: property_mgr.h:356
Collection of utility functions for component reference designators (refdes)
@ SYM_ORIENT_270
@ SYM_ROTATE_CLOCKWISE
@ SYM_ROTATE_COUNTERCLOCKWISE
@ SYM_MIRROR_Y
@ SYM_ORIENT_180
@ SYM_MIRROR_X
@ SYM_NORMAL
@ SYM_ORIENT_90
@ SYM_ORIENT_0
@ NO_CONNECT_END
Definition: sch_item.h:76
@ SHEET_LABEL_END
Definition: sch_item.h:75
@ LABEL_END
Definition: sch_item.h:72
@ JUNCTION_END
Definition: sch_item.h:70
@ PIN_END
Definition: sch_item.h:71
@ WIRE_END
Definition: sch_item.h:68
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
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:54
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:73
static struct SCH_SYMBOL_DESC _SCH_SYMBOL_DESC
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
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:378
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
bool draw_visible_fields
Definition: lib_symbol.h:66
TRANSFORM transform
Definition: lib_symbol.h:64
std::vector< std::pair< int, wxString > > Fields
Definition: sch_screen.h:84
A simple container for schematic symbol instance information.
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)
Definition: trigo.cpp:183
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:163
@ SCH_FIELD_LOCATE_FOOTPRINT_T
Definition: typeinfo.h:165
@ SCH_SYMBOL_T
Definition: typeinfo.h:155
@ SCH_FIELD_T
Definition: typeinfo.h:154
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:182
@ SCH_FIELD_LOCATE_VALUE_T
Definition: typeinfo.h:164
@ LIB_PIN_T
Definition: typeinfo.h:201
@ SCH_FIELD_LOCATE_DATASHEET_T
Definition: typeinfo.h:166
@ SCH_SYMBOL_LOCATE_POWER_T
Definition: typeinfo.h:179
@ SCH_PIN_T
Definition: typeinfo.h:158
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588