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