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