KiCad PCB EDA Suite
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-2022 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 <sch_symbol.h>
33#include <sch_sheet_path.h>
34#include <schematic.h>
35#include <trace_helpers.h>
36#include <trigo.h>
37#include <refdes_utils.h>
38#include <wx/log.h>
39#include <string_utils.h>
40#include "plotters/plotter.h"
41
42
47std::string toUTFTildaText( const wxString& txt )
48{
49 std::string ret = TO_UTF8( txt );
50
51 for( std::string::iterator it = ret.begin(); it!=ret.end(); ++it )
52 {
53 if( (unsigned char) *it <= ' ' )
54 *it = '~';
55 }
56
57 return ret;
58}
59
60
75{
76 static LIB_SYMBOL* symbol;
77
78 if( !symbol )
79 {
80 symbol = new LIB_SYMBOL( wxEmptyString );
81
82 LIB_SHAPE* square = new LIB_SHAPE( symbol, SHAPE_T::RECT );
83
84 square->MoveTo( VECTOR2I( schIUScale.MilsToIU( -200 ), schIUScale.MilsToIU( 200 ) ) );
85 square->SetEnd( VECTOR2I( schIUScale.MilsToIU( 200 ), schIUScale.MilsToIU( -200 ) ) );
86
87 LIB_TEXT* text = new LIB_TEXT( symbol );
88
89 text->SetTextSize( wxSize( schIUScale.MilsToIU( 150 ), schIUScale.MilsToIU( 150 ) ) );
90 text->SetText( wxString( wxT( "??" ) ) );
91
92 symbol->AddDrawItem( square );
93 symbol->AddDrawItem( text );
94 }
95
96 return symbol;
97}
98
99
101 SCH_ITEM( nullptr, SCH_SYMBOL_T )
102{
103 m_DNP = false;
104 Init( VECTOR2I( 0, 0 ) );
105}
106
107
108SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId,
109 const SCH_SHEET_PATH* aSheet, int aUnit, int aConvert,
110 const VECTOR2I& aPosition, EDA_ITEM* aParent ) :
111 SCH_ITEM( aParent, SCH_SYMBOL_T )
112{
113 Init( aPosition );
114
115 m_unit = aUnit;
116 m_convert = aConvert;
117 m_lib_id = aLibId;
118
119 std::unique_ptr< LIB_SYMBOL > part;
120
121 part = aSymbol.Flatten();
122 part->SetParent();
123 SetLibSymbol( part.release() );
124
125 // Copy fields from the library symbol
126 UpdateFields( aSheet,
127 true, /* update style */
128 false, /* update ref */
129 false, /* update other fields */
130 true, /* reset ref */
131 true /* reset other fields */ );
132
133 m_prefix = UTIL::GetRefDesPrefix( m_part->GetReferenceField().GetText() );
134
135 if( aSheet )
136 {
138
139 // Value and footprint name are stored in the SCH_SHEET_PATH path manager,
140 // if aSheet != nullptr, not in the symbol itself.
141 // Copy them to the currently displayed field texts
142 SetValue( GetValue( aSheet, false ) );
143 SetFootprint( GetFootprint( aSheet, false ) );
144 }
145
146 // Inherit the include in bill of materials and board netlist settings from library symbol.
147 m_inBom = aSymbol.GetIncludeInBom();
148 m_onBoard = aSymbol.GetIncludeOnBoard();
149 m_DNP = false;
150
151}
152
153
154SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet,
155 const PICKED_SYMBOL& aSel, const VECTOR2I& aPosition,
156 EDA_ITEM* aParent ) :
157 SCH_SYMBOL( aSymbol, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, aPosition, aParent )
158{
159 // Set any fields that were modified as part of the symbol selection
160 for( const std::pair<int, wxString>& i : aSel.Fields )
161 {
162 SCH_FIELD* field = GetFieldById( i.first );
163
164 if( field )
165 field->SetText( i.second );
166 }
167}
168
169
171 SCH_ITEM( aSymbol )
172{
173 m_parent = aSymbol.m_parent;
174 m_pos = aSymbol.m_pos;
175 m_unit = aSymbol.m_unit;
176 m_convert = aSymbol.m_convert;
177 m_lib_id = aSymbol.m_lib_id;
179 m_inBom = aSymbol.m_inBom;
180 m_onBoard = aSymbol.m_onBoard;
181 m_DNP = aSymbol.m_DNP;
182
183 if( aSymbol.m_part )
184 SetLibSymbol( new LIB_SYMBOL( *aSymbol.m_part.get() ) );
185
186 const_cast<KIID&>( m_Uuid ) = aSymbol.m_Uuid;
187
188 m_transform = aSymbol.m_transform;
189 m_prefix = aSymbol.m_prefix;
191 m_fields = aSymbol.m_fields;
192
193 // Re-parent the fields, which before this had aSymbol as parent
194 for( SCH_FIELD& field : m_fields )
195 field.SetParent( this );
196
199}
200
201
202void SCH_SYMBOL::Init( const VECTOR2I& pos )
203{
205 m_pos = pos;
206 m_unit = 1; // In multi unit chip - which unit to draw.
207 m_convert = LIB_ITEM::LIB_CONVERT::BASE; // De Morgan Handling
208
209 // The rotation/mirror transformation matrix. pos normal
211
212 // construct only the mandatory fields, which are the first 4 only.
213 for( int i = 0; i < MANDATORY_FIELDS; ++i )
214 {
215 m_fields.emplace_back( pos, i, this, TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
216
217 if( i == REFERENCE_FIELD )
218 m_fields.back().SetLayer( LAYER_REFERENCEPART );
219 else if( i == VALUE_FIELD )
220 m_fields.back().SetLayer( LAYER_VALUEPART );
221 else
222 m_fields.back().SetLayer( LAYER_FIELDS );
223 }
224
225 m_prefix = wxString( wxT( "U" ) );
226 m_isInNetlist = true;
227 m_inBom = true;
228 m_onBoard = true;
229}
230
231
233{
234 return new SCH_SYMBOL( *this );
235}
236
237
239{
240 if( !m_part )
241 return true;
242
243 return false;
244}
245
246
247void SCH_SYMBOL::ViewGetLayers( int aLayers[], int& aCount ) const
248{
249 aCount = 7;
250 aLayers[0] = LAYER_DANGLING; // Pins are drawn by their parent symbol, so the parent
251 // symbol needs to draw to LAYER_DANGLING
252 aLayers[1] = LAYER_DEVICE;
253 aLayers[2] = LAYER_REFERENCEPART;
254 aLayers[3] = LAYER_VALUEPART;
255 aLayers[4] = LAYER_FIELDS;
256 aLayers[5] = LAYER_DEVICE_BACKGROUND;
257 aLayers[6] = LAYER_SELECTION_SHADOWS;
258}
259
260
262{
263 // If a symbol's anchor is not grid-aligned to its pins then moving from the anchor is
264 // going to end up moving the symbol's pins off-grid.
265
266 // The minimal grid size allowed to place a pin is 25 mils
267 const int min_grid_size = schIUScale.MilsToIU( 25 );
268
269 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
270 {
271 if( ( ( pin->GetPosition().x - m_pos.x ) % min_grid_size ) != 0 )
272 return false;
273
274 if( ( ( pin->GetPosition().y - m_pos.y ) % min_grid_size ) != 0 )
275 return false;
276 }
277
278 return true;
279}
280
281
282void SCH_SYMBOL::SetLibId( const LIB_ID& aLibId )
283{
284 if( m_lib_id != aLibId )
285 {
286 m_lib_id = aLibId;
287 SetModified();
288 }
289}
290
291
293{
294 if( !m_schLibSymbolName.IsEmpty() )
295 return m_schLibSymbolName;
296 else
297 return m_lib_id.Format();
298}
299
300
302{
303 wxCHECK2( ( aLibSymbol == nullptr ) || ( aLibSymbol->IsRoot() ), aLibSymbol = nullptr );
304
305 m_part.reset( aLibSymbol );
306 UpdatePins();
307}
308
309
311{
312 if( m_part )
313 return m_part->GetDescription();
314
315 return wxEmptyString;
316}
317
318
320{
321 if( m_part )
322 return m_part->GetKeyWords();
323
324 return wxEmptyString;
325}
326
327
329{
330 if( m_part )
331 return m_part->GetDatasheetField().GetText();
332
333 return wxEmptyString;
334}
335
336
338{
339 std::map<wxString, wxString> altPinMap;
340 std::map<wxString, KIID> pinUuidMap;
341
342 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
343 {
344 pinUuidMap[ pin->GetNumber() ] = pin->m_Uuid;
345
346 if( !pin->GetAlt().IsEmpty() )
347 altPinMap[ pin->GetNumber() ] = pin->GetAlt();
348 }
349
350 m_pins.clear();
351 m_pinMap.clear();
352
353 if( !m_part )
354 return;
355
356 unsigned i = 0;
357
358 for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) )
359 {
360 wxASSERT( libPin->Type() == LIB_PIN_T );
361
362 // NW: Don't filter by unit: this data-structure is used for all instances,
363 // some if which might have different units.
364 if( libPin->GetConvert() && m_convert && m_convert != libPin->GetConvert() )
365 continue;
366
367 m_pins.push_back( std::make_unique<SCH_PIN>( libPin, this ) );
368
369 auto ii = pinUuidMap.find( libPin->GetNumber() );
370
371 if( ii != pinUuidMap.end() )
372 const_cast<KIID&>( m_pins.back()->m_Uuid ) = ii->second;
373
374 auto iii = altPinMap.find( libPin->GetNumber() );
375
376 if( iii != altPinMap.end() )
377 m_pins.back()->SetAlt( iii->second );
378
379 m_pinMap[ libPin ] = i;
380
381 ++i;
382 }
383}
384
385
386void SCH_SYMBOL::SetUnit( int aUnit )
387{
388 if( m_unit != aUnit )
389 {
390 UpdateUnit( aUnit );
391 SetModified();
392 }
393}
394
395
396void SCH_SYMBOL::UpdateUnit( int aUnit )
397{
398 m_unit = aUnit;
399}
400
401
402void SCH_SYMBOL::SetConvert( int aConvert )
403{
404 if( m_convert != aConvert )
405 {
406 m_convert = aConvert;
407
408 // The convert may have a different pin layout so the update the pin map.
409 UpdatePins();
410 SetModified();
411 }
412}
413
414
415void SCH_SYMBOL::SetTransform( const TRANSFORM& aTransform )
416{
417 if( m_transform != aTransform )
418 {
419 m_transform = aTransform;
420 SetModified();
421 }
422}
423
424
426{
427 if( m_part )
428 return m_part->GetUnitCount();
429
430 return 0;
431}
432
433
435{
436 wxCHECK( m_part, ( wxString::Format( _( "Unit %s" ), LIB_SYMBOL::SubReference( aUnit ) ) ) );
437
438 return m_part->GetUnitDisplayName( aUnit );
439}
440
441
443{
444 wxCHECK( m_part, false );
445
446 return m_part->HasUnitDisplayName( aUnit );
447}
448
449
450void SCH_SYMBOL::PrintBackground( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
451{
453 opts.transform = m_transform;
454 opts.draw_visible_fields = false;
455 opts.draw_hidden_fields = false;
456
457 if( m_part )
458 m_part->PrintBackground( aSettings, m_pos + aOffset, m_unit, m_convert, opts, GetDNP() );
459}
460
461
462void SCH_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
463{
465 opts.transform = m_transform;
466 opts.draw_visible_fields = false;
467 opts.draw_hidden_fields = false;
468
469 if( m_part )
470 {
471 m_part->Print( aSettings, m_pos + aOffset, m_unit, m_convert, opts, GetDNP() );
472 }
473 else // Use dummy() part if the actual cannot be found.
474 {
475 dummy()->Print( aSettings, m_pos + aOffset, 0, 0, opts, GetDNP() );
476 }
477
478 for( SCH_FIELD& field : m_fields )
479 field.Print( aSettings, aOffset );
480}
481
482
484 const KIID_PATH& aSheetPath ) const
485{
486 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
487 {
488 if( instance.m_Path == aSheetPath )
489 {
490 aInstance = instance;
491 return true;
492 }
493 }
494
495 return false;
496}
497
498
499void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
500{
501 // Search for an existing path and remove it if found (should not occur)
502 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
503 {
504 if( m_instanceReferences[ii].m_Path == aInstancePath.Path() )
505 {
506 wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
507 " sheet path %s\n"
508 " reference %s, unit %d from symbol %s.",
509 aInstancePath.Path().AsString(),
510 m_instanceReferences[ii].m_Reference,
511 m_instanceReferences[ii].m_Unit,
512 m_Uuid.AsString() );
513
514 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
515 ii--;
516 }
517 }
518}
519
520
521void SCH_SYMBOL::SortInstances( bool (*aSortFunction)( const SYMBOL_INSTANCE_REFERENCE& aLhs,
522 const SYMBOL_INSTANCE_REFERENCE& aRhs ) )
523{
524 std::sort( m_instanceReferences.begin(), m_instanceReferences.end(), aSortFunction );
525}
526
527
528void SCH_SYMBOL::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef,
529 int aUnit, const wxString& aValue,
530 const wxString& aFootprint )
531{
532 // Search for an existing path and remove it if found (should not occur)
533 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
534 {
535 if( m_instanceReferences[ii].m_Path == aPath )
536 {
537 wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
538 " sheet path %s\n"
539 " reference %s, unit %d from symbol %s.",
540 aPath.AsString(),
541 m_instanceReferences[ii].m_Reference,
542 m_instanceReferences[ii].m_Unit,
543 m_Uuid.AsString() );
544
545 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
546 ii--;
547 }
548 }
549
551 instance.m_Path = aPath;
552 instance.m_Reference = aRef;
553 instance.m_Unit = aUnit;
554 instance.m_Value = aValue;
555 instance.m_Footprint = aFootprint;
556
557 wxLogTrace( traceSchSheetPaths,
558 "Adding symbol '%s' instance:\n"
559 " sheet path '%s'\n"
560 " reference '%s'\n"
561 " unit %d\n"
562 " value '%s'\n"
563 " footprint '%s'",
565 aPath.AsString(),
566 aRef,
567 aUnit,
568 aValue,
569 aFootprint );
570
571 m_instanceReferences.push_back( instance );
572
573 // This should set the default instance to the first saved instance data for each symbol
574 // when importing sheets.
575 if( m_instanceReferences.size() == 1 )
576 {
577 m_fields[ REFERENCE_FIELD ].SetText( aRef );
578 m_fields[ VALUE_FIELD ].SetText( aValue );
579 m_unit = aUnit;
580 m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
581 }
582}
583
584
586{
587 // Search for an existing path and remove it if found (should not occur)
588 for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
589 {
590 if( m_instanceReferences[ii].m_Path == aInstance.m_Path )
591 {
592 wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
593 " sheet path %s\n"
594 " reference %s, unit %d from symbol %s.",
595 aInstance.m_Path.AsString(),
596 m_instanceReferences[ii].m_Reference,
597 m_instanceReferences[ii].m_Unit,
598 m_Uuid.AsString() );
599
600 m_instanceReferences.erase( m_instanceReferences.begin() + ii );
601 ii--;
602 }
603 }
604
605 SYMBOL_INSTANCE_REFERENCE instance = aInstance;
606
607 wxLogTrace( traceSchSheetPaths,
608 "Adding symbol '%s' instance:\n"
609 " sheet path '%s'\n"
610 " reference '%s'\n"
611 " unit %d\n"
612 " value '%s'\n"
613 " footprint '%s'",
615 instance.m_Path.AsString(),
616 instance.m_Reference,
617 instance.m_Unit,
618 instance.m_Value,
619 instance.m_Footprint );
620
621 m_instanceReferences.push_back( instance );
622
623 // This should set the default instance to the first saved instance data for each symbol
624 // when importing sheets.
625 if( m_instanceReferences.size() == 1 )
626 {
627 m_fields[ REFERENCE_FIELD ].SetText( instance.m_Reference );
628 m_fields[ VALUE_FIELD ].SetText( instance.m_Value );
629 m_unit = instance.m_Unit;
630 m_fields[ FOOTPRINT_FIELD ].SetText( instance.m_Footprint );
631 }
632}
633
634
635const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
636{
637 KIID_PATH path = sheet->Path();
638 wxString ref;
639 wxString subRef;
640
641 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
642 {
643 if( instance.m_Path == path )
644 {
645 ref = instance.m_Reference;
646 subRef = LIB_SYMBOL::SubReference( instance.m_Unit );
647 break;
648 }
649 }
650
651 // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
652 // use this as a default for this path. This will happen if we load a version 1 schematic
653 // file. It will also mean that multiple instances of the same sheet by default all have
654 // the same symbol references, but perhaps this is best.
655 if( ref.IsEmpty() && !GetField( REFERENCE_FIELD )->GetText().IsEmpty() )
656 {
657 const_cast<SCH_SYMBOL*>( this )->SetRef( sheet, GetField( REFERENCE_FIELD )->GetText() );
658 ref = GetField( REFERENCE_FIELD )->GetText();
659 }
660
661 if( ref.IsEmpty() )
663
664 if( aIncludeUnit && GetUnitCount() > 1 )
665 ref += subRef;
666
667 return ref;
668}
669
670
671bool SCH_SYMBOL::IsReferenceStringValid( const wxString& aReferenceString )
672{
673 return !UTIL::GetRefDesPrefix( aReferenceString ).IsEmpty();
674}
675
676
677void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
678{
679 KIID_PATH path = sheet->Path();
680 bool found = false;
681
682 // check to see if it is already there before inserting it
684 {
685 if( instance.m_Path == path )
686 {
687 found = true;
688 instance.m_Reference = ref;
689 break;
690 }
691 }
692
693 if( !found )
696
697 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
698 pin->ClearDefaultNetName( sheet );
699
700 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
701 m_fields[ REFERENCE_FIELD ].SetText( ref );
702
703 // Reinit the m_prefix member if needed
705
706 if( m_prefix.IsEmpty() )
707 m_prefix = wxT( "U" );
708
709 // Power symbols have references starting with # and are not included in netlists
710 m_isInNetlist = ! ref.StartsWith( wxT( "#" ) );
711}
712
713
715{
716 KIID_PATH path = aSheet->Path();
717
718 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
719 {
720 if( instance.m_Path == path )
721 return instance.m_Reference.Last() != '?';
722 }
723
724 return false;
725}
726
727
729{
730 KIID_PATH path = aSheet->Path();
731
732 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
733 {
734 if( instance.m_Path == path )
735 return instance.m_Unit;
736 }
737
738 // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
739 // version 1 schematic file.
740 return m_unit;
741}
742
743
744void SCH_SYMBOL::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
745{
746 KIID_PATH path = aSheet->Path();
747
748 // check to see if it is already there before inserting it
750 {
751 if( instance.m_Path == path )
752 {
753 instance.m_Unit = aUnitSelection;
754 return;
755 }
756 }
757
758 // didn't find it; better add it
760}
761
762
763void SCH_SYMBOL::SetUnitSelection( int aUnitSelection )
764{
766 instance.m_Unit = aUnitSelection;
767}
768
769
770const wxString SCH_SYMBOL::GetValue( const SCH_SHEET_PATH* sheet, bool aResolve ) const
771{
772 KIID_PATH path = sheet->Path();
773
774 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
775 {
776 if( instance.m_Path == path && !instance.m_Value.IsEmpty() )
777 {
778 // This can only be overridden by a new value but if we are resolving,
779 // make sure that the symbol returns the fully resolved text
780 if( aResolve )
781 {
782 SCH_SYMBOL new_sym( *this );
783 new_sym.GetField( VALUE_FIELD )->SetText( instance.m_Value );
784 return new_sym.GetField( VALUE_FIELD )->GetShownText();
785 }
786
787 return instance.m_Value;
788 }
789 }
790
791 if( !aResolve )
792 return GetField( VALUE_FIELD )->GetText();
793
794 return GetField( VALUE_FIELD )->GetShownText();
795}
796
797
798void SCH_SYMBOL::SetValue( const SCH_SHEET_PATH* sheet, const wxString& aValue )
799{
800 if( sheet == nullptr )
801 {
802 // Set all instances to the updated value
804 instance.m_Value = aValue;
805
806 m_fields[ VALUE_FIELD ].SetText( aValue );
807 return;
808 }
809
810 KIID_PATH path = sheet->Path();
811 bool found = false;
812
813 // check to see if it is already there before inserting it
815 {
816 if( instance.m_Path == path )
817 {
818 found = true;
819 instance.m_Value = aValue;
820 break;
821 }
822 }
823
824 // didn't find it; better add it
825 if( !found )
826 {
828 wxEmptyString );
829 }
830
831 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
832 m_fields[ VALUE_FIELD ].SetText( aValue );
833}
834
835
836const wxString SCH_SYMBOL::GetFootprint( const SCH_SHEET_PATH* sheet, bool aResolve ) const
837{
838 KIID_PATH path = sheet->Path();
839
840 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
841 {
842 if( instance.m_Path == path && !instance.m_Footprint.IsEmpty() )
843 {
844 // This can only be an override from an Update Schematic from PCB, and therefore
845 // will always be fully resolved.
846 return instance.m_Footprint;
847 }
848 }
849
850 if( !aResolve )
851 return GetField( FOOTPRINT_FIELD )->GetText();
852
854}
855
856
857void SCH_SYMBOL::SetFootprint( const SCH_SHEET_PATH* sheet, const wxString& aFootprint )
858{
859 if( sheet == nullptr )
860 {
861 // Set all instances to new footprint value
863 instance.m_Footprint = aFootprint;
864
865 m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
866 return;
867 }
868
869 KIID_PATH path = sheet->Path();
870 bool found = false;
871
872 // check to see if it is already there before inserting it
874 {
875 if( instance.m_Path == path )
876 {
877 found = true;
878 instance.m_Footprint = aFootprint;
879 break;
880 }
881 }
882
883 // didn't find it; better add it
884 if( !found )
885 {
887 wxEmptyString, aFootprint );
888 }
889
890 if( Schematic() && *sheet == Schematic()->CurrentSheet() )
891 m_fields[ FOOTPRINT_FIELD ].SetText( aFootprint );
892}
893
894
896{
897 return &m_fields[aFieldType];
898}
899
900
902{
903 return &m_fields[aFieldType];
904}
905
906
908{
909 for( size_t ii = 0; ii < m_fields.size(); ++ii )
910 {
911 if( m_fields[ii].GetId() == aFieldId )
912 return &m_fields[ii];
913 }
914
915 return nullptr;
916}
917
918
919wxString SCH_SYMBOL::GetFieldText( const wxString& aFieldName ) const
920{
921 for( const SCH_FIELD& field : m_fields )
922 {
923 if( aFieldName == field.GetName() || aFieldName == field.GetCanonicalName() )
924 return field.GetText();
925 }
926
927 return wxEmptyString;
928}
929
930
931void SCH_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
932{
933 for( SCH_FIELD& field : m_fields )
934 {
935 if( aVisibleOnly )
936 {
937 if( !field.IsVisible() || field.GetShownText().IsEmpty() )
938 continue;
939 }
940
941 aVector.push_back( &field );
942 }
943}
944
945
947{
948 int newNdx = m_fields.size();
949
950 m_fields.push_back( aField );
951 return &m_fields[newNdx];
952}
953
954
955void SCH_SYMBOL::RemoveField( const wxString& aFieldName )
956{
957 for( unsigned i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
958 {
959 if( aFieldName == m_fields[i].GetName( false ) )
960 {
961 m_fields.erase( m_fields.begin() + i );
962 return;
963 }
964 }
965}
966
967
968SCH_FIELD* SCH_SYMBOL::FindField( const wxString& aFieldName, bool aIncludeDefaultFields )
969{
970 unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
971
972 for( unsigned i = start; i < m_fields.size(); ++i )
973 {
974 if( aFieldName == m_fields[i].GetName( false ) )
975 return &m_fields[i];
976 }
977
978 return nullptr;
979}
980
981
982void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef,
983 bool aUpdateOtherFields, bool aResetRef, bool aResetOtherFields )
984{
985 if( m_part )
986 {
987 std::vector<LIB_FIELD*> fields;
988
989 m_part->GetFields( fields );
990
991 for( const LIB_FIELD* libField : fields )
992 {
993 int id = libField->GetId();
994 SCH_FIELD* schField;
995
996 if( id >= 0 && id < MANDATORY_FIELDS )
997 {
998 schField = GetFieldById( id );
999 }
1000 else
1001 {
1002 schField = FindField( libField->GetCanonicalName() );
1003
1004 if( !schField )
1005 {
1006 wxString fieldName = libField->GetCanonicalName();
1007 SCH_FIELD newField( VECTOR2I( 0, 0 ), GetFieldCount(), this, fieldName );
1008 schField = AddField( newField );
1009 }
1010 }
1011
1012 if( aUpdateStyle )
1013 {
1014 schField->ImportValues( *libField );
1015 schField->SetTextPos( m_pos + libField->GetTextPos() );
1016 }
1017
1018 if( id == REFERENCE_FIELD && aPath )
1019 {
1020 if( aResetRef )
1021 SetRef( aPath, m_part->GetReferenceField().GetText() );
1022 else if( aUpdateRef )
1023 SetRef( aPath, libField->GetText() );
1024 }
1025 else if( id == VALUE_FIELD )
1026 {
1027 SetValue( aPath, UnescapeString( libField->GetText() ) );
1028 }
1029 else if( id == FOOTPRINT_FIELD )
1030 {
1031 if( aResetOtherFields || aUpdateOtherFields )
1032 SetFootprint( aPath, libField->GetText() );
1033 }
1034 else if( id == DATASHEET_FIELD )
1035 {
1036 if( aResetOtherFields )
1037 schField->SetText( GetDatasheet() ); // alias-specific value
1038 else if( aUpdateOtherFields )
1039 schField->SetText( libField->GetText() );
1040 }
1041 else
1042 {
1043 if( aResetOtherFields || aUpdateOtherFields )
1044 schField->SetText( libField->GetText() );
1045 }
1046 }
1047 }
1048}
1049
1050
1051void SCH_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
1052{
1053 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1054 aFunction( pin.get() );
1055
1056 for( SCH_FIELD& field : m_fields )
1057 aFunction( &field );
1058}
1059
1060
1061SCH_PIN* SCH_SYMBOL::GetPin( const wxString& aNumber ) const
1062{
1063 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1064 {
1065 if( pin->GetNumber() == aNumber )
1066 return pin.get();
1067 }
1068
1069 return nullptr;
1070}
1071
1072
1073void SCH_SYMBOL::GetLibPins( std::vector<LIB_PIN*>& aPinsList ) const
1074{
1075 if( m_part )
1076 m_part->GetPins( aPinsList, m_unit, m_convert );
1077}
1078
1079
1080std::vector<LIB_PIN*> SCH_SYMBOL::GetLibPins() const
1081{
1082 std::vector<LIB_PIN*> pinList;
1083
1084 GetLibPins( pinList );
1085 return pinList;
1086}
1087
1088
1090{
1091 wxASSERT( m_pinMap.count( aLibPin ) );
1092 return m_pins[ m_pinMap.at( aLibPin ) ].get();
1093}
1094
1095
1096std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
1097{
1098 std::vector<SCH_PIN*> pins;
1099
1100 if( aSheet == nullptr )
1101 {
1102 wxCHECK_MSG( Schematic(), pins, "Can't call GetPins on a symbol with no schematic" );
1103
1104 aSheet = &Schematic()->CurrentSheet();
1105 }
1106
1107 int unit = GetUnitSelection( aSheet );
1108
1109 for( const std::unique_ptr<SCH_PIN>& p : m_pins )
1110 {
1111 if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
1112 continue;
1113
1114 pins.push_back( p.get() );
1115 }
1116
1117 return pins;
1118}
1119
1120
1122{
1123 wxCHECK_RET( (aItem != nullptr) && (aItem->Type() == SCH_SYMBOL_T),
1124 wxT( "Cannot swap data with invalid symbol." ) );
1125
1126 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
1127
1128 std::swap( m_lib_id, symbol->m_lib_id );
1129
1130 LIB_SYMBOL* libSymbol = symbol->m_part.release();
1131 symbol->m_part.reset( m_part.release() );
1132 symbol->UpdatePins();
1133 m_part.reset( libSymbol );
1134 UpdatePins();
1135
1136 std::swap( m_pos, symbol->m_pos );
1137 std::swap( m_unit, symbol->m_unit );
1138 std::swap( m_convert, symbol->m_convert );
1139
1140 m_fields.swap( symbol->m_fields ); // std::vector's swap()
1141
1142 for( SCH_FIELD& field : symbol->m_fields )
1143 field.SetParent( symbol );
1144
1145 for( SCH_FIELD& field : m_fields )
1146 field.SetParent( this );
1147
1148 TRANSFORM tmp = m_transform;
1149
1150 m_transform = symbol->m_transform;
1151 symbol->m_transform = tmp;
1152
1153 std::swap( m_instanceReferences, symbol->m_instanceReferences );
1154 std::swap( m_schLibSymbolName, symbol->m_schLibSymbolName );
1155}
1156
1157
1158void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
1159{
1160 for( int i = 0; i < MANDATORY_FIELDS; ++i )
1161 aVars->push_back( m_fields[i].GetCanonicalName().Upper() );
1162
1163 for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
1164 aVars->push_back( m_fields[i].GetName() );
1165
1166 aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
1167 aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
1168 aVars->push_back( wxT( "UNIT" ) );
1169 aVars->push_back( wxT( "SYMBOL_LIBRARY" ) );
1170 aVars->push_back( wxT( "SYMBOL_NAME" ) );
1171 aVars->push_back( wxT( "SYMBOL_DESCRIPTION" ) );
1172 aVars->push_back( wxT( "SYMBOL_KEYWORDS" ) );
1173 aVars->push_back( wxT( "EXCLUDE_FROM_BOM" ) );
1174 aVars->push_back( wxT( "EXCLUDE_FROM_BOARD" ) );
1175 aVars->push_back( wxT( "DNP" ) );
1176}
1177
1178
1179bool SCH_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const
1180{
1181 SCHEMATIC* schematic = Schematic();
1182
1183 // SCH_SYMOL object has no context outside a schematic.
1184 if( !schematic )
1185 return false;
1186
1187 for( int i = 0; i < MANDATORY_FIELDS; ++i )
1188 {
1189 if( token->IsSameAs( m_fields[ i ].GetCanonicalName().Upper() ) )
1190 {
1191 if( i == REFERENCE_FIELD )
1192 *token = GetRef( &schematic->CurrentSheet(), true );
1193 else if( i == VALUE_FIELD )
1194 *token = GetValue( &schematic->CurrentSheet(), true );
1195 else if( i == FOOTPRINT_FIELD )
1196 *token = GetFootprint( &schematic->CurrentSheet(), true );
1197 else
1198 *token = m_fields[ i ].GetShownText( aDepth + 1 );
1199
1200 return true;
1201 }
1202 }
1203
1204 for( size_t i = MANDATORY_FIELDS; i < m_fields.size(); ++i )
1205 {
1206 if( token->IsSameAs( m_fields[ i ].GetName() )
1207 || token->IsSameAs( m_fields[ i ].GetName().Upper() ) )
1208 {
1209 *token = m_fields[ i ].GetShownText( aDepth + 1 );
1210 return true;
1211 }
1212 }
1213
1214 for( const TEMPLATE_FIELDNAME& templateFieldname :
1216 {
1217 if( token->IsSameAs( templateFieldname.m_Name )
1218 || token->IsSameAs( templateFieldname.m_Name.Upper() ) )
1219 {
1220 // If we didn't find it in the fields list then it isn't set on this symbol.
1221 // Just return an empty string.
1222 *token = wxEmptyString;
1223 return true;
1224 }
1225 }
1226
1227 if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
1228 {
1229 wxString footprint;
1230
1231 footprint = GetFootprint( &schematic->CurrentSheet(), true );
1232
1233 wxArrayString parts = wxSplit( footprint, ':' );
1234
1235 *token = parts[ 0 ];
1236 return true;
1237 }
1238 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
1239 {
1240 wxString footprint;
1241
1242 footprint = GetFootprint( &schematic->CurrentSheet(), true );
1243
1244 wxArrayString parts = wxSplit( footprint, ':' );
1245
1246 *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
1247 return true;
1248 }
1249 else if( token->IsSameAs( wxT( "UNIT" ) ) )
1250 {
1251 int unit;
1252
1253 unit = GetUnitSelection( &schematic->CurrentSheet() );
1254
1255 *token = LIB_SYMBOL::SubReference( unit );
1256 return true;
1257 }
1258 else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) )
1259 {
1260 *token = m_lib_id.GetLibNickname();
1261 return true;
1262 }
1263 else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) )
1264 {
1265 *token = m_lib_id.GetLibItemName();
1266 return true;
1267 }
1268 else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) )
1269 {
1270 *token = GetDescription();
1271 return true;
1272 }
1273 else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) )
1274 {
1275 *token = GetKeyWords();
1276 return true;
1277 }
1278 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
1279 {
1280 *token = this->GetIncludeInBom() ? wxT( "" ) : _( "Excluded from BOM" );
1281 return true;
1282 }
1283 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
1284 {
1285 *token = this->GetIncludeOnBoard() ? wxT( "" ) : _( "Excluded from board" );
1286 return true;
1287 }
1288 else if( token->IsSameAs( wxT( "DNP" ) ) )
1289 {
1290 *token = this->GetDNP() ? wxT( "" ) : _( "DNP" );
1291 return true;
1292 }
1293
1294 return false;
1295}
1296
1297
1298void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1299{
1300 if( aSheetPath )
1301 {
1302 KIID_PATH path = aSheetPath->Path();
1303
1305 {
1306 if( instance.m_Path == path )
1307 {
1308 if( instance.m_Reference.IsEmpty() || aResetPrefix )
1309 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1310 else
1311 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1312 }
1313 }
1314 }
1315 else
1316 {
1318 {
1319 if( instance.m_Reference.IsEmpty() || aResetPrefix)
1320 instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix );
1321 else
1322 instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference );
1323 }
1324 }
1325
1326 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1327 pin->ClearDefaultNetName( aSheetPath );
1328
1329 // These 2 changes do not work in complex hierarchy.
1330 // When a clear annotation is made, the calling function must call a
1331 // UpdateAllScreenReferences for the active sheet.
1332 // But this call cannot made here.
1333 wxString currentReference = m_fields[REFERENCE_FIELD].GetText();
1334
1335 if( currentReference.IsEmpty() || aResetPrefix )
1337 else
1338 m_fields[REFERENCE_FIELD].SetText( UTIL::GetRefDesUnannotated( currentReference ) );
1339}
1340
1341
1343{
1344 // An empty sheet path is illegal, at a minimum the root sheet UUID must be present.
1345 wxCHECK( aSheetPath.size() > 0, false );
1346
1347 for( const SYMBOL_INSTANCE_REFERENCE& instance : m_instanceReferences )
1348 {
1349 // if aSheetPath is found, nothing to do:
1350 if( instance.m_Path == aSheetPath )
1351 return false;
1352 }
1353
1354 // This entry does not exist: add it, with its last-used reference
1356 return true;
1357}
1358
1359
1361 const KIID_PATH& aNewSheetPath )
1362{
1363 auto it = std::find_if( m_instanceReferences.begin(), m_instanceReferences.end(),
1364 [ aOldSheetPath ]( SYMBOL_INSTANCE_REFERENCE& r )->bool
1365 {
1366 return aOldSheetPath == r.m_Path;
1367 }
1368 );
1369
1370 if( it != m_instanceReferences.end() )
1371 {
1372 wxLogTrace( traceSchSheetPaths,
1373 "Replacing sheet path %s\n with sheet path %s\n for symbol %s.",
1374 aOldSheetPath.AsString(), aNewSheetPath.AsString(), m_Uuid.AsString() );
1375
1376 it->m_Path = aNewSheetPath;
1377 return true;
1378 }
1379
1380 wxLogTrace( traceSchSheetPaths,
1381 "Could not find sheet path %s\n to replace with sheet path %s\n for symbol %s.",
1382 aOldSheetPath.AsString(), aNewSheetPath.AsString(), m_Uuid.AsString() );
1383
1384 return false;
1385}
1386
1387
1388void SCH_SYMBOL::SetOrientation( int aOrientation )
1389{
1390 TRANSFORM temp = TRANSFORM();
1391 bool transform = false;
1392
1393 switch( aOrientation )
1394 {
1395 case SYM_ORIENT_0:
1396 case SYM_NORMAL: // default transform matrix
1397 m_transform.x1 = 1;
1398 m_transform.y2 = -1;
1400 break;
1401
1402 case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
1403 temp.x1 = temp.y2 = 0;
1404 temp.y1 = 1;
1405 temp.x2 = -1;
1406 transform = true;
1407 break;
1408
1409 case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1410 temp.x1 = temp.y2 = 0;
1411 temp.y1 = -1;
1412 temp.x2 = 1;
1413 transform = true;
1414 break;
1415
1416 case SYM_MIRROR_Y: // Mirror Y (incremental rotation)
1417 temp.x1 = -1;
1418 temp.y2 = 1;
1419 temp.y1 = temp.x2 = 0;
1420 transform = true;
1421 break;
1422
1423 case SYM_MIRROR_X: // Mirror X (incremental rotation)
1424 temp.x1 = 1;
1425 temp.y2 = -1;
1426 temp.y1 = temp.x2 = 0;
1427 transform = true;
1428 break;
1429
1430 case SYM_ORIENT_90:
1433 break;
1434
1435 case SYM_ORIENT_180:
1439 break;
1440
1441 case SYM_ORIENT_270:
1444 break;
1445
1446 case ( SYM_ORIENT_0 + SYM_MIRROR_X ):
1449 break;
1450
1451 case ( SYM_ORIENT_0 + SYM_MIRROR_Y ):
1454 break;
1455
1456 case ( SYM_ORIENT_90 + SYM_MIRROR_X ):
1459 break;
1460
1461 case ( SYM_ORIENT_90 + SYM_MIRROR_Y ):
1464 break;
1465
1466 case ( SYM_ORIENT_180 + SYM_MIRROR_X ):
1469 break;
1470
1471 case ( SYM_ORIENT_180 + SYM_MIRROR_Y ):
1474 break;
1475
1476 case ( SYM_ORIENT_270 + SYM_MIRROR_X ):
1479 break;
1480
1481 case ( SYM_ORIENT_270 + SYM_MIRROR_Y ):
1484 break;
1485
1486 default:
1487 transform = false;
1488 wxFAIL_MSG( "Invalid schematic symbol orientation type." );
1489 break;
1490 }
1491
1492 if( transform )
1493 {
1494 /* The new matrix transform is the old matrix transform modified by the
1495 * requested transformation, which is the temp transform (rot,
1496 * mirror ..) in order to have (in term of matrix transform):
1497 * transform coord = new_m_transform * coord
1498 * where transform coord is the coord modified by new_m_transform from
1499 * the initial value coord.
1500 * new_m_transform is computed (from old_m_transform and temp) to
1501 * have:
1502 * transform coord = old_m_transform * temp
1503 */
1504 TRANSFORM newTransform;
1505
1506 newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1507 newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1508 newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1509 newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1510 m_transform = newTransform;
1511 }
1512}
1513
1514
1516{
1517 int rotate_values[] =
1518 {
1531 };
1532
1533 // Try to find the current transform option:
1534 TRANSFORM transform = m_transform;
1535 SCH_SYMBOL temp( *this );
1536
1537 for( int type_rotate : rotate_values )
1538 {
1539 temp.SetOrientation( type_rotate );
1540
1541 if( transform == temp.GetTransform() )
1542 return type_rotate;
1543 }
1544
1545 // Error: orientation not found in list (should not happen)
1546 wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
1547
1548 return SYM_NORMAL;
1549}
1550
1551
1552#if defined(DEBUG)
1553
1554void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const
1555{
1556 // for now, make it look like XML:
1557 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1558 << " ref=\"" << TO_UTF8( GetField( REFERENCE_FIELD )->GetName() )
1559 << '"' << " chipName=\""
1560 << GetLibId().Format() << '"' << m_pos
1561 << " layer=\"" << m_layer
1562 << '"' << ">\n";
1563
1564 // skip the reference, it's been output already.
1565 for( int i = 1; i < GetFieldCount(); ++i )
1566 {
1567 const wxString& value = GetFields()[i].GetText();
1568
1569 if( !value.IsEmpty() )
1570 {
1571 NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
1572 << TO_UTF8( GetFields()[i].GetName() )
1573 << '"' << " value=\""
1574 << TO_UTF8( value ) << "\"/>\n";
1575 }
1576 }
1577
1578 NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
1579}
1580
1581#endif
1582
1583
1584BOX2I SCH_SYMBOL::doGetBoundingBox( bool aIncludePins, bool aIncludeFields ) const
1585{
1586 BOX2I bBox;
1587
1588 if( m_part )
1589 bBox = m_part->GetBodyBoundingBox( m_unit, m_convert, aIncludePins, false );
1590 else
1591 bBox = dummy()->GetBodyBoundingBox( m_unit, m_convert, aIncludePins, false );
1592
1593 int x0 = bBox.GetX();
1594 int xm = bBox.GetRight();
1595
1596 // We must reverse Y values, because matrix orientation
1597 // suppose Y axis normal for the library items coordinates,
1598 // m_transform reverse Y values, but bBox is already reversed!
1599 int y0 = -bBox.GetY();
1600 int ym = -bBox.GetBottom();
1601
1602 // Compute the real Boundary box (rotated, mirrored ...)
1603 int x1 = m_transform.x1 * x0 + m_transform.y1 * y0;
1604 int y1 = m_transform.x2 * x0 + m_transform.y2 * y0;
1605 int x2 = m_transform.x1 * xm + m_transform.y1 * ym;
1606 int y2 = m_transform.x2 * xm + m_transform.y2 * ym;
1607
1608 bBox.SetX( x1 );
1609 bBox.SetY( y1 );
1610 bBox.SetWidth( x2 - x1 );
1611 bBox.SetHeight( y2 - y1 );
1612 bBox.Normalize();
1613
1614 bBox.Offset( m_pos );
1615
1616 if( aIncludeFields )
1617 {
1618 for( const SCH_FIELD& field : m_fields )
1619 {
1620 if( field.IsVisible() )
1621 bBox.Merge( field.GetBoundingBox() );
1622 }
1623 }
1624
1625 return bBox;
1626}
1627
1628
1630{
1631 return doGetBoundingBox( false, false );
1632}
1633
1634
1636{
1637 return doGetBoundingBox( true, false );
1638}
1639
1640
1642{
1643 return doGetBoundingBox( true, true );
1644}
1645
1646
1647void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1648{
1649 wxString msg;
1650
1651 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1652 SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
1653
1654 // part and alias can differ if alias is not the root
1655 if( m_part )
1656 {
1657 if( m_part.get() != dummy() )
1658 {
1659 if( m_part->IsPower() )
1660 {
1661 aList.emplace_back( _( "Power symbol" ), GetValue( currentSheet, true ) );
1662 }
1663 else
1664 {
1665 aList.emplace_back( _( "Reference" ), GetRef( currentSheet ) );
1666 aList.emplace_back( _( "Value" ), GetValue( currentSheet, true ) );
1667 aList.emplace_back( _( "Name" ), UnescapeString( GetLibId().GetLibItemName() ) );
1668 }
1669
1670#if 0 // Display symbol flags, for debug only
1671 aList.emplace_back( _( "flags" ), wxString::Format( "%X", GetEditFlags() ) );
1672#endif
1673
1674 if( !m_part->IsRoot() )
1675 {
1676 msg = _( "Missing parent" );
1677
1678 std::shared_ptr< LIB_SYMBOL > parent = m_part->GetParent().lock();
1679
1680 if( parent )
1681 msg = parent->GetName();
1682
1683 aList.emplace_back( _( "Alias of" ), UnescapeString( msg ) );
1684 }
1685 else if( !m_lib_id.GetLibNickname().empty() )
1686 {
1687 aList.emplace_back( _( "Library" ), m_lib_id.GetLibNickname() );
1688 }
1689 else
1690 {
1691 aList.emplace_back( _( "Library" ), _( "Undefined!!!" ) );
1692 }
1693
1694 // Display the current associated footprint, if exists.
1695 msg = GetFootprint( currentSheet, true );
1696
1697 if( msg.IsEmpty() )
1698 msg = _( "<Unknown>" );
1699
1700 aList.emplace_back( _( "Footprint" ), msg );
1701
1702 // Display description of the symbol, and keywords found in lib
1703 aList.emplace_back( _( "Description" ), m_part->GetDescription() );
1704 aList.emplace_back( _( "Keywords" ), m_part->GetKeyWords() );
1705 }
1706 }
1707 else
1708 {
1709 aList.emplace_back( _( "Reference" ), GetRef( currentSheet ) );
1710
1711 aList.emplace_back( _( "Value" ), GetValue( currentSheet, true ) );
1712 aList.emplace_back( _( "Name" ), GetLibId().GetLibItemName() );
1713
1714 wxString libNickname = GetLibId().GetLibNickname();
1715
1716 if( libNickname.empty() )
1717 msg = _( "No library defined!" );
1718 else
1719 msg.Printf( _( "Symbol not found in %s!" ), libNickname );
1720
1721 aList.emplace_back( _( "Library" ), msg );
1722 }
1723}
1724
1725
1727{
1729}
1730
1731
1733{
1734 int dx = m_pos.x;
1735
1737 MIRROR( m_pos.x, aCenter );
1738 dx -= m_pos.x; // dx,0 is the move vector for this transform
1739
1740 for( SCH_FIELD& field : m_fields )
1741 {
1742 // Move the fields to the new position because the symbol itself has moved.
1743 VECTOR2I pos = field.GetTextPos();
1744 pos.x -= dx;
1745 field.SetTextPos( pos );
1746 }
1747}
1748
1749
1751{
1752 int dy = m_pos.y;
1753
1755 MIRROR( m_pos.y, aCenter );
1756 dy -= m_pos.y; // 0,dy is the move vector for this transform
1757
1758 for( SCH_FIELD& field : m_fields )
1759 {
1760 // Move the fields to the new position because the symbol itself has moved.
1761 VECTOR2I pos = field.GetTextPos();
1762 pos.y -= dy;
1763 field.SetTextPos( pos );
1764 }
1765}
1766
1767
1768void SCH_SYMBOL::Rotate( const VECTOR2I& aCenter )
1769{
1770 VECTOR2I prev = m_pos;
1771
1772 RotatePoint( m_pos, aCenter, ANGLE_90 );
1773
1775
1776 for( SCH_FIELD& field : m_fields )
1777 {
1778 // Move the fields to the new position because the symbol itself has moved.
1779 VECTOR2I pos = field.GetTextPos();
1780 pos.x -= prev.x - m_pos.x;
1781 pos.y -= prev.y - m_pos.y;
1782 field.SetTextPos( pos );
1783 }
1784}
1785
1786
1787bool SCH_SYMBOL::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
1788{
1789 // Symbols are searchable via the child field and pin item text.
1790 return false;
1791}
1792
1793
1794void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1795{
1796 for( auto& pin : m_pins )
1797 {
1798 LIB_PIN* lib_pin = pin->GetLibPin();
1799
1800 if( lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
1801 continue;
1802
1803 DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
1804 aItemList.push_back( item );
1805 }
1806}
1807
1808
1809bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
1810 const SCH_SHEET_PATH* aPath )
1811{
1812 bool changed = false;
1813
1814 for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1815 {
1816 bool previousState = pin->IsDangling();
1817 pin->SetIsDangling( true );
1818
1819 VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
1820
1821 for( DANGLING_END_ITEM& each_item : aItemList )
1822 {
1823 // Some people like to stack pins on top of each other in a symbol to indicate
1824 // internal connection. While technically connected, it is not particularly useful
1825 // to display them that way, so skip any pins that are in the same symbol as this
1826 // one.
1827 if( each_item.GetParent() == this )
1828 continue;
1829
1830 switch( each_item.GetType() )
1831 {
1832 case PIN_END:
1833 case LABEL_END:
1834 case SHEET_LABEL_END:
1835 case WIRE_END:
1836 case NO_CONNECT_END:
1837 case JUNCTION_END:
1838
1839 if( pos == each_item.GetPosition() )
1840 pin->SetIsDangling( false );
1841
1842 break;
1843
1844 default:
1845 break;
1846 }
1847
1848 if( !pin->IsDangling() )
1849 break;
1850 }
1851
1852 changed = ( changed || ( previousState != pin->IsDangling() ) );
1853 }
1854
1855 return changed;
1856}
1857
1858
1860{
1861 wxCHECK_MSG( Pin != nullptr && Pin->Type() == LIB_PIN_T, VECTOR2I( 0, 0 ),
1862 wxT( "Cannot get physical position of pin." ) );
1863
1865}
1866
1867
1868std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
1869{
1870 std::vector<VECTOR2I> retval;
1871
1872 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1873 {
1874 // Collect only pins attached to the current unit and convert.
1875 // others are not associated to this symbol instance
1876 int pin_unit = pin->GetLibPin()->GetUnit();
1877 int pin_convert = pin->GetLibPin()->GetConvert();
1878
1879 if( pin_unit > 0 && pin_unit != GetUnit() )
1880 continue;
1881
1882 if( pin_convert > 0 && pin_convert != GetConvert() )
1883 continue;
1884
1885 retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos );
1886 }
1887
1888 return retval;
1889}
1890
1891
1893{
1894 if( m_part )
1895 {
1896 // Calculate the position relative to the symbol.
1897 VECTOR2I libPosition = aPosition - m_pos;
1898
1899 return m_part->LocateDrawItem( m_unit, m_convert, aType, libPosition, m_transform );
1900 }
1901
1902 return nullptr;
1903}
1904
1905
1906wxString SCH_SYMBOL::GetSelectMenuText( UNITS_PROVIDER* aUnitsProvider ) const
1907{
1908 return wxString::Format( _( "Symbol %s [%s]" ),
1909 GetField( REFERENCE_FIELD )->GetShownText(),
1910 UnescapeString( GetLibId().GetLibItemName() ) );
1911}
1912
1913
1914INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData,
1915 const std::vector<KICAD_T>& aScanTypes )
1916{
1917 for( KICAD_T scanType : aScanTypes )
1918 {
1919 if( scanType == SCH_LOCATE_ANY_T
1920 || ( scanType == SCH_SYMBOL_T )
1921 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
1922 {
1923 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
1924 return INSPECT_RESULT::QUIT;
1925 }
1926
1927 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1928 {
1929 for( SCH_FIELD& field : m_fields )
1930 {
1931 if( INSPECT_RESULT::QUIT == aInspector( &field, (void*) this ) )
1932 return INSPECT_RESULT::QUIT;
1933 }
1934 }
1935
1936 if( scanType == SCH_FIELD_LOCATE_REFERENCE_T )
1937 {
1938 if( INSPECT_RESULT::QUIT == aInspector( GetField( REFERENCE_FIELD ), (void*) this ) )
1939 return INSPECT_RESULT::QUIT;
1940 }
1941
1942 if( scanType == SCH_FIELD_LOCATE_VALUE_T
1943 || ( scanType == SCH_SYMBOL_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
1944 {
1945 if( INSPECT_RESULT::QUIT == aInspector( GetField( VALUE_FIELD ), (void*) this ) )
1946 return INSPECT_RESULT::QUIT;
1947 }
1948
1949 if( scanType == SCH_FIELD_LOCATE_FOOTPRINT_T )
1950 {
1951 if( INSPECT_RESULT::QUIT == aInspector( GetField( FOOTPRINT_FIELD ), (void*) this ) )
1952 return INSPECT_RESULT::QUIT;
1953 }
1954
1955 if( scanType == SCH_FIELD_LOCATE_DATASHEET_T )
1956 {
1957 if( INSPECT_RESULT::QUIT == aInspector( GetField( DATASHEET_FIELD ), (void*) this ) )
1958 return INSPECT_RESULT::QUIT;
1959 }
1960
1961 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_PIN_T )
1962 {
1963 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1964 {
1965 // Collect only pins attached to the current unit and convert.
1966 // others are not associated to this symbol instance
1967 int pin_unit = pin->GetLibPin()->GetUnit();
1968 int pin_convert = pin->GetLibPin()->GetConvert();
1969
1970 if( pin_unit > 0 && pin_unit != GetUnit() )
1971 continue;
1972
1973 if( pin_convert > 0 && pin_convert != GetConvert() )
1974 continue;
1975
1976 if( INSPECT_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
1977 return INSPECT_RESULT::QUIT;
1978 }
1979 }
1980 }
1981
1983}
1984
1985
1986bool SCH_SYMBOL::operator <( const SCH_ITEM& aItem ) const
1987{
1988 if( Type() != aItem.Type() )
1989 return Type() < aItem.Type();
1990
1991 auto symbol = static_cast<const SCH_SYMBOL*>( &aItem );
1992
1994
1995 if( rect.GetArea() != symbol->GetBodyAndPinsBoundingBox().GetArea() )
1996 return rect.GetArea() < symbol->GetBodyAndPinsBoundingBox().GetArea();
1997
1998 if( m_pos.x != symbol->m_pos.x )
1999 return m_pos.x < symbol->m_pos.x;
2000
2001 if( m_pos.y != symbol->m_pos.y )
2002 return m_pos.y < symbol->m_pos.y;
2003
2004 return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
2005}
2006
2007
2008bool SCH_SYMBOL::operator==( const SCH_SYMBOL& aSymbol ) const
2009{
2010 if( GetFieldCount() != aSymbol.GetFieldCount() )
2011 return false;
2012
2013 for( int i = VALUE_FIELD; i < GetFieldCount(); i++ )
2014 {
2015 if( GetFields()[i].GetText().Cmp( aSymbol.GetFields()[i].GetText() ) != 0 )
2016 return false;
2017 }
2018
2019 return true;
2020}
2021
2022
2023bool SCH_SYMBOL::operator!=( const SCH_SYMBOL& aSymbol ) const
2024{
2025 return !( *this == aSymbol );
2026}
2027
2028
2030{
2031 wxCHECK_MSG( Type() == aItem.Type(), *this,
2032 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
2033 GetClass() );
2034
2035 if( &aItem != this )
2036 {
2037 SCH_ITEM::operator=( aItem );
2038
2039 SCH_SYMBOL* c = (SCH_SYMBOL*) &aItem;
2040
2041 m_lib_id = c->m_lib_id;
2042
2043 LIB_SYMBOL* libSymbol = c->m_part ? new LIB_SYMBOL( *c->m_part.get() ) : nullptr;
2044
2045 m_part.reset( libSymbol );
2046 m_pos = c->m_pos;
2047 m_unit = c->m_unit;
2048 m_convert = c->m_convert;
2050
2052
2053 m_fields = c->m_fields; // std::vector's assignment operator
2054
2055 // Reparent fields after assignment to new symbol.
2056 for( SCH_FIELD& field : m_fields )
2057 field.SetParent( this );
2058
2059 UpdatePins();
2060 }
2061
2062 return *this;
2063}
2064
2065
2066bool SCH_SYMBOL::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
2067{
2068 BOX2I bBox = GetBodyBoundingBox();
2069 bBox.Inflate( aAccuracy / 2 );
2070
2071 if( bBox.Contains( aPosition ) )
2072 return true;
2073
2074 return false;
2075}
2076
2077
2078bool SCH_SYMBOL::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
2079{
2081 return false;
2082
2083 BOX2I rect = aRect;
2084
2085 rect.Inflate( aAccuracy / 2 );
2086
2087 if( aContained )
2088 return rect.Contains( GetBodyBoundingBox() );
2089
2090 return rect.Intersects( GetBodyBoundingBox() );
2091}
2092
2093
2094bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
2095{
2097
2098 for( const auto& pin : m_pins )
2099 {
2100 if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
2101 continue;
2102
2103 // Collect only pins attached to the current unit and convert.
2104 // others are not associated to this symbol instance
2105 int pin_unit = pin->GetLibPin()->GetUnit();
2106 int pin_convert = pin->GetLibPin()->GetConvert();
2107
2108 if( pin_unit > 0 && pin_unit != GetUnit() )
2109 continue;
2110
2111 if( pin_convert > 0 && pin_convert != GetConvert() )
2112 continue;
2113
2114 if( pin->GetLocalPosition() == new_pos )
2115 return true;
2116 }
2117
2118 return false;
2119}
2120
2121
2123{
2124 return m_isInNetlist;
2125}
2126
2127
2128void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground ) const
2129{
2130 if( aBackground )
2131 return;
2132
2133 if( m_part )
2134 {
2135 LIB_PINS libPins;
2136 m_part->GetPins( libPins, GetUnit(), GetConvert() );
2137
2138 // Copy the source so we can re-orient and translate it.
2139 LIB_SYMBOL tempSymbol( *m_part );
2140 LIB_PINS tempPins;
2141 tempSymbol.GetPins( tempPins, GetUnit(), GetConvert() );
2142
2143 // Copy the pin info from the symbol to the temp pins
2144 for( unsigned i = 0; i < tempPins.size(); ++ i )
2145 {
2146 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2147 LIB_PIN* tempPin = tempPins[ i ];
2148
2149 tempPin->SetName( symbolPin->GetShownName() );
2150 tempPin->SetType( symbolPin->GetType() );
2151 tempPin->SetShape( symbolPin->GetShape() );
2152
2153 if( symbolPin->IsDangling() )
2154 tempPin->SetFlags( IS_DANGLING );
2155 }
2156
2157 TRANSFORM temp = GetTransform();
2158 aPlotter->StartBlock( nullptr );
2159
2160 for( bool local_background : { true, false } )
2161 {
2162 tempSymbol.Plot( aPlotter, GetUnit(), GetConvert(), local_background, m_pos, temp,
2163 GetDNP() );
2164
2165 for( SCH_FIELD field : m_fields )
2166 field.Plot( aPlotter, local_background );
2167 }
2168
2169 // Plot attributes to a hypertext menu
2170 std::vector<wxString> properties;
2171
2172 for( const SCH_FIELD& field : GetFields() )
2173 {
2174 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2175 field.GetName(),
2176 field.GetShownText() ) );
2177 }
2178
2179 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2180 _( "Description" ),
2181 m_part->GetDescription() ) );
2182
2183 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
2184 _( "Keywords" ),
2185 m_part->GetKeyWords() ) );
2186
2187 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
2188
2189 aPlotter->EndBlock( nullptr );
2190
2191 if( !m_part->IsPower() )
2192 aPlotter->Bookmark( GetBoundingBox(), GetField( REFERENCE_FIELD )->GetShownText(), _("Symbols") );
2193 }
2194}
2195
2196
2197void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter ) const
2198{
2199 if( m_part )
2200 {
2201 LIB_PINS libPins;
2202 m_part->GetPins( libPins, GetUnit(), GetConvert() );
2203
2204 // Copy the source to stay const
2205 LIB_SYMBOL tempSymbol( *m_part );
2206 LIB_PINS tempPins;
2207 tempSymbol.GetPins( tempPins, GetUnit(), GetConvert() );
2208
2209 TRANSFORM transform = GetTransform();
2210
2211 // Copy the pin info from the symbol to the temp pins
2212 for( unsigned i = 0; i < tempPins.size(); ++ i )
2213 {
2214 SCH_PIN* symbolPin = GetPin( libPins[ i ] );
2215 LIB_PIN* tempPin = tempPins[ i ];
2216
2217 tempPin->SetName( symbolPin->GetShownName() );
2218 tempPin->SetType( symbolPin->GetType() );
2219 tempPin->SetShape( symbolPin->GetShape() );
2220 tempPin->Plot( aPlotter, false, m_pos, transform, GetDNP() );
2221 }
2222 }
2223}
2224
2225
2227{
2228 for( const auto& pin : m_pins )
2229 {
2230 if( pin->IsBrightened() )
2231 return true;
2232 }
2233
2234 return false;
2235}
2236
2237
2239{
2240 for( auto& pin : m_pins )
2241 pin->ClearBrightened();
2242}
2243
2244
2246{
2247 for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
2248 {
2249 int pin_unit = pin->GetLibPin()->GetUnit();
2250 int pin_convert = pin->GetLibPin()->GetConvert();
2251
2252 if( pin_unit > 0 && pin_unit != GetUnit() )
2253 continue;
2254
2255 if( pin_convert > 0 && pin_convert != GetConvert() )
2256 continue;
2257
2258 if( pin->IsPointClickableAnchor( aPos ) )
2259 return true;
2260 }
2261
2262 return false;
2263}
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
@ add_component
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
void Offset(coord_type dx, coord_type dy)
Definition: box2.h:224
void SetX(coord_type val)
Definition: box2.h:235
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
void SetY(coord_type val)
Definition: box2.h:240
coord_type GetY() const
Definition: box2.h:181
void SetWidth(coord_type val)
Definition: box2.h:245
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
coord_type GetX() const
Definition: box2.h:180
coord_type GetRight() const
Definition: box2.h:189
ecoord_type GetArea() const
Return the area of the rectangle.
Definition: box2.h:701
void SetHeight(coord_type val)
Definition: box2.h:250
coord_type GetBottom() const
Definition: box2.h:190
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition: sch_item.h:82
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:147
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
void SetModified()
Definition: eda_item.cpp:64
const KIID m_Uuid
Definition: eda_item.h:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:498
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:496
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:371
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:163
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
wxString AsString() const
Definition: kiid.cpp:332
Definition: kiid.h:48
wxString AsString() const
Definition: kiid.cpp:251
Field object used in symbol libraries.
Definition: lib_field.h:60
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:117
const UTF8 & GetLibItemName() const
Definition: lib_id.h:101
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:61
int GetUnit() const
Definition: lib_item.h:273
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:78
void SetName(const wxString &aName)
Definition: lib_pin.h:114
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:91
VECTOR2I GetPosition() const override
Definition: lib_pin.h:222
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:1125
Define a library symbol object.
Definition: lib_symbol.h:98
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:707
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition: lib_symbol.h:182
bool GetIncludeOnBoard() const
Definition: lib_symbol.h:660
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:816
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Definition: lib_symbol.cpp:588
const BOX2I GetBodyBoundingBox(int aUnit, int aConvert, bool aIncludePins, bool aIncludePrivateItems) const
Get the symbol bounding box excluding fields.
bool GetIncludeInBom() const
Definition: lib_symbol.h:652
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:856
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:460
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:656
Define a symbol library graphical text item.
Definition: lib_text.h:40
Base plotter engine class.
Definition: plotter.h:110
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition: plotter.h:457
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:518
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:446
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:527
TEMPLATES m_TemplateFieldNames
Holds all the data relating to one schematic.
Definition: schematic.h:61
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:120
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:172
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:50
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:169
void ImportValues(const LIB_FIELD &aSource)
Copy parameters from a LIB_FIELD source.
Definition: sch_field.cpp:397
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition: sch_item.cpp:70
virtual wxString GetClass() const override
Return the class name.
Definition: sch_item.h:157
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:112
FIELDS_AUTOPLACED m_fieldsAutoplaced
Definition: sch_item.h:493
SCH_LAYER_ID m_layer
Definition: sch_item.h:491
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.
Schematic symbol object.
Definition: sch_symbol.h:80
wxString m_prefix
C, R, U, Q etc - the first character(s) which typically indicate what the symbol is.
Definition: sch_symbol.h:769
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction) override
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:425
VECTOR2I m_pos
Definition: sch_symbol.h:763
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:764
void SetConvert(int aConvert)
Definition: sch_symbol.cpp:402
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:328
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:282
bool ReplaceInstanceSheetPath(const KIID_PATH &aOldSheetPath, const KIID_PATH &aNewSheetPath)
Replace aOldSheetPath with aNewSheetPath in the instance list.
wxString GetSelectMenuText(UNITS_PROVIDER *aUnitsProvider) const override
Return the text to display to be used in the selection clarification context menu when multiple items...
bool HasBrightenedPins()
std::vector< SCH_FIELD > & GetFields()
Return a vector of fields from the symbol.
Definition: sch_symbol.h:415
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit, const wxString &aValue=wxEmptyString, const wxString &aFootprint=wxEmptyString)
Add a full hierarchical reference to this symbol.
Definition: sch_symbol.cpp:528
void Print(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset) override
Print a symbol.
Definition: sch_symbol.cpp:462
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.
bool operator!=(const SCH_SYMBOL &aSymbol) const
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
Definition: sch_symbol.cpp:798
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:225
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:470
const wxString GetFootprint(const SCH_SHEET_PATH *sheet, bool aResolve) const
Return the instance-specific footprint assignment for the given sheet path.
Definition: sch_symbol.cpp:836
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:968
void UpdateUnit(int aUnit)
Change the unit number to aUnit without setting any internal flags.
Definition: sch_symbol.cpp:396
wxString GetClass() const override
Return the class name.
Definition: sch_symbol.h:119
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:499
static bool IsReferenceStringValid(const wxString &aReferenceString)
Test for an acceptable reference string.
Definition: sch_symbol.cpp:671
void PlotPins(PLOTTER *aPlotter) const
Plot just the symbol pins.
std::vector< SYMBOL_INSTANCE_REFERENCE > m_instanceReferences
Definition: sch_symbol.h:798
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
Definition: sch_symbol.cpp:955
int m_convert
The alternate body style for symbols that have more than one body style defined.
Definition: sch_symbol.h:766
void SwapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:292
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:635
bool IsInNetlist() const
bool GetIncludeOnBoard() const
Definition: sch_symbol.h:748
std::unordered_map< LIB_PIN *, unsigned > m_pinMap
library pin pointer : SCH_PIN's index
Definition: sch_symbol.h:789
bool GetIncludeInBom() const
Definition: sch_symbol.h:745
void ClearBrightenedPins()
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_symbol.cpp:232
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
Definition: sch_symbol.cpp:857
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:895
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
VECTOR2I GetPinPhysicalPosition(const LIB_PIN *Pin) const
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Definition: sch_symbol.cpp:337
int GetConvert() const
Definition: sch_symbol.h:267
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
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.
Definition: sch_symbol.cpp:982
wxString m_schLibSymbolName
The name used to look up a symbol in the symbol library embedded in a schematic.
Definition: sch_symbol.h:781
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:677
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.
void PrintBackground(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset) override
Print only the background parts of a symbol (if any)
Definition: sch_symbol.cpp:450
wxString GetDescription() const
Definition: sch_symbol.cpp:310
std::vector< SCH_FIELD > m_fields
Variable length list of fields.
Definition: sch_symbol.h:784
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.
bool m_onBoard
True to include in netlist when updating board.
Definition: sch_symbol.h:793
int m_unit
The unit for multiple part per package symbols.
Definition: sch_symbol.h:765
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
Definition: sch_symbol.cpp:238
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:415
void Init(const VECTOR2I &pos=VECTOR2I(0, 0))
Definition: sch_symbol.cpp:202
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:247
bool GetInstance(SYMBOL_INSTANCE_REFERENCE &aInstance, const KIID_PATH &aSheetPath) const
Definition: sch_symbol.cpp:483
bool operator<(const SCH_ITEM &aItem) const override
bool m_DNP
True if symbol is set to 'Do Not Populate'.
Definition: sch_symbol.h:794
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
wxString GetKeyWords() const
Definition: sch_symbol.cpp:319
std::vector< LIB_PIN * > GetLibPins() const
Return a vector with all the pins from the library object.
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:907
TRANSFORM & GetTransform()
Definition: sch_symbol.h:275
bool HasUnitDisplayName(int aUnit)
Return true if the given unit aUnit has a display name set.
Definition: sch_symbol.cpp:442
BOX2I doGetBoundingBox(bool aIncludePins, bool aIncludeFields) const
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:946
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.
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:714
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:791
const wxString GetValue(const SCH_SHEET_PATH *sheet, bool aResolve) const
Return the instance-specific value for the given sheet path.
Definition: sch_symbol.cpp:770
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:728
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:386
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:172
wxString GetUnitDisplayName(int aUnit)
Return the display name for a given unit aUnit.
Definition: sch_symbol.cpp:434
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:783
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
SCH_SYMBOL & operator=(const SCH_ITEM &aItem)
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:931
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:744
std::vector< std::unique_ptr< SCH_PIN > > m_pins
a SCH_PIN for every LIB_PIN (all units)
Definition: sch_symbol.h:788
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:301
BOX2I GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the pins or fields.
wxString GetFieldText(const wxString &aFieldName) const
Search for a field named aFieldName and returns text associated with this field.
Definition: sch_symbol.cpp:919
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:261
void SortInstances(bool(*aSortFunction)(const SYMBOL_INSTANCE_REFERENCE &aLhs, const SYMBOL_INSTANCE_REFERENCE &aRhs))
Definition: sch_symbol.cpp:521
bool m_inBom
True to include in bill of materials export.
Definition: sch_symbol.h:792
std::unique_ptr< LIB_SYMBOL > m_part
a flattened copy of the LIB_SYMBOL from the PROJECT's libraries.
Definition: sch_symbol.h:786
bool operator==(const SCH_SYMBOL &aSymbol) const
bool GetDNP() const
Definition: sch_symbol.h:751
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:47
int x2
Definition: transform.h:51
int y1
Definition: transform.h:50
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:56
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
int y2
Definition: transform.h:52
int x1
Definition: transform.h:49
bool empty() const
Definition: utf8.h:103
T Convert(const wxString &aValue)
Convert a wxString to a generic type T.
Definition: eagle_parser.h:173
#define _(s)
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:414
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
E_SERIE r
Definition: eserie.cpp:41
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
@ LAYER_DANGLING
Definition: layer_ids.h:368
@ LAYER_DEVICE
Definition: layer_ids.h:357
@ LAYER_VALUEPART
Definition: layer_ids.h:353
@ LAYER_FIELDS
Definition: layer_ids.h:354
@ LAYER_DEVICE_BACKGROUND
Definition: layer_ids.h:372
@ LAYER_REFERENCEPART
Definition: layer_ids.h:352
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:381
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:54
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
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 GetText(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:98
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.
@ PT_NC
not connected (must be left open)
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
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:73
@ SHEET_LABEL_END
Definition: sch_item.h:72
@ LABEL_END
Definition: sch_item.h:69
@ JUNCTION_END
Definition: sch_item.h:67
@ PIN_END
Definition: sch_item.h:68
@ WIRE_END
Definition: sch_item.h:65
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:47
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
bool draw_visible_fields
Definition: lib_symbol.h:65
TRANSFORM transform
Definition: lib_symbol.h:63
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 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
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:164
@ SCH_FIELD_LOCATE_FOOTPRINT_T
Definition: typeinfo.h:166
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:183
@ SCH_FIELD_LOCATE_VALUE_T
Definition: typeinfo.h:165
@ LIB_PIN_T
Definition: typeinfo.h:203
@ SCH_FIELD_LOCATE_DATASHEET_T
Definition: typeinfo.h:167
@ SCH_SYMBOL_LOCATE_POWER_T
Definition: typeinfo.h:180
@ SCH_PIN_T
Definition: typeinfo.h:159
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618