KiCad PCB EDA Suite
sch_component.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-2020 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 <fctsys.h>
26 #include <sch_edit_frame.h>
27 #include <msgpanel.h>
28 #include <bitmaps.h>
29 #include <lib_rectangle.h>
30 #include <lib_pin.h>
31 #include <lib_text.h>
32 #include <sch_component.h>
33 #include <sch_sheet_path.h>
34 #include <schematic.h>
35 #include <trace_helpers.h>
36 
37 
42 std::string toUTFTildaText( const wxString& txt )
43 {
44  std::string ret = TO_UTF8( txt );
45 
46  for( std::string::iterator it = ret.begin(); it!=ret.end(); ++it )
47  {
48  if( (unsigned char) *it <= ' ' )
49  *it = '~';
50  }
51  return ret;
52 }
53 
54 
68 static LIB_PART* dummy()
69 {
70  static LIB_PART* part;
71 
72  if( !part )
73  {
74  part = new LIB_PART( wxEmptyString );
75 
76  LIB_RECTANGLE* square = new LIB_RECTANGLE( part );
77 
78  square->MoveTo( wxPoint( Mils2iu( -200 ), Mils2iu( 200 ) ) );
79  square->SetEndPosition( wxPoint( Mils2iu( 200 ), Mils2iu( -200 ) ) );
80 
81  LIB_TEXT* text = new LIB_TEXT( part );
82 
83  text->SetTextSize( wxSize( Mils2iu( 150 ), Mils2iu( 150 ) ) );
84  text->SetText( wxString( wxT( "??" ) ) );
85 
86  part->AddDrawItem( square );
87  part->AddDrawItem( text );
88  }
89 
90  return part;
91 }
92 
93 
94 SCH_COMPONENT::SCH_COMPONENT( const wxPoint& aPos, SCH_ITEM* aParent ) :
95  SCH_ITEM( aParent, SCH_COMPONENT_T )
96 {
97  Init( aPos );
98 }
99 
100 
102  int unit, int convert, const wxPoint& pos ) :
104 {
105  Init( pos );
106 
107  m_unit = unit;
108  m_convert = convert;
109  m_lib_id = aLibId;
110 
111  std::unique_ptr< LIB_PART > part;
112 
113  part = aPart.Flatten();
114  part->SetParent();
115  SetLibSymbol( part.release() );
116 
117  // Copy fields from the library component
118  UpdateFields( true, true );
119 
120  // Update the reference -- just the prefix for now.
121  if( sheet )
122  SetRef( sheet, m_part->GetReferenceField().GetText() + wxT( "?" ) );
123  else
124  m_prefix = m_part->GetReferenceField().GetText() + wxT( "?" );
125 
126  // Inherit the include in bill of materials and board netlist settings from library symbol.
127  m_inBom = aPart.GetIncludeInBom();
128  m_onBoard = aPart.GetIncludeOnBoard();
129 }
130 
131 
133  const wxPoint& pos ) :
134  SCH_COMPONENT( aPart, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, pos )
135 {
136  // Set any fields that were modified as part of the component selection
137  for( auto const& i : aSel.Fields )
138  {
139  auto field = this->GetField( i.first );
140 
141  if( field )
142  field->SetText( i.second );
143  }
144 }
145 
146 
148  SCH_ITEM( aComponent )
149 {
150  m_Parent = aComponent.m_Parent;
151  m_Pos = aComponent.m_Pos;
152  m_unit = aComponent.m_unit;
153  m_convert = aComponent.m_convert;
154  m_lib_id = aComponent.m_lib_id;
155  m_isInNetlist = aComponent.m_isInNetlist;
156  m_inBom = aComponent.m_inBom;
157  m_onBoard = aComponent.m_onBoard;
158 
159  if( aComponent.m_part )
160  SetLibSymbol( new LIB_PART( *aComponent.m_part.get() ) );
161 
162  const_cast<KIID&>( m_Uuid ) = aComponent.m_Uuid;
163 
164  m_transform = aComponent.m_transform;
165  m_prefix = aComponent.m_prefix;
167  m_Fields = aComponent.m_Fields;
168 
169  // Re-parent the fields, which before this had aComponent as parent
170  for( SCH_FIELD& field : m_Fields )
171  field.SetParent( this );
172 
174 }
175 
176 
177 void SCH_COMPONENT::Init( const wxPoint& pos )
178 {
179  m_Pos = pos;
180  m_unit = 1; // In multi unit chip - which unit to draw.
181  m_convert = LIB_ITEM::LIB_CONVERT::BASE; // De Morgan Handling
182 
183  // The rotation/mirror transformation matrix. pos normal
185 
186  // construct only the mandatory fields, which are the first 4 only.
187  for( int i = 0; i < MANDATORY_FIELDS; ++i )
188  {
189  m_Fields.emplace_back( pos, i, this, TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
190 
191  if( i == REFERENCE )
192  m_Fields.back().SetLayer( LAYER_REFERENCEPART );
193  else if( i == VALUE )
194  m_Fields.back().SetLayer( LAYER_VALUEPART );
195  else
196  m_Fields.back().SetLayer( LAYER_FIELDS );
197  }
198 
199  m_prefix = wxString( wxT( "U" ) );
200  m_isInNetlist = true;
201  m_inBom = true;
202  m_onBoard = true;
203 }
204 
205 
207 {
208  return new SCH_COMPONENT( *this );
209 }
210 
211 
212 void SCH_COMPONENT::ViewGetLayers( int aLayers[], int& aCount ) const
213 {
214  aCount = 3;
215  aLayers[0] = LAYER_DEVICE;
216  aLayers[1] = LAYER_DEVICE_BACKGROUND;
217  aLayers[2] = LAYER_SELECTION_SHADOWS;
218 }
219 
220 
221 void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId )
222 {
223  if( m_lib_id != aLibId )
224  {
225  m_lib_id = aLibId;
226  SetModified();
227  }
228 }
229 
230 
232 {
233  if( !m_schLibSymbolName.IsEmpty() )
234  return m_schLibSymbolName;
235  else
236  return m_lib_id.Format().wx_str();
237 }
238 
239 
241 {
242  wxCHECK2( ( aLibSymbol == nullptr ) || ( aLibSymbol->IsRoot() ), aLibSymbol = nullptr );
243 
244  m_part.reset( aLibSymbol );
245  UpdatePins();
246 }
247 
248 
250 {
251  if( m_part )
252  return m_part->GetDescription();
253 
254  return wxEmptyString;
255 }
256 
257 
259 {
260  if( m_part )
261  return m_part->GetDatasheetField().GetText();
262 
263  return wxEmptyString;
264 }
265 
266 
268 {
269  std::map<wxString, wxString> altPinMap;
270 
271  for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
272  {
273  if( !pin->GetAlt().IsEmpty() )
274  altPinMap[ pin->GetNumber() ] = pin->GetAlt();
275  }
276 
277  m_pins.clear();
278  m_pinMap.clear();
279 
280  if( !m_part )
281  return;
282 
283  unsigned i = 0;
284 
285  for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) )
286  {
287  wxASSERT( libPin->Type() == LIB_PIN_T );
288 
289  if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) )
290  continue;
291 
292  m_pins.push_back( std::make_unique<SCH_PIN>( libPin, this ) );
293 
294  auto ii = altPinMap.find( libPin->GetNumber() );
295 
296  if( ii != altPinMap.end() )
297  m_pins.back()->SetAlt( ii->second );
298 
299  m_pinMap[ libPin ] = i;
300 
301  ++i;
302  }
303 }
304 
305 
306 void SCH_COMPONENT::SetUnit( int aUnit )
307 {
308  if( m_unit != aUnit )
309  {
310  m_unit = aUnit;
311  SetModified();
312  }
313 }
314 
315 
316 void SCH_COMPONENT::UpdateUnit( int aUnit )
317 {
318  m_unit = aUnit;
319 }
320 
321 
322 void SCH_COMPONENT::SetConvert( int aConvert )
323 {
324  if( m_convert != aConvert )
325  {
326  m_convert = aConvert;
327 
328  // The convert may have a different pin layout so the update the pin map.
329  UpdatePins();
330  SetModified();
331  }
332 }
333 
334 
335 void SCH_COMPONENT::SetTransform( const TRANSFORM& aTransform )
336 {
337  if( m_transform != aTransform )
338  {
339  m_transform = aTransform;
340  SetModified();
341  }
342 }
343 
344 
346 {
347  if( m_part )
348  return m_part->GetUnitCount();
349 
350  return 0;
351 }
352 
353 
354 void SCH_COMPONENT::Print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset )
355 {
356  PART_DRAW_OPTIONS opts;
357  opts.transform = m_transform;
358  opts.draw_visible_fields = false;
359  opts.draw_hidden_fields = false;
360 
361  if( m_part )
362  {
363  m_part->Print( aSettings, m_Pos + aOffset, m_unit, m_convert, opts );
364  }
365  else // Use dummy() part if the actual cannot be found.
366  {
367  dummy()->Print( aSettings, m_Pos + aOffset, 0, 0, opts );
368  }
369 
370  for( SCH_FIELD& field : m_Fields )
371  field.Print( aSettings, aOffset );
372 }
373 
374 
375 void SCH_COMPONENT::AddHierarchicalReference( const KIID_PATH& aPath, const wxString& aRef,
376  int aUnit, const wxString& aValue,
377  const wxString& aFootprint )
378 {
379  // Search for an existing path and remove it if found (should not occur)
380  for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
381  {
382  if( m_instanceReferences[ii].m_Path == aPath )
383  {
384  wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
385  " sheet path %s\n"
386  " reference %s, unit %d from symbol %s.",
387  aPath.AsString(),
388  m_instanceReferences[ii].m_Reference,
389  m_instanceReferences[ii].m_Unit,
390  m_Uuid.AsString() );
391 
392  m_instanceReferences.erase( m_instanceReferences.begin() + ii );
393  ii--;
394  }
395  }
396 
398  instance.m_Path = aPath;
399  instance.m_Reference = aRef;
400  instance.m_Unit = aUnit;
401  instance.m_Value = aValue;
402  instance.m_Footprint = aFootprint;
403 
404  wxLogTrace( traceSchSheetPaths, "Adding symbol instance:\n"
405  " sheet path %s\n"
406  " reference %s, unit %d to symbol %s.",
407  aPath.AsString(),
408  aRef,
409  aUnit,
410  m_Uuid.AsString() );
411 
412  m_instanceReferences.push_back( instance );
413 }
414 
415 
416 const wxString SCH_COMPONENT::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUnit ) const
417 {
418  KIID_PATH path = sheet->Path();
419  wxString ref;
420 
421  for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
422  {
423  if( instance.m_Path == path )
424  {
425  ref = instance.m_Reference;
426  break;
427  }
428  }
429 
430  // If it was not found in m_Paths array, then see if it is in m_Field[REFERENCE] -- if so,
431  // use this as a default for this path. This will happen if we load a version 1 schematic
432  // file. It will also mean that multiple instances of the same sheet by default all have
433  // the same component references, but perhaps this is best.
434  if( ref.IsEmpty() && !GetField( REFERENCE )->GetText().IsEmpty() )
435  {
436  const_cast<SCH_COMPONENT*>( this )->SetRef( sheet, GetField( REFERENCE )->GetText() );
437  ref = GetField( REFERENCE )->GetText();
438  }
439 
440  if( ref.IsEmpty() )
441  ref = m_prefix;
442 
443  if( aIncludeUnit && GetUnitCount() > 1 )
444  ref += LIB_PART::SubReference( GetUnit() );
445 
446  return ref;
447 }
448 
449 
450 bool SCH_COMPONENT::IsReferenceStringValid( const wxString& aReferenceString )
451 {
452  wxString text = aReferenceString;
453  bool ok = true;
454 
455  // Try to unannotate this reference
456  while( !text.IsEmpty() && ( text.Last() == '?' || wxIsdigit( text.Last() ) ) )
457  text.RemoveLast();
458 
459  if( text.IsEmpty() )
460  ok = false;
461 
462  return ok;
463 }
464 
465 
466 void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
467 {
468  KIID_PATH path = sheet->Path();
469  bool notInArray = true;
470 
471  // check to see if it is already there before inserting it
473  {
474  if( instance.m_Path == path )
475  {
476  instance.m_Reference = ref;
477  notInArray = false;
478  }
479  }
480 
481  if( notInArray )
482  AddHierarchicalReference( path, ref, m_unit );
483 
484  for( std::unique_ptr<SCH_PIN>& pin : m_pins )
485  pin->ClearDefaultNetName( sheet );
486 
487  SCH_FIELD* rf = GetField( REFERENCE );
488 
489  // @todo Should we really be checking for what is a "reasonable" position?
490  if( rf->GetText().IsEmpty()
491  || ( abs( rf->GetTextPos().x - m_Pos.x ) +
492  abs( rf->GetTextPos().y - m_Pos.y ) > Mils2iu( 10000 ) ) )
493  {
494  // move it to a reasonable position
495  rf->SetTextPos( m_Pos + wxPoint( Mils2iu( 50 ), Mils2iu( 50 ) ) );
496  }
497 
498  rf->SetText( ref ); // for drawing.
499 
500  // Reinit the m_prefix member if needed
501  wxString prefix = ref;
502 
503  if( IsReferenceStringValid( prefix ) )
504  {
505  while( prefix.Last() == '?' || wxIsdigit( prefix.Last() ) )
506  prefix.RemoveLast();
507  }
508  else
509  {
510  prefix = wxT( "U" ); // Set to default ref prefix
511  }
512 
513  if( m_prefix != prefix )
514  m_prefix = prefix;
515 
516  // Power components have references starting with # and are not included in netlists
517  m_isInNetlist = ! ref.StartsWith( wxT( "#" ) );
518 }
519 
520 
522 {
523  KIID_PATH path = aSheet->Path();
524 
525  for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
526  {
527  if( instance.m_Path == path )
528  return instance.m_Reference.Last() != '?';
529  }
530 
531  return false;
532 }
533 
534 
536 {
537  KIID_PATH path = aSheet->Path();
538 
539  for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
540  {
541  if( instance.m_Path == path )
542  return instance.m_Unit;
543  }
544 
545  // If it was not found in m_Paths array, then use m_unit. This will happen if we load a
546  // version 1 schematic file.
547  return m_unit;
548 }
549 
550 
551 void SCH_COMPONENT::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
552 {
553  KIID_PATH path = aSheet->Path();
554 
555  // check to see if it is already there before inserting it
557  {
558  if( instance.m_Path == path )
559  {
560  instance.m_Unit = aUnitSelection;
561  return;
562  }
563  }
564 
565  // didn't find it; better add it
566  AddHierarchicalReference( path, m_prefix, aUnitSelection );
567 }
568 
569 
570 const wxString SCH_COMPONENT::GetValue( const SCH_SHEET_PATH* sheet ) const
571 {
572  KIID_PATH path = sheet->Path();
573 
574  for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
575  {
576  if( instance.m_Path == path && !instance.m_Value.IsEmpty() )
577  {
578  SCH_FIELD dummy( wxDefaultPosition, VALUE, const_cast<SCH_COMPONENT*>( this ) );
579  dummy.SetText( instance.m_Value );
580  return dummy.GetShownText();
581  }
582  }
583 
584  return GetField( VALUE )->GetShownText();
585 }
586 
587 
588 void SCH_COMPONENT::SetValue( const SCH_SHEET_PATH* sheet, const wxString& aValue )
589 {
590  if( sheet == nullptr )
591  {
592  // Clear instance overrides and set primary field value
594  instance.m_Value = wxEmptyString;
595 
596  m_Fields[ VALUE ].SetText( aValue );
597  return;
598  }
599 
600  KIID_PATH path = sheet->Path();
601 
602  // check to see if it is already there before inserting it
604  {
605  if( instance.m_Path == path )
606  {
607  instance.m_Value = aValue;
608  return;
609  }
610  }
611 
612  // didn't find it; better add it
613  AddHierarchicalReference( path, m_prefix, m_unit, aValue, wxEmptyString );
614 }
615 
616 
617 const wxString SCH_COMPONENT::GetFootprint( const SCH_SHEET_PATH* sheet ) const
618 {
619  KIID_PATH path = sheet->Path();
620 
621  for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
622  {
623  if( instance.m_Path == path && !instance.m_Footprint.IsEmpty() )
624  {
625  SCH_FIELD dummy( wxDefaultPosition, FOOTPRINT, const_cast<SCH_COMPONENT*>( this ) );
626  dummy.SetText( instance.m_Footprint );
627  return dummy.GetShownText();
628  }
629  }
630 
631  return GetField( FOOTPRINT )->GetShownText();
632 }
633 
634 
635 void SCH_COMPONENT::SetFootprint( const SCH_SHEET_PATH* sheet, const wxString& aFootprint )
636 {
637  if( sheet == nullptr )
638  {
639  // Clear instance overrides and set primary field value
641  instance.m_Footprint = wxEmptyString;
642 
643  m_Fields[ FOOTPRINT ].SetText( aFootprint );
644  return;
645  }
646 
647  KIID_PATH path = sheet->Path();
648 
649  // check to see if it is already there before inserting it
651  {
652  if( instance.m_Path == path )
653  {
654  instance.m_Footprint = aFootprint;
655  return;
656  }
657  }
658 
659  // didn't find it; better add it
660  AddHierarchicalReference( path, m_prefix, m_unit, wxEmptyString, aFootprint );
661 }
662 
663 
665 {
666  if( (unsigned) aFieldNdx < m_Fields.size() )
667  return &m_Fields[aFieldNdx];
668 
669  return nullptr;
670 }
671 
672 
673 const SCH_FIELD* SCH_COMPONENT::GetField( int aFieldNdx ) const
674 {
675  if( (unsigned) aFieldNdx < m_Fields.size() )
676  return &m_Fields[aFieldNdx];
677 
678  return nullptr;
679 }
680 
681 
682 wxString SCH_COMPONENT::GetFieldText( const wxString& aFieldName, SCH_EDIT_FRAME* aFrame ) const
683 {
684  for( const SCH_FIELD& field : m_Fields )
685  {
686  if( aFieldName == field.GetName() )
687  return field.GetText();
688  }
689 
690  return wxEmptyString;
691 }
692 
693 
694 void SCH_COMPONENT::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
695 {
696  for( SCH_FIELD& field : m_Fields )
697  {
698  if( !aVisibleOnly || ( field.IsVisible() && !field.IsVoid() ) )
699  aVector.push_back( &field );
700  }
701 }
702 
703 
705 {
706  int newNdx = m_Fields.size();
707 
708  m_Fields.push_back( aField );
709  return &m_Fields[newNdx];
710 }
711 
712 
713 void SCH_COMPONENT::RemoveField( const wxString& aFieldName )
714 {
715  for( unsigned i = MANDATORY_FIELDS; i < m_Fields.size(); ++i )
716  {
717  if( aFieldName == m_Fields[i].GetName( false ) )
718  {
719  m_Fields.erase( m_Fields.begin() + i );
720  return;
721  }
722  }
723 }
724 
725 
726 SCH_FIELD* SCH_COMPONENT::FindField( const wxString& aFieldName, bool aIncludeDefaultFields )
727 {
728  unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
729 
730  for( unsigned i = start; i < m_Fields.size(); ++i )
731  {
732  if( aFieldName == m_Fields[i].GetName( false ) )
733  return &m_Fields[i];
734  }
735 
736  return NULL;
737 }
738 
739 
740 void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
741 {
742  if( m_part )
743  {
744  wxString symbolName;
745  LIB_FIELDS fields;
746  m_part->GetFields( fields );
747 
748  for( const LIB_FIELD& libField : fields )
749  {
750  int idx = libField.GetId();
751  SCH_FIELD* schField;
752 
753  if( idx == REFERENCE && !aResetRef )
754  continue;
755 
756  if( idx >= 0 && idx < MANDATORY_FIELDS )
757  {
758  schField = GetField( idx );
759  }
760  else
761  {
762  schField = FindField( libField.GetCanonicalName() );
763 
764  if( !schField )
765  {
766  wxString fieldName = libField.GetCanonicalName();
767  SCH_FIELD newField( wxPoint( 0, 0), GetFieldCount(), this, fieldName );
768  schField = AddField( newField );
769  }
770  }
771 
772  if( aResetStyle )
773  {
774  schField->ImportValues( libField );
775  schField->SetTextPos( m_Pos + libField.GetTextPos() );
776  }
777 
778  if( idx == VALUE )
779  {
780  schField->SetText( m_lib_id.GetLibItemName() ); // fetch alias-specific value
781  symbolName = m_lib_id.GetLibItemName();
782  }
783  else if( idx == DATASHEET )
784  {
785  schField->SetText( GetDatasheet() ); // fetch alias-specific value
786  }
787  else
788  {
789  schField->SetText( libField.GetText() );
790  }
791  }
792  }
793 }
794 
795 
796 SCH_PIN* SCH_COMPONENT::GetPin( const wxString& aNumber )
797 {
798  for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
799  {
800  if( pin->GetNumber() == aNumber )
801  return pin.get();
802  }
803 
804  return nullptr;
805 }
806 
807 
808 void SCH_COMPONENT::GetLibPins( std::vector<LIB_PIN*>& aPinsList )
809 {
810  if( m_part )
811  m_part->GetPins( aPinsList, m_unit, m_convert );
812 }
813 
814 
816 {
817  wxASSERT( m_pinMap.count( aLibPin ) );
818  return m_pins[ m_pinMap.at( aLibPin ) ].get();
819 }
820 
821 
822 std::vector<SCH_PIN*> SCH_COMPONENT::GetPins( const SCH_SHEET_PATH* aSheet ) const
823 {
824  std::vector<SCH_PIN*> pins;
825 
826  if( aSheet == nullptr )
827  {
828  wxCHECK_MSG( Schematic(), pins, "Can't call GetPins on a component with no schematic" );
829 
830  aSheet = &Schematic()->CurrentSheet();
831  }
832 
833  int unit = GetUnitSelection( aSheet );
834 
835  for( const auto& p : m_pins )
836  {
837  if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
838  continue;
839 
840  pins.push_back( p.get() );
841  }
842 
843  return pins;
844 }
845 
846 
848 {
849  wxCHECK_RET( (aItem != NULL) && (aItem->Type() == SCH_COMPONENT_T),
850  wxT( "Cannot swap data with invalid component." ) );
851 
852  SCH_COMPONENT* component = (SCH_COMPONENT*) aItem;
853 
854  std::swap( m_lib_id, component->m_lib_id );
855 
856  LIB_PART* part = component->m_part.release();
857  component->m_part.reset( m_part.release() );
858  component->UpdatePins();
859  m_part.reset( part );
860  UpdatePins();
861 
862  std::swap( m_Pos, component->m_Pos );
863  std::swap( m_unit, component->m_unit );
864  std::swap( m_convert, component->m_convert );
865 
866  m_Fields.swap( component->m_Fields ); // std::vector's swap()
867 
868  for( SCH_FIELD& field : component->m_Fields )
869  field.SetParent( component );
870 
871  for( SCH_FIELD& field : m_Fields )
872  field.SetParent( this );
873 
874  TRANSFORM tmp = m_transform;
875 
876  m_transform = component->m_transform;
877  component->m_transform = tmp;
878 
879  std::swap( m_instanceReferences, component->m_instanceReferences );
880 }
881 
882 
883 void SCH_COMPONENT::GetContextualTextVars( wxArrayString* aVars ) const
884 {
885  for( int i = 0; i < MANDATORY_FIELDS; ++i )
886  aVars->push_back( m_Fields[i].GetCanonicalName().Upper() );
887 
888  for( size_t i = MANDATORY_FIELDS; i < m_Fields.size(); ++i )
889  aVars->push_back( m_Fields[i].GetName() );
890 
891  aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
892  aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
893  aVars->push_back( wxT( "UNIT" ) );
894 }
895 
896 
897 bool SCH_COMPONENT::ResolveTextVar( wxString* token, int aDepth ) const
898 {
899  SCHEMATIC* schematic = Schematic();
900 
901  for( int i = 0; i < MANDATORY_FIELDS; ++i )
902  {
903  if( token->IsSameAs( m_Fields[ i ].GetCanonicalName().Upper() ) )
904  {
905  if( i == REFERENCE && schematic )
906  *token = GetRef( &schematic->CurrentSheet(), true );
907  else if( i == VALUE && schematic )
908  *token = GetValue( &schematic->CurrentSheet() );
909  else if( i == FOOTPRINT && schematic )
910  *token = GetFootprint( &schematic->CurrentSheet() );
911  else
912  *token = m_Fields[ i ].GetShownText( aDepth + 1 );
913 
914  return true;
915  }
916  }
917 
918  for( size_t i = MANDATORY_FIELDS; i < m_Fields.size(); ++i )
919  {
920  if( token->IsSameAs( m_Fields[ i ].GetName() )
921  || token->IsSameAs( m_Fields[ i ].GetName().Upper() ) )
922  {
923  *token = m_Fields[ i ].GetShownText( aDepth + 1 );
924  return true;
925  }
926  }
927 
928  if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
929  {
930  wxString footprint;
931 
932  if( schematic )
933  footprint = GetFootprint( &schematic->CurrentSheet() );
934  else
935  footprint = m_Fields[ FOOTPRINT ].GetShownText();
936 
937  wxArrayString parts = wxSplit( footprint, ':' );
938 
939  *token = parts[ 0 ];
940  return true;
941  }
942  else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
943  {
944  wxString footprint;
945 
946  if( schematic )
947  footprint = GetFootprint( &schematic->CurrentSheet() );
948  else
949  footprint = m_Fields[ FOOTPRINT ].GetShownText();
950 
951  wxArrayString parts = wxSplit( footprint, ':' );
952 
953  *token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
954  return true;
955  }
956  else if( token->IsSameAs( wxT( "UNIT" ) ) )
957  {
958  int unit;
959 
960  if( schematic )
961  unit = GetUnitSelection( &schematic->CurrentSheet() );
962  else
963  unit = GetUnit();
964 
965  *token = LIB_PART::SubReference( unit );
966  return true;
967  }
968 
969  return false;
970 }
971 
972 
974 {
975  // Build a reference with no annotation,
976  // i.e. a reference ended by only one '?'
977  wxString defRef = m_prefix;
978 
979  if( !IsReferenceStringValid( defRef ) )
980  { // This is a malformed reference: reinit this reference
981  m_prefix = defRef = wxT("U"); // Set to default ref prefix
982  }
983 
984  while( defRef.Last() == '?' )
985  defRef.RemoveLast();
986 
987  defRef.Append( wxT( "?" ) );
988 
989  if( aSheetPath )
990  {
991  KIID_PATH path = aSheetPath->Path();
992 
994  {
995  if( instance.m_Path == path )
996  instance.m_Reference = defRef;
997  }
998  }
999  else
1000  {
1002  instance.m_Reference = defRef;
1003  }
1004 
1005  for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1006  pin->ClearDefaultNetName( aSheetPath );
1007 
1008  // These 2 changes do not work in complex hierarchy.
1009  // When a clear annotation is made, the calling function must call a
1010  // UpdateAllScreenReferences for the active sheet.
1011  // But this call cannot made here.
1012  m_Fields[REFERENCE].SetText( defRef ); //for drawing.
1013 }
1014 
1015 
1017 {
1018  // a empty sheet path is illegal:
1019  wxCHECK( aSheetPath.size() > 0, false );
1020 
1021  wxString reference_path;
1022 
1023  for( const COMPONENT_INSTANCE_REFERENCE& instance : m_instanceReferences )
1024  {
1025  // if aSheetPath is found, nothing to do:
1026  if( instance.m_Path == aSheetPath )
1027  return false;
1028  }
1029 
1030  // This entry does not exist: add it, with its last-used reference
1031  AddHierarchicalReference( aSheetPath, m_Fields[REFERENCE].GetText(), m_unit );
1032  return true;
1033 }
1034 
1035 
1037  const KIID_PATH& aNewSheetPath )
1038 {
1039  auto it = std::find_if( m_instanceReferences.begin(), m_instanceReferences.end(),
1040  [ aOldSheetPath ]( COMPONENT_INSTANCE_REFERENCE& r )->bool
1041  {
1042  return aOldSheetPath == r.m_Path;
1043  }
1044  );
1045 
1046  if( it != m_instanceReferences.end() )
1047  {
1048  wxLogTrace( traceSchSheetPaths,
1049  "Replacing sheet path %s\n with sheet path %s\n for symbol %s.",
1050  aOldSheetPath.AsString(), aNewSheetPath.AsString(), m_Uuid.AsString() );
1051 
1052  it->m_Path = aNewSheetPath;
1053  return true;
1054  }
1055 
1056  wxLogTrace( traceSchSheetPaths,
1057  "Could not find sheet path %s\n to replace with sheet path %s\n for symbol %s.",
1058  aOldSheetPath.AsString(), aNewSheetPath.AsString(), m_Uuid.AsString() );
1059 
1060  return false;
1061 }
1062 
1063 
1064 void SCH_COMPONENT::SetOrientation( int aOrientation )
1065 {
1066  TRANSFORM temp = TRANSFORM();
1067  bool transform = false;
1068 
1069  switch( aOrientation )
1070  {
1071  case CMP_ORIENT_0:
1072  case CMP_NORMAL: // default transform matrix
1073  m_transform.x1 = 1;
1074  m_transform.y2 = -1;
1075  m_transform.x2 = m_transform.y1 = 0;
1076  break;
1077 
1078  case CMP_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
1079  temp.x1 = temp.y2 = 0;
1080  temp.y1 = 1;
1081  temp.x2 = -1;
1082  transform = true;
1083  break;
1084 
1085  case CMP_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1086  temp.x1 = temp.y2 = 0;
1087  temp.y1 = -1;
1088  temp.x2 = 1;
1089  transform = true;
1090  break;
1091 
1092  case CMP_MIRROR_Y: // Mirror Y (incremental rotation)
1093  temp.x1 = -1;
1094  temp.y2 = 1;
1095  temp.y1 = temp.x2 = 0;
1096  transform = true;
1097  break;
1098 
1099  case CMP_MIRROR_X: // Mirror X (incremental rotation)
1100  temp.x1 = 1;
1101  temp.y2 = -1;
1102  temp.y1 = temp.x2 = 0;
1103  transform = true;
1104  break;
1105 
1106  case CMP_ORIENT_90:
1109  break;
1110 
1111  case CMP_ORIENT_180:
1115  break;
1116 
1117  case CMP_ORIENT_270:
1120  break;
1121 
1122  case ( CMP_ORIENT_0 + CMP_MIRROR_X ):
1125  break;
1126 
1127  case ( CMP_ORIENT_0 + CMP_MIRROR_Y ):
1130  break;
1131 
1132  case ( CMP_ORIENT_90 + CMP_MIRROR_X ):
1135  break;
1136 
1137  case ( CMP_ORIENT_90 + CMP_MIRROR_Y ):
1140  break;
1141 
1142  case ( CMP_ORIENT_180 + CMP_MIRROR_X ):
1145  break;
1146 
1147  case ( CMP_ORIENT_180 + CMP_MIRROR_Y ):
1150  break;
1151 
1152  case ( CMP_ORIENT_270 + CMP_MIRROR_X ):
1155  break;
1156 
1157  case ( CMP_ORIENT_270 + CMP_MIRROR_Y ):
1160  break;
1161 
1162  default:
1163  transform = false;
1164  wxFAIL_MSG( "Invalid schematic symbol orientation type." );
1165  break;
1166  }
1167 
1168  if( transform )
1169  {
1170  /* The new matrix transform is the old matrix transform modified by the
1171  * requested transformation, which is the temp transform (rot,
1172  * mirror ..) in order to have (in term of matrix transform):
1173  * transform coord = new_m_transform * coord
1174  * where transform coord is the coord modified by new_m_transform from
1175  * the initial value coord.
1176  * new_m_transform is computed (from old_m_transform and temp) to
1177  * have:
1178  * transform coord = old_m_transform * temp
1179  */
1180  TRANSFORM newTransform;
1181 
1182  newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1183  newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1184  newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1185  newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1186  m_transform = newTransform;
1187  }
1188 }
1189 
1190 
1192 {
1193  int rotate_values[] =
1194  {
1195  CMP_ORIENT_0,
1196  CMP_ORIENT_90,
1202  CMP_MIRROR_Y,
1207  };
1208 
1209  // Try to find the current transform option:
1210  TRANSFORM transform = m_transform;
1211 
1212  for( int type_rotate : rotate_values )
1213  {
1214  SetOrientation( type_rotate );
1215 
1216  if( transform == m_transform )
1217  return type_rotate;
1218  }
1219 
1220  // Error: orientation not found in list (should not happen)
1221  wxFAIL_MSG( "Schematic symbol orientation matrix internal error." );
1222  m_transform = transform;
1223 
1224  return CMP_NORMAL;
1225 }
1226 
1227 
1228 #if defined(DEBUG)
1229 
1230 void SCH_COMPONENT::Show( int nestLevel, std::ostream& os ) const
1231 {
1232  // for now, make it look like XML:
1233  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1234  << " ref=\"" << TO_UTF8( GetField( 0 )->GetName() )
1235  << '"' << " chipName=\""
1236  << GetLibId().Format() << '"' << m_Pos
1237  << " layer=\"" << m_Layer
1238  << '"' << ">\n";
1239 
1240  // skip the reference, it's been output already.
1241  for( int i = 1; i < GetFieldCount(); ++i )
1242  {
1243  wxString value = GetField( i )->GetText();
1244 
1245  if( !value.IsEmpty() )
1246  {
1247  NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
1248  << TO_UTF8( GetField( i )->GetName() )
1249  << '"' << " value=\""
1250  << TO_UTF8( value ) << "\"/>\n";
1251  }
1252  }
1253 
1254  NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
1255 }
1256 
1257 #endif
1258 
1259 
1261 {
1262  EDA_RECT bBox;
1263 
1264  if( m_part )
1265  bBox = m_part->GetBodyBoundingBox( m_unit, m_convert );
1266  else
1267  bBox = dummy()->GetBodyBoundingBox( m_unit, m_convert );
1268 
1269  int x0 = bBox.GetX();
1270  int xm = bBox.GetRight();
1271 
1272  // We must reverse Y values, because matrix orientation
1273  // suppose Y axis normal for the library items coordinates,
1274  // m_transform reverse Y values, but bBox is already reversed!
1275  int y0 = -bBox.GetY();
1276  int ym = -bBox.GetBottom();
1277 
1278  // Compute the real Boundary box (rotated, mirrored ...)
1279  int x1 = m_transform.x1 * x0 + m_transform.y1 * y0;
1280  int y1 = m_transform.x2 * x0 + m_transform.y2 * y0;
1281  int x2 = m_transform.x1 * xm + m_transform.y1 * ym;
1282  int y2 = m_transform.x2 * xm + m_transform.y2 * ym;
1283 
1284  bBox.SetX( x1 );
1285  bBox.SetY( y1 );
1286  bBox.SetWidth( x2 - x1 );
1287  bBox.SetHeight( y2 - y1 );
1288  bBox.Normalize();
1289 
1290  bBox.Offset( m_Pos );
1291  return bBox;
1292 }
1293 
1294 
1296 {
1297  EDA_RECT bbox = GetBodyBoundingBox();
1298 
1299  for( const SCH_FIELD& field : m_Fields )
1300  bbox.Merge( field.GetBoundingBox() );
1301 
1302  return bbox;
1303 }
1304 
1305 
1306 const EDA_RECT SCH_COMPONENT::GetBoundingBox( bool aIncludeInvisibleText ) const
1307 {
1308  EDA_RECT bbox = GetBodyBoundingBox();
1309 
1310  for( const SCH_FIELD& field : m_Fields )
1311  {
1312  if( field.IsVisible() || aIncludeInvisibleText )
1313  bbox.Merge( field.GetBoundingBox() );
1314  }
1315 
1316  return bbox;
1317 }
1318 
1319 
1321 {
1322  wxString msg;
1323 
1324  SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1325  SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
1326 
1327  // part and alias can differ if alias is not the root
1328  if( m_part )
1329  {
1330  if( m_part.get() != dummy() )
1331  {
1332  aList.push_back( MSG_PANEL_ITEM( _( "Reference" ), GetRef( currentSheet ), DARKCYAN ) );
1333 
1334  msg = m_part->IsPower() ? _( "Power symbol" ) : _( "Value" );
1335 
1336  aList.push_back( MSG_PANEL_ITEM( msg, GetValue( currentSheet ), DARKCYAN ) );
1337 
1338 #if 0 // Display component flags, for debug only
1339  aList.push_back( MSG_PANEL_ITEM( _( "flags" ),
1340  wxString::Format("%X", GetEditFlags()), BROWN ) );
1341 #endif
1342 
1343  // Display component reference in library and library
1344  aList.push_back( MSG_PANEL_ITEM( _( "Name" ), GetLibId().GetLibItemName(), BROWN ) );
1345 
1346  if( !m_part->IsRoot() )
1347  {
1348  msg = _( "Missing parent" );
1349 
1350  std::shared_ptr< LIB_PART > parent = m_part->GetParent().lock();
1351 
1352  if( parent )
1353  msg = parent->GetName();
1354 
1355  aList.push_back( MSG_PANEL_ITEM( _( "Alias of" ), msg, BROWN ) );
1356  }
1357  else if( !m_lib_id.GetLibNickname().empty() )
1358  {
1359  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), m_lib_id.GetLibNickname(),
1360  BROWN ) );
1361  }
1362  else
1363  {
1364  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), _( "Undefined!!!" ), RED ) );
1365  }
1366 
1367  // Display the current associated footprint, if exists.
1368  msg = GetFootprint( currentSheet );
1369 
1370  if( msg.IsEmpty() )
1371  msg = _( "<Unknown>" );
1372 
1373  aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), msg, DARKRED ) );
1374 
1375  // Display description of the component, and keywords found in lib
1376  aList.push_back( MSG_PANEL_ITEM( _( "Description" ), m_part->GetDescription(),
1377  DARKCYAN ) );
1378  aList.push_back( MSG_PANEL_ITEM( _( "Key words" ), m_part->GetKeyWords(), DARKCYAN ) );
1379  }
1380  }
1381  else
1382  {
1383  aList.push_back( MSG_PANEL_ITEM( _( "Reference" ), GetRef( currentSheet ), DARKCYAN ) );
1384 
1385  aList.push_back( MSG_PANEL_ITEM( _( "Value" ), GetValue( currentSheet ), DARKCYAN ) );
1386  aList.push_back( MSG_PANEL_ITEM( _( "Name" ), GetLibId().GetLibItemName(), BROWN ) );
1387 
1388  wxString libNickname = GetLibId().GetLibNickname();
1389 
1390  if( libNickname.empty() )
1391  {
1392  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), _( "No library defined!" ), RED ) );
1393  }
1394  else
1395  {
1396  msg.Printf( _( "Symbol not found in %s!" ), libNickname );
1397  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), msg , RED ) );
1398  }
1399  }
1400 }
1401 
1402 
1404 {
1405  return add_component_xpm;
1406 }
1407 
1408 
1409 void SCH_COMPONENT::MirrorY( int aYaxis_position )
1410 {
1411  int dx = m_Pos.x;
1412 
1414  MIRROR( m_Pos.x, aYaxis_position );
1415  dx -= m_Pos.x; // dx,0 is the move vector for this transform
1416 
1417  for( SCH_FIELD& field : m_Fields )
1418  {
1419  // Move the fields to the new position because the component itself has moved.
1420  wxPoint pos = field.GetTextPos();
1421  pos.x -= dx;
1422  field.SetTextPos( pos );
1423  }
1424 }
1425 
1426 
1427 void SCH_COMPONENT::MirrorX( int aXaxis_position )
1428 {
1429  int dy = m_Pos.y;
1430 
1432  MIRROR( m_Pos.y, aXaxis_position );
1433  dy -= m_Pos.y; // dy,0 is the move vector for this transform
1434 
1435  for( SCH_FIELD& field : m_Fields )
1436  {
1437  // Move the fields to the new position because the component itself has moved.
1438  wxPoint pos = field.GetTextPos();
1439  pos.y -= dy;
1440  field.SetTextPos( pos );
1441  }
1442 }
1443 
1444 
1446 {
1447  wxPoint prev = m_Pos;
1448 
1449  RotatePoint( &m_Pos, aPosition, 900 );
1450 
1452 
1453  for( SCH_FIELD& field : m_Fields )
1454  {
1455  // Move the fields to the new position because the component itself has moved.
1456  wxPoint pos = field.GetTextPos();
1457  pos.x -= prev.x - m_Pos.x;
1458  pos.y -= prev.y - m_Pos.y;
1459  field.SetTextPos( pos );
1460  }
1461 }
1462 
1463 
1464 bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData )
1465 {
1466  wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText( EDA_UNITS::MILLIMETRES ) );
1467 
1468  // Components are searchable via the child field and pin item text.
1469  return false;
1470 }
1471 
1472 
1473 void SCH_COMPONENT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1474 {
1475  for( auto& pin : m_pins )
1476  {
1477  LIB_PIN* lib_pin = pin->GetLibPin();
1478 
1479  if( lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
1480  continue;
1481 
1482  DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
1483  aItemList.push_back( item );
1484  }
1485 }
1486 
1487 
1488 bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
1489  const SCH_SHEET_PATH* aPath )
1490 {
1491  bool changed = false;
1492 
1493  for( std::unique_ptr<SCH_PIN>& pin : m_pins )
1494  {
1495  bool previousState = pin->IsDangling();
1496  pin->SetIsDangling( true );
1497 
1498  wxPoint pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_Pos;
1499 
1500  for( DANGLING_END_ITEM& each_item : aItemList )
1501  {
1502  // Some people like to stack pins on top of each other in a symbol to indicate
1503  // internal connection. While technically connected, it is not particularly useful
1504  // to display them that way, so skip any pins that are in the same symbol as this
1505  // one.
1506  if( each_item.GetParent() == this )
1507  continue;
1508 
1509  switch( each_item.GetType() )
1510  {
1511  case PIN_END:
1512  case LABEL_END:
1513  case SHEET_LABEL_END:
1514  case WIRE_START_END:
1515  case WIRE_END_END:
1516  case NO_CONNECT_END:
1517  case JUNCTION_END:
1518 
1519  if( pos == each_item.GetPosition() )
1520  pin->SetIsDangling( false );
1521 
1522  break;
1523 
1524  default:
1525  break;
1526  }
1527 
1528  if( !pin->IsDangling() )
1529  break;
1530  }
1531 
1532  changed = ( changed || ( previousState != pin->IsDangling() ) );
1533  }
1534 
1535  return changed;
1536 }
1537 
1538 
1540 {
1541  wxCHECK_MSG( Pin != NULL && Pin->Type() == LIB_PIN_T, wxPoint( 0, 0 ),
1542  wxT( "Cannot get physical position of pin." ) );
1543 
1544  return m_transform.TransformCoordinate( Pin->GetPosition() ) + m_Pos;
1545 }
1546 
1547 
1548 std::vector<wxPoint> SCH_COMPONENT::GetConnectionPoints() const
1549 {
1550  std::vector<wxPoint> retval;
1551 
1552  for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1553  {
1554  // Collect only pins attached to the current unit and convert.
1555  // others are not associated to this component instance
1556  int pin_unit = pin->GetLibPin()->GetUnit();
1557  int pin_convert = pin->GetLibPin()->GetConvert();
1558 
1559  if( pin_unit > 0 && pin_unit != GetUnit() )
1560  continue;
1561 
1562  if( pin_convert > 0 && pin_convert != GetConvert() )
1563  continue;
1564 
1565  retval.push_back( m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_Pos );
1566  }
1567 
1568  return retval;
1569 }
1570 
1571 
1573 {
1574  if( m_part )
1575  {
1576  // Calculate the position relative to the component.
1577  wxPoint libPosition = aPosition - m_Pos;
1578 
1579  return m_part->LocateDrawItem( m_unit, m_convert, aType, libPosition, m_transform );
1580  }
1581 
1582  return NULL;
1583 }
1584 
1585 
1587 {
1588  return wxString::Format( _( "Symbol %s [%s]" ),
1589  GetField( REFERENCE )->GetShownText(),
1590  GetLibId().GetLibItemName().wx_str() );
1591 }
1592 
1593 
1594 SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
1595  const KICAD_T aFilterTypes[] )
1596 {
1597  KICAD_T stype;
1598 
1599  for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p )
1600  {
1601  if( stype == SCH_LOCATE_ANY_T
1602  || ( stype == SCH_COMPONENT_T )
1603  || ( stype == SCH_COMPONENT_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
1604  {
1605  if( SEARCH_RESULT::QUIT == aInspector( this, aTestData ) )
1606  return SEARCH_RESULT::QUIT;
1607  }
1608 
1609  if( stype == SCH_LOCATE_ANY_T || stype == SCH_FIELD_T )
1610  {
1611  for( SCH_FIELD& field : m_Fields )
1612  {
1613  if( SEARCH_RESULT::QUIT == aInspector( &field, (void*) this ) )
1614  return SEARCH_RESULT::QUIT;
1615  }
1616  }
1617 
1618  if( stype == SCH_FIELD_LOCATE_REFERENCE_T )
1619  {
1620  if( SEARCH_RESULT::QUIT == aInspector( GetField( REFERENCE ), (void*) this ) )
1621  return SEARCH_RESULT::QUIT;
1622  }
1623 
1624  if( stype == SCH_FIELD_LOCATE_VALUE_T
1625  || ( stype == SCH_COMPONENT_LOCATE_POWER_T && m_part && m_part->IsPower() ) )
1626  {
1627  if( SEARCH_RESULT::QUIT == aInspector( GetField( VALUE ), (void*) this ) )
1628  return SEARCH_RESULT::QUIT;
1629  }
1630 
1631  if( stype == SCH_FIELD_LOCATE_FOOTPRINT_T )
1632  {
1633  if( SEARCH_RESULT::QUIT == aInspector( GetField( FOOTPRINT ), (void*) this ) )
1634  return SEARCH_RESULT::QUIT;
1635  }
1636 
1637  if( stype == SCH_FIELD_LOCATE_DATASHEET_T )
1638  {
1639  if( SEARCH_RESULT::QUIT == aInspector( GetField( DATASHEET ), (void*) this ) )
1640  return SEARCH_RESULT::QUIT;
1641  }
1642 
1643  if( stype == SCH_LOCATE_ANY_T || stype == SCH_PIN_T )
1644  {
1645  for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
1646  {
1647  // Collect only pins attached to the current unit and convert.
1648  // others are not associated to this component instance
1649  int pin_unit = pin->GetLibPin()->GetUnit();
1650  int pin_convert = pin->GetLibPin()->GetConvert();
1651 
1652  if( pin_unit > 0 && pin_unit != GetUnit() )
1653  continue;
1654 
1655  if( pin_convert > 0 && pin_convert != GetConvert() )
1656  continue;
1657 
1658  if( SEARCH_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
1659  return SEARCH_RESULT::QUIT;
1660  }
1661  }
1662  }
1663 
1664  return SEARCH_RESULT::CONTINUE;
1665 }
1666 
1667 
1668 bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
1669 {
1670  if( Type() != aItem.Type() )
1671  return Type() < aItem.Type();
1672 
1673  auto component = static_cast<const SCH_COMPONENT*>( &aItem );
1674 
1675  EDA_RECT rect = GetBodyBoundingBox();
1676 
1677  if( rect.GetArea() != component->GetBodyBoundingBox().GetArea() )
1678  return rect.GetArea() < component->GetBodyBoundingBox().GetArea();
1679 
1680  if( m_Pos.x != component->m_Pos.x )
1681  return m_Pos.x < component->m_Pos.x;
1682 
1683  if( m_Pos.y != component->m_Pos.y )
1684  return m_Pos.y < component->m_Pos.y;
1685 
1686  return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort
1687 }
1688 
1689 
1690 bool SCH_COMPONENT::operator==( const SCH_COMPONENT& aComponent ) const
1691 {
1692  if( GetFieldCount() != aComponent.GetFieldCount() )
1693  return false;
1694 
1695  for( int i = VALUE; i < GetFieldCount(); i++ )
1696  {
1697  if( GetField( i )->GetText().Cmp( aComponent.GetField( i )->GetText() ) != 0 )
1698  return false;
1699  }
1700 
1701  return true;
1702 }
1703 
1704 
1705 bool SCH_COMPONENT::operator!=( const SCH_COMPONENT& aComponent ) const
1706 {
1707  return !( *this == aComponent );
1708 }
1709 
1710 
1712 {
1713  wxCHECK_MSG( Type() == aItem.Type(), *this,
1714  wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
1715  GetClass() );
1716 
1717  if( &aItem != this )
1718  {
1719  SCH_ITEM::operator=( aItem );
1720 
1721  SCH_COMPONENT* c = (SCH_COMPONENT*) &aItem;
1722 
1723  m_lib_id = c->m_lib_id;
1724 
1725  LIB_PART* libSymbol = c->m_part ? new LIB_PART( *c->m_part.get() ) : nullptr;
1726 
1727  m_part.reset( libSymbol );
1728  m_Pos = c->m_Pos;
1729  m_unit = c->m_unit;
1730  m_convert = c->m_convert;
1731  m_transform = c->m_transform;
1732 
1734 
1735  m_Fields = c->m_Fields; // std::vector's assignment operator
1736 
1737  // Reparent fields after assignment to new component.
1738  for( SCH_FIELD& field : m_Fields )
1739  field.SetParent( this );
1740 
1741  UpdatePins();
1742  }
1743 
1744  return *this;
1745 }
1746 
1747 
1748 bool SCH_COMPONENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
1749 {
1750  EDA_RECT bBox = GetBodyBoundingBox();
1751  bBox.Inflate( aAccuracy );
1752 
1753  if( bBox.Contains( aPosition ) )
1754  return true;
1755 
1756  return false;
1757 }
1758 
1759 
1760 bool SCH_COMPONENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
1761 {
1763  return false;
1764 
1765  EDA_RECT rect = aRect;
1766 
1767  rect.Inflate( aAccuracy );
1768 
1769  if( aContained )
1770  return rect.Contains( GetBodyBoundingBox() );
1771 
1772  return rect.Intersects( GetBodyBoundingBox() );
1773 }
1774 
1775 
1776 bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
1777 {
1778  wxPoint new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_Pos );
1779 
1780  for( const auto& pin : m_pins )
1781  {
1782  // Collect only pins attached to the current unit and convert.
1783  // others are not associated to this component instance
1784  int pin_unit = pin->GetLibPin()->GetUnit();
1785  int pin_convert = pin->GetLibPin()->GetConvert();
1786 
1787  if( pin_unit > 0 && pin_unit != GetUnit() )
1788  continue;
1789 
1790  if( pin_convert > 0 && pin_convert != GetConvert() )
1791  continue;
1792 
1793  if( pin->GetLocalPosition() == new_pos )
1794  return true;
1795  }
1796 
1797  return false;
1798 }
1799 
1800 
1802 {
1803  return m_isInNetlist;
1804 }
1805 
1806 
1807 void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
1808 {
1809  if( m_part )
1810  {
1811  TRANSFORM temp = GetTransform();
1812  aPlotter->StartBlock( nullptr );
1813 
1814  m_part->Plot( aPlotter, GetUnit(), GetConvert(), m_Pos, temp );
1815 
1816  for( SCH_FIELD field : m_Fields )
1817  field.Plot( aPlotter );
1818 
1819  aPlotter->EndBlock( nullptr );
1820  }
1821 }
1822 
1823 
1825 {
1826  for( const auto& pin : m_pins )
1827  {
1828  if( pin->IsBrightened() )
1829  return true;
1830  }
1831 
1832  return false;
1833 }
1834 
1835 
1837 {
1838  for( auto& pin : m_pins )
1839  pin->ClearBrightened();
1840 }
1841 
1842 
bool operator!=(const SCH_COMPONENT &aComponent) const
void UpdateFields(bool aResetStyle, bool aResetRef=false)
Restores fields to the original library values.
EDA_UNITS
Definition: common.h:198
bool ReplaceInstanceSheetPath(const KIID_PATH &aOldSheetPath, const KIID_PATH &aNewSheetPath)
Replace aOldSheetPath with aNewSheetPath in the instance list.
void Offset(int dx, int dy)
Definition: eda_rect.h:157
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
SCH_LAYER_ID m_Layer
Definition: sch_item.h:199
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
void SetModified()
Definition: base_struct.cpp:87
void Rotate(wxPoint aPosition) override
Rotate the item around aPosition 90 degrees in the clockwise direction.
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:174
void SetLibSymbol(LIB_PART *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
void SetLibId(const LIB_ID &aName)
void Plot(PLOTTER *aPlotter) override
Plot the schematic item to aPlotter.
name of datasheet
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
void SetTransform(const TRANSFORM &aTransform)
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:486
PNG memory record (file in memory).
Definition: bitmap_def.h:29
void UpdateUnit(int aUnit)
Change the unit number to aUnit without setting any internal flags.
int GetOrientation()
Get the display symbol orientation.
int y2
Definition: transform.h:51
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
Holds all the data relating to one schematic A schematic may consist of one or more sheets (and one r...
Definition: schematic.h:42
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData) override
Function Matches compares the item against the search criteria in aSearchData.
bool operator==(const SCH_COMPONENT &aComponent) const
Define a symbol library graphical text item.
Definition: lib_text.h:40
int GetX() const
Definition: eda_rect.h:111
SCH_FIELDS m_Fields
Variable length list of fields.
void ImportValues(const LIB_FIELD &aSource)
Function ImportValues copy parameters from a LIB_FIELD source.
Definition: sch_field.cpp:233
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:128
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Field object used in symbol libraries.
Definition: lib_field.h:59
wxString GetSchSymbolLibraryName() const
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:59
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:247
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:116
bool m_onBoard
True to include in netlist when updating board.
int GetUnitCount() const
Return the number of units per package of the symbol.
double square(double x)
int x2
Definition: transform.h:50
void MirrorX(int aXaxis_position) override
Mirror item relative to the X axis about aXaxis_position.
bool IsInNetlist() const
Definition: color4d.h:61
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:477
void ClearBrightenedPins()
std::vector< COMPONENT_INSTANCE_REFERENCE > m_instanceReferences
SCH_PIN * GetPin(const wxString &number)
Find a symbol pin by number.
wxString AsString() const
Definition: common.cpp:165
const BITMAP_OPAQUE add_component_xpm[1]
const wxString GetValue(const SCH_SHEET_PATH *sheet) const
int x1
Definition: transform.h:48
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
wxString GetDescription() const
Return information about the aliased parts.
Schematic editor (Eeschema) main window.
LIB_ITEM * GetDrawItem(const wxPoint &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the component library item at aPosition that is part of this component.
void SwapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:238
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
The base class for create windows for drawing purpose.
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
bool Contains(const wxPoint &aPoint) const
Function Contains.
FIELDS_AUTOPLACED m_fieldsAutoplaced
Definition: sch_item.h:201
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:102
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
virtual void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:196
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:42
The base class for drawable items used by schematic library components.
Definition: lib_item.h:61
int GetBottom() const
Definition: eda_rect.h:124
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
void SetConvert(int aConvert)
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:105
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:100
int y1
Definition: transform.h:49
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:175
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:458
int GetUnit() const
Definition: lib_item.h:295
int GetUnit() const
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:121
wxString m_schLibSymbolName
The name used to look up a symbol in the symbol library embedded in a schematic.
#define NULL
const wxString GetFootprint(const SCH_SHEET_PATH *sheet) const
bool m_isInNetlist
True if the component should appear in the netlist.
void SetHeight(int val)
Definition: eda_rect.h:186
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:237
TRANSFORM & GetTransform() const
A simple container for schematic symbol instance infromation.
EDA_RECT GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the fields.
std::vector< SCH_FIELD > & GetFields()
Returns a vector of fields from the component.
bool operator<(const SCH_ITEM &aItem) const override
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
SCH_COMPONENT(const wxPoint &pos=wxPoint(0, 0), SCH_ITEM *aParent=NULL)
int GetRight() const
Definition: eda_rect.h:121
std::string toUTFTildaText(const wxString &txt)
Convert a wxString to UTF8 and replace any control characters with a ~, where a control character is ...
Define a library symbol object.
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:126
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
wxString GetDatasheet() const
Return the documentation text for the given part alias.
void SetX(int val)
Definition: eda_rect.h:168
wxLogTrace helper definitions.
bool IsAnnotated(const SCH_SHEET_PATH *aSheet)
Checks if the component has a valid annotation (reference) for the given sheet path.
void SetUnit(int aUnit)
Change the unit number to aUnit.
SCH_SHEET_PATH.
std::unique_ptr< LIB_PART > m_part
double GetArea() const
Function GetArea returns the area of the rectangle.
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
void SetWidth(int val)
Definition: eda_rect.h:180
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this symbol.
Definition: color4d.h:59
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
int GetFieldCount() const
Return the number of fields in this symbol.
UTF8 Format() const
Definition: lib_id.cpp:237
void SetY(int val)
Definition: eda_rect.h:174
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieves a list of the SCH_PINs for the given sheet path.
const KIID m_Uuid
Definition: base_struct.h:162
wxPoint GetPosition() const override
Definition: lib_pin.h:258
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
void Normalize()
Function Normalize ensures that the height ant width are positive.
int m_unit
The unit for multiple part per package components.
Definition: sch_component.h:85
Field Value of part, i.e. "3.3K".
void Init(const wxPoint &pos=wxPoint(0, 0))
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
Base plotter engine class.
Definition: plotter.h:114
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
void Print(RENDER_SETTINGS *aSettings, const wxPoint &aOffset) override
Print a component.
wxString GetFieldText(const wxString &aFieldName, SCH_EDIT_FRAME *aFrame) const
Search for a field named aFieldName and returns text associated with this field.
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
LIB_ID m_lib_id
Name and library the symbol was loaded from, i.e. 74xx:74LS00.
Definition: sch_component.h:84
const wxChar *const traceFindItem
Flag to enable find debug tracing.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
#define _(s)
Definition: 3d_actions.cpp:33
void MirrorY(int aYaxis_position) override
Mirror item relative to the Y axis about aYaxis_position.
bool HasBrightenedPins()
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:218
STATUS_FLAGS m_Flags
Definition: base_struct.h:176
wxString AsString() const
Definition: common.h:137
wxString wx_str() const
Definition: utf8.cpp:51
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Schematic symbol object.
Definition: sch_component.h:80
int GetY() const
Definition: eda_rect.h:112
bool GetIncludeOnBoard() const
void RemoveField(const wxString &aFieldName)
Removes a user field from the symbol.
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
bool m_inBom
True to include in bill of materials export.
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList, const SCH_SHEET_PATH *aPath=nullptr) override
Test if the component's dangling state has changed for all pins.
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
virtual wxString GetClass() const override
Function GetClass returns the class name.
Definition: sch_item.h:221
const wxPoint & GetTextPos() const
Definition: eda_text.h:248
SCH_SHEET_PATH & GetCurrentSheet() const
T Convert(const wxString &aValue)
Function Convert converts a wxString to a generic type T.
Definition: eagle_parser.h:175
std::vector< std::pair< int, wxString > > Fields
Definition: sch_screen.h:86
int GetConvert() const
void Print(RENDER_SETTINGS *aSettings, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Print part.
int m_convert
The alternate body style for components that have more than one body style defined.
Definition: sch_component.h:86
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition: sch_item.h:85
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.
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
std::vector< wxPoint > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
std::vector< std::unique_ptr< SCH_PIN > > m_pins
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
SEARCH_RESULT
Definition: base_struct.h:51
void GetLibPins(std::vector< LIB_PIN * > &aPinsList)
Populate a vector with all the pins from the library object.
static bool IsReferenceStringValid(const wxString &aReferenceString)
Tests for an acceptable reference string.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
wxString GetClass() const override
Function GetClass returns the class name.
bool GetIncludeInBom() const
Message panel definition file.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath)
Clear exiting component annotation.
wxString m_prefix
C, R, U, Q etc - the first character which typically indicates what the component is.
Definition: sch_component.h:89
const LIB_ID & GetLibId() const
SCH_COMPONENT & operator=(const SCH_ITEM &aItem)
const EDA_RECT GetBodyBoundingBox(int aUnit, int aConvert) const
Get the symbol bounding box excluding fields.
wxPoint GetPinPhysicalPosition(const LIB_PIN *Pin) const
TRANSFORM m_transform
The rotation/mirror transformation matrix.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:194
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:127
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
bool doIsConnected(const wxPoint &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
std::unordered_map< LIB_PIN *, unsigned > m_pinMap
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
bool empty() const
Definition: utf8.h:108
SCH_SHEET_PATH & CurrentSheet() const
Definition: schematic.h:119
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...