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-2018 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 
30 #include <fctsys.h>
31 #include <pgm_base.h>
32 #include <class_drawpanel.h>
33 #include <gr_basic.h>
34 #include <kicad_string.h>
35 #include <richio.h>
36 #include <sch_edit_frame.h>
37 #include <plotter.h>
38 #include <msgpanel.h>
39 #include <bitmaps.h>
40 
41 #include <general.h>
42 #include <class_library.h>
43 #include <lib_rectangle.h>
44 #include <lib_pin.h>
45 #include <lib_text.h>
46 #include <sch_component.h>
47 #include <sch_sheet.h>
48 #include <sch_sheet_path.h>
49 #include <netlist_object.h>
50 #include <lib_draw_item.h>
51 #include <symbol_lib_table.h>
52 
54 
55 #include <wx/tokenzr.h>
56 #include <iostream>
57 #include <cctype>
58 
59 #include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition
60 
61 #include <trace_helpers.h>
62 
63 #define NULL_STRING "_NONAME_"
64 
70 std::string toUTFTildaText( const wxString& txt )
71 {
72  std::string ret = TO_UTF8( txt );
73 
74  for( std::string::iterator it = ret.begin(); it!=ret.end(); ++it )
75  {
76  if( (unsigned char) *it <= ' ' )
77  *it = '~';
78  }
79  return ret;
80 }
81 
82 
96 static LIB_PART* dummy()
97 {
98  static LIB_PART* part;
99 
100  if( !part )
101  {
102  part = new LIB_PART( wxEmptyString );
103 
104  LIB_RECTANGLE* square = new LIB_RECTANGLE( part );
105 
106  square->Move( wxPoint( -200, 200 ) );
107  square->SetEndPosition( wxPoint( 200, -200 ) );
108 
109  LIB_TEXT* text = new LIB_TEXT( part );
110 
111  text->SetTextSize( wxSize( 150, 150 ) );
112  text->SetText( wxString( wxT( "??" ) ) );
113 
114  part->AddDrawItem( square );
115  part->AddDrawItem( text );
116  }
117 
118  return part;
119 }
120 
121 
123  SCH_ITEM( aParent, SCH_COMPONENT_T )
124 {
125  Init( aPos );
126  m_currentSheetPath = NULL;
128 }
129 
130 
132  int convert, const wxPoint& pos, bool setNewItemFlag ) :
133  SCH_ITEM( NULL, SCH_COMPONENT_T )
134 {
135  Init( pos );
136 
137  m_unit = unit;
138  m_convert = convert;
139  m_lib_id.SetLibItemName( aPart.GetName(), false );
140  m_part = aPart.SharedPtr();
141  m_currentSheetPath = NULL;
143 
145 
146  if( setNewItemFlag )
147  m_Flags = IS_NEW | IS_MOVED;
148 
149  // Import user defined fields from the library component
150  UpdateFields( true, true );
151 
152  // Update the pin locations
153  UpdatePinCache();
154 
155  wxString msg = aPart.GetReferenceField().GetText();
156 
157  if( msg.IsEmpty() )
158  msg = wxT( "U" );
159 
160  m_prefix = msg;
161 
162  // update the reference -- just the prefix for now.
163  msg += wxT( "?" );
164  SetRef( sheet, msg );
165 
166  // Use the schematic component name instead of the library value field name.
167  GetField( VALUE )->SetText( GetLibId().GetLibItemName() );
168 }
169 
170 
172  SCH_ITEM( aComponent )
173 {
174  m_currentSheetPath = NULL;
175  m_Parent = aComponent.m_Parent;
176  m_Pos = aComponent.m_Pos;
177  m_unit = aComponent.m_unit;
178  m_convert = aComponent.m_convert;
179  m_lib_id = aComponent.m_lib_id;
180  m_part = aComponent.m_part;
181  m_Pins = aComponent.m_Pins;
182 
183  SetTimeStamp( aComponent.m_TimeStamp );
184 
185  m_transform = aComponent.m_transform;
186  m_prefix = aComponent.m_prefix;
188  m_Fields = aComponent.m_Fields;
189 
190  // Re-parent the fields, which before this had aComponent as parent
191  for( int i = 0; i<GetFieldCount(); ++i )
192  {
193  GetField( i )->SetParent( this );
194  }
195 
196  m_isDangling = aComponent.m_isDangling;
198 }
199 
200 
201 void SCH_COMPONENT::Init( const wxPoint& pos )
202 {
203  m_Pos = pos;
204  m_unit = 0; // In multi unit chip - which unit to draw.
205  m_convert = 0; // De Morgan Handling
206 
207  // The rotation/mirror transformation matrix. pos normal
209 
210  // construct only the mandatory fields, which are the first 4 only.
211  for( int i = 0; i < MANDATORY_FIELDS; ++i )
212  {
213  SCH_FIELD field( pos, i, this, TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
214 
215  if( i == REFERENCE )
216  field.SetLayer( LAYER_REFERENCEPART );
217  else if( i == VALUE )
218  field.SetLayer( LAYER_VALUEPART );
219 
220  // else keep LAYER_FIELDS from SCH_FIELD constructor
221 
222  // SCH_FIELD's implicitly created copy constructor is called in here
223  AddField( field );
224  }
225 
226  m_prefix = wxString( wxT( "U" ) );
227 }
228 
229 
231 {
232  return new SCH_COMPONENT( *this );
233 }
234 
235 
236 void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, PART_LIBS* aLibs )
237 {
238  if( m_lib_id != aLibId )
239  {
240  m_lib_id = aLibId;
241  SetModified();
242 
243  if( aLibs )
244  Resolve( aLibs );
245  else
246  m_part.reset();
247  }
248 }
249 
250 
251 void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aSymLibTable,
252  PART_LIB* aCacheLib )
253 {
254  if( m_lib_id == aLibId )
255  return;
256 
257  m_lib_id = aLibId;
258  SetModified();
259 
260  LIB_ALIAS* alias = nullptr;
261 
262  if( aSymLibTable && aSymLibTable->HasLibrary( m_lib_id.GetLibNickname() ) )
263  alias = aSymLibTable->LoadSymbol( m_lib_id.GetLibNickname(), m_lib_id.GetLibItemName() );
264 
265  if( !alias && aCacheLib )
266  alias = aCacheLib->FindAlias( m_lib_id.Format().wx_str() );
267 
268  if( alias && alias->GetPart() )
269  m_part = alias->GetPart()->SharedPtr();
270  else
271  m_part.reset();
272 }
273 
274 
276 {
277  if( PART_SPTR part = m_part.lock() )
278  {
279  LIB_ALIAS* alias = part->GetAlias( GetLibId().GetLibItemName() );
280 
281  if( !alias )
282  return wxEmptyString;
283 
284  return alias->GetDescription();
285  }
286 
287  return wxEmptyString;
288 }
289 
290 
292 {
293  if( PART_SPTR part = m_part.lock() )
294  {
295  LIB_ALIAS* alias = part->GetAlias( GetLibId().GetLibItemName() );
296 
297  if( !alias )
298  return wxEmptyString;
299 
300  return alias->GetDocFileName();
301  }
302 
303  return wxEmptyString;
304 }
305 
306 
308 {
309  // I've never been happy that the actual individual PART_LIB is left up to
310  // flimsy search path ordering. None-the-less find a part based on that design:
311  if( LIB_PART* part = aLibs->FindLibPart( m_lib_id ) )
312  {
313  m_part = part->SharedPtr();
314  return true;
315  }
316 
317  return false;
318 }
319 
320 
321 bool SCH_COMPONENT::Resolve( SYMBOL_LIB_TABLE& aLibTable, PART_LIB* aCacheLib )
322 {
323  LIB_ALIAS* alias = nullptr;
324 
325  try
326  {
327  // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the the library nickname
328  // is not found in the table so check if the library still exists in the table
329  // before attempting to load the symbol.
330  if( m_lib_id.IsValid() && aLibTable.HasLibrary( m_lib_id.GetLibNickname() ) )
331  alias = aLibTable.LoadSymbol( m_lib_id );
332 
333  // Fall back to cache library. This is temporary until the new schematic file
334  // format is implemented.
335  if( !alias && aCacheLib )
336  alias = aCacheLib->FindAlias( m_lib_id.Format().wx_str() );
337 
338  if( alias && alias->GetPart() )
339  {
340  m_part = alias->GetPart()->SharedPtr();
341  return true;
342  }
343  }
344  catch( const IO_ERROR& )
345  {
346  wxLogDebug( "Cannot resolve library symbol %s", m_lib_id.Format().wx_str() );
347  }
348 
349  return false;
350 }
351 
352 
353 // Helper sort function, used in SCH_COMPONENT::ResolveAll, to sort
354 // sch component by lib_id
355 static bool sort_by_libid( const SCH_COMPONENT* ref, SCH_COMPONENT* cmp )
356 {
357  if( ref->GetLibId() == cmp->GetLibId() )
358  {
359  if( ref->GetUnit() == cmp->GetUnit() )
360  return ref->GetConvert() < cmp->GetConvert();
361 
362  return ref->GetUnit() < cmp->GetUnit();
363  }
364 
365  return ref->GetLibId() < cmp->GetLibId();
366 }
367 
368 
369 void SCH_COMPONENT::ResolveAll( const SCH_COLLECTOR& aComponents, PART_LIBS* aLibs )
370 {
371  // Usually, many components use the same part lib.
372  // to avoid too long calculation time the list of components is grouped
373  // and once the lib part is found for one member of a group, it is also
374  // set for all other members of this group
375  std::vector<SCH_COMPONENT*> cmp_list;
376 
377  // build the cmp list.
378  for( int i = 0; i < aComponents.GetCount(); ++i )
379  {
380  SCH_COMPONENT* cmp = dynamic_cast<SCH_COMPONENT*>( aComponents[i] );
381  wxASSERT( cmp );
382 
383  if( cmp ) // cmp == NULL should not occur.
384  cmp_list.push_back( cmp );
385  }
386 
387  // sort it by lib part. Cmp will be grouped by same lib part.
388  std::sort( cmp_list.begin(), cmp_list.end(), sort_by_libid );
389 
390  LIB_ID curr_libid;
391 
392  for( unsigned ii = 0; ii < cmp_list.size (); ++ii )
393  {
394  SCH_COMPONENT* cmp = cmp_list[ii];
395  curr_libid = cmp->m_lib_id;
396  cmp->Resolve( aLibs );
397  cmp->UpdatePinCache();
398 
399  // Propagate the m_part pointer to other members using the same lib_id
400  for( unsigned jj = ii+1; jj < cmp_list.size (); ++jj )
401  {
402  SCH_COMPONENT* next_cmp = cmp_list[jj];
403 
404  if( curr_libid != next_cmp->m_lib_id )
405  break;
406 
407  next_cmp->m_part = cmp->m_part;
408 
409  if( ( cmp->m_unit == next_cmp->m_unit ) && ( cmp->m_convert == next_cmp->m_convert ) )
410  // Propagate the pin cache vector as well
411  next_cmp->m_Pins = cmp->m_Pins;
412  else
413  next_cmp->UpdatePinCache();
414 
415  ii = jj;
416  }
417  }
418 }
419 
420 
421 void SCH_COMPONENT::ResolveAll( const SCH_COLLECTOR& aComponents, SYMBOL_LIB_TABLE& aLibTable,
422  PART_LIB* aCacheLib )
423 {
424  std::vector<SCH_COMPONENT*> cmp_list;
425 
426  for( int i = 0; i < aComponents.GetCount(); ++i )
427  {
428  SCH_COMPONENT* cmp = dynamic_cast<SCH_COMPONENT*>( aComponents[i] );
429 
430  wxCHECK2_MSG( cmp, continue, "Invalid SCH_COMPONENT pointer in list." );
431 
432  cmp_list.push_back( cmp );
433  }
434 
435  // sort it by lib part. Cmp will be grouped by same lib part.
436  std::sort( cmp_list.begin(), cmp_list.end(), sort_by_libid );
437 
438  LIB_ID curr_libid;
439 
440  for( unsigned ii = 0; ii < cmp_list.size (); ++ii )
441  {
442  SCH_COMPONENT* cmp = cmp_list[ii];
443  curr_libid = cmp->m_lib_id;
444  cmp->Resolve( aLibTable, aCacheLib );
445  cmp->UpdatePinCache();
446 
447  // Propagate the m_part pointer to other members using the same lib_id
448  for( unsigned jj = ii+1; jj < cmp_list.size (); ++jj )
449  {
450  SCH_COMPONENT* next_cmp = cmp_list[jj];
451 
452  if( curr_libid != next_cmp->m_lib_id )
453  break;
454 
455  next_cmp->m_part = cmp->m_part;
456 
457  if( ( cmp->m_unit == next_cmp->m_unit ) && ( cmp->m_convert == next_cmp->m_convert ) )
458  // Propagate the pin cache vector as well
459  next_cmp->m_Pins = cmp->m_Pins;
460  else
461  next_cmp->UpdatePinCache();
462 
463  ii = jj;
464  }
465  }
466 }
467 
468 
470 {
471  if( PART_SPTR part = m_part.lock() )
472  {
473  m_Pins.clear();
474  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
475  {
476  wxASSERT( pin->Type() == LIB_PIN_T );
477 
478  if( pin->GetUnit() && m_unit && ( m_unit != pin->GetUnit() ) )
479  continue;
480 
481  if( pin->GetConvert() && m_convert && ( m_convert != pin->GetConvert() ) )
482  continue;
483 
484  m_Pins.push_back( pin->GetPosition() );
485  }
486  }
487 }
488 
489 
491 {
492  // Usually, many components use the same part lib.
493  // to avoid too long calculation time the list of components is grouped
494  // and once the lib part is found for one member of a group, it is also
495  // set for all other members of this group
496  std::vector<SCH_COMPONENT*> cmp_list;
497 
498  // build the cmp list.
499  for( int i = 0; i < aComponents.GetCount(); ++i )
500  {
501  SCH_COMPONENT* cmp = dynamic_cast<SCH_COMPONENT*>( aComponents[i] );
502  wxASSERT( cmp );
503 
504  if( cmp ) // cmp == NULL should not occur.
505  cmp_list.push_back( cmp );
506  }
507 
508  // sort it by lib part. Cmp will be grouped by same lib part.
509  std::sort( cmp_list.begin(), cmp_list.end(), sort_by_libid );
510 
511  LIB_ID curr_libid;
512 
513  for( unsigned ii = 0; ii < cmp_list.size (); ++ii )
514  {
515  SCH_COMPONENT* cmp = cmp_list[ii];
516  curr_libid = cmp->m_lib_id;
517  cmp->UpdatePinCache();
518 
519  // Propagate the m_Pins vector to other members using the same lib_id
520  for( unsigned jj = ii+1; jj < cmp_list.size (); ++jj )
521  {
522  SCH_COMPONENT* next_cmp = cmp_list[jj];
523 
524  if( ( curr_libid != next_cmp->m_lib_id )
525  || ( cmp->m_unit != next_cmp->m_unit )
526  || ( cmp->m_convert != next_cmp->m_convert ) )
527  break;
528 
529  // Propagate the pin cache vector as well
530  next_cmp->m_Pins = cmp->m_Pins;
531  ii = jj;
532  }
533  }
534 }
535 
536 
537 void SCH_COMPONENT::SetUnit( int aUnit )
538 {
539  if( m_unit != aUnit )
540  {
541  m_unit = aUnit;
542  SetModified();
543  }
544 }
545 
546 
547 void SCH_COMPONENT::UpdateUnit( int aUnit )
548 {
549  m_unit = aUnit;
550 }
551 
552 
553 void SCH_COMPONENT::SetConvert( int aConvert )
554 {
555  if( m_convert != aConvert )
556  {
557  m_convert = aConvert;
558  SetModified();
559  }
560 }
561 
562 
563 void SCH_COMPONENT::SetTransform( const TRANSFORM& aTransform )
564 {
565  if( m_transform != aTransform )
566  {
567  m_transform = aTransform;
568  SetModified();
569  }
570 }
571 
572 
574 {
575  if( PART_SPTR part = m_part.lock() )
576  {
577  return part->GetUnitCount();
578  }
579 
580  return 0;
581 }
582 
583 
584 void SCH_COMPONENT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset,
585  GR_DRAWMODE aDrawMode, COLOR4D aColor,
586  bool aDrawPinText )
587 {
588  auto opts = PART_DRAW_OPTIONS::Default();
589  opts.draw_mode = aDrawMode;
590  opts.color = aColor;
591  opts.transform = m_transform;
592  opts.show_pin_text = aDrawPinText;
593  opts.draw_visible_fields = false;
594  opts.draw_hidden_fields = false;
595 
596  if( PART_SPTR part = m_part.lock() )
597  {
598  // Draw pin targets if part is being dragged
599  bool dragging = aPanel->GetScreen()->GetCurItem() == this && aPanel->IsMouseCaptured();
600 
601  if( !dragging )
602  {
603  opts.dangling = m_isDangling;
604  }
605 
606  part->Draw( aPanel, aDC, m_Pos + aOffset, m_unit, m_convert, opts );
607  }
608  else // Use dummy() part if the actual cannot be found.
609  {
610  dummy()->Draw( aPanel, aDC, m_Pos + aOffset, 0, 0, opts );
611  }
612 
613  SCH_FIELD* field = GetField( REFERENCE );
614 
615  if( field->IsVisible() && !field->IsMoving() )
616  {
617  field->Draw( aPanel, aDC, aOffset, aDrawMode );
618  }
619 
620  for( int ii = VALUE; ii < GetFieldCount(); ii++ )
621  {
622  field = GetField( ii );
623 
624  if( field->IsMoving() )
625  continue;
626 
627  field->Draw( aPanel, aDC, aOffset, aDrawMode );
628  }
629 
630 #if 0
631  // Only for testing purposes, draw the component bounding box
632  {
634  GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN );
635 #if 1
636  if( GetField( REFERENCE )->IsVisible() )
637  {
638  boundingBox = GetField( REFERENCE )->GetBoundingBox();
639  GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN );
640  }
641 
642  if( GetField( VALUE )->IsVisible() )
643  {
644  boundingBox = GetField( VALUE )->GetBoundingBox();
645  GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN );
646  }
647 #endif
648  }
649 #endif
650 }
651 
652 
653 void SCH_COMPONENT::AddHierarchicalReference( const wxString& aPath,
654  const wxString& aRef,
655  int aMulti )
656 {
657  wxString h_path, h_ref;
658  wxStringTokenizer tokenizer;
659  wxString separators( wxT( " " ) );
660 
661  // Search for an existing path and remove it if found (should not occur)
662  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
663  {
664  tokenizer.SetString( m_PathsAndReferences[ii], separators );
665  h_path = tokenizer.GetNextToken();
666 
667  if( h_path.Cmp( aPath ) == 0 )
668  {
669  m_PathsAndReferences.RemoveAt( ii );
670  ii--;
671  }
672  }
673 
674  h_ref = aPath + wxT( " " ) + aRef;
675  h_ref << wxT( " " ) << aMulti;
676  m_PathsAndReferences.Add( h_ref );
677 }
678 
679 
680 wxString SCH_COMPONENT::GetPath( const SCH_SHEET_PATH* sheet ) const
681 {
682  wxCHECK_MSG( sheet != NULL, wxEmptyString,
683  wxT( "Cannot get component path with invalid sheet object." ) );
684 
685  wxString str;
686 
687  str.Printf( wxT( "%8.8lX" ), (long unsigned) m_TimeStamp );
688  return sheet->Path() + str;
689 }
690 
691 
692 const wxString SCH_COMPONENT::GetRef( const SCH_SHEET_PATH* sheet )
693 {
694  wxString path = GetPath( sheet );
695  wxString h_path, h_ref;
696  wxStringTokenizer tokenizer;
697  wxString separators( wxT( " " ) );
698 
699  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
700  {
701  tokenizer.SetString( m_PathsAndReferences[ii], separators );
702  h_path = tokenizer.GetNextToken();
703 
704  if( h_path.Cmp( path ) == 0 )
705  {
706  h_ref = tokenizer.GetNextToken();
707 
708  /* printf( "GetRef hpath: %s\n",
709  * TO_UTF8( m_PathsAndReferences[ii] ) ); */
710  return h_ref;
711  }
712  }
713 
714  // if it was not found in m_Paths array, then see if it is in
715  // m_Field[REFERENCE] -- if so, use this as a default for this path.
716  // this will happen if we load a version 1 schematic file.
717  // it will also mean that multiple instances of the same sheet by default
718  // all have the same component references, but perhaps this is best.
719  if( !GetField( REFERENCE )->GetText().IsEmpty() )
720  {
721  SetRef( sheet, GetField( REFERENCE )->GetText() );
722  return GetField( REFERENCE )->GetText();
723  }
724 
725  return m_prefix;
726 }
727 
728 
729 bool SCH_COMPONENT::IsReferenceStringValid( const wxString& aReferenceString )
730 {
731  wxString text = aReferenceString;
732  bool ok = true;
733 
734  // Try to unannotate this reference
735  while( !text.IsEmpty() && ( text.Last() == '?' || std::isdigit( text.Last().GetValue() ) ) )
736  text.RemoveLast();
737 
738  if( text.IsEmpty() )
739  ok = false;
740 
741  // Add here other constraints
742  // Currently:no other constraint
743 
744  return ok;
745 }
746 
747 
748 void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
749 {
750  wxString path = GetPath( sheet );
751 
752  bool notInArray = true;
753 
754  wxString h_path, h_ref;
755  wxStringTokenizer tokenizer;
756  wxString separators( wxT( " " ) );
757 
758  // check to see if it is already there before inserting it
759  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
760  {
761  tokenizer.SetString( m_PathsAndReferences[ii], separators );
762  h_path = tokenizer.GetNextToken();
763 
764  if( h_path.Cmp( path ) == 0 )
765  {
766  // just update the reference text, not the timestamp.
767  h_ref = h_path + wxT( " " ) + ref;
768  h_ref += wxT( " " );
769  tokenizer.GetNextToken(); // Skip old reference
770  h_ref += tokenizer.GetNextToken(); // Add part selection
771 
772  // Add the part selection
773  m_PathsAndReferences[ii] = h_ref;
774  notInArray = false;
775  }
776  }
777 
778  if( notInArray )
779  AddHierarchicalReference( path, ref, m_unit );
780 
781  SCH_FIELD* rf = GetField( REFERENCE );
782 
783  if( rf->GetText().IsEmpty()
784  || ( abs( rf->GetTextPos().x - m_Pos.x ) +
785  abs( rf->GetTextPos().y - m_Pos.y ) > 10000 ) )
786  {
787  // move it to a reasonable position
788  rf->SetTextPos( m_Pos + wxPoint( 50, 50 ) );
789  }
790 
791  rf->SetText( ref ); // for drawing.
792 
793  // Reinit the m_prefix member if needed
794  wxString prefix = ref;
795 
796  if( IsReferenceStringValid( prefix ) )
797  {
798  while( prefix.Last() == '?' || std::isdigit( prefix.Last().GetValue() ) )
799  prefix.RemoveLast();
800  }
801  else
802  {
803  prefix = wxT( "U" ); // Set to default ref prefix
804  }
805 
806  if( m_prefix != prefix )
807  m_prefix = prefix;
808 }
809 
810 
812 {
813  wxString string_timestamp, string_oldtimestamp;
814 
815  string_timestamp.Printf( wxT( "%08lX" ), (long unsigned) aNewTimeStamp );
816  string_oldtimestamp.Printf( wxT( "%08lX" ), (long unsigned) m_TimeStamp );
817  EDA_ITEM::SetTimeStamp( aNewTimeStamp );
818 
819  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
820  {
821  m_PathsAndReferences[ii].Replace( string_oldtimestamp.GetData(),
822  string_timestamp.GetData() );
823  }
824 }
825 
826 
828 {
829  wxString path = GetPath( aSheet );
830  wxString h_path, h_multi;
831  wxStringTokenizer tokenizer;
832  wxString separators( wxT( " " ) );
833 
834  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
835  {
836  tokenizer.SetString( m_PathsAndReferences[ii], separators );
837  h_path = tokenizer.GetNextToken();
838 
839  if( h_path.Cmp( path ) == 0 )
840  {
841  tokenizer.GetNextToken(); // Skip reference
842  h_multi = tokenizer.GetNextToken();
843  long imulti = 1;
844  h_multi.ToLong( &imulti );
845  return imulti;
846  }
847  }
848 
849  // if it was not found in m_Paths array, then use m_unit.
850  // this will happen if we load a version 1 schematic file.
851  return m_unit;
852 }
853 
854 
855 void SCH_COMPONENT::SetUnitSelection( SCH_SHEET_PATH* aSheet, int aUnitSelection )
856 {
857  wxString path = GetPath( aSheet );
858 
859  bool notInArray = true;
860 
861  wxString h_path, h_ref;
862  wxStringTokenizer tokenizer;
863  wxString separators( wxT( " " ) );
864 
865  //check to see if it is already there before inserting it
866  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
867  {
868  tokenizer.SetString( m_PathsAndReferences[ii], separators );
869  h_path = tokenizer.GetNextToken();
870 
871  if( h_path.Cmp( path ) == 0 )
872  {
873  //just update the unit selection.
874  h_ref = h_path + wxT( " " );
875  h_ref += tokenizer.GetNextToken(); // Add reference
876  h_ref += wxT( " " );
877  h_ref << aUnitSelection; // Add part selection
878 
879  // Ann the part selection
880  m_PathsAndReferences[ii] = h_ref;
881  notInArray = false;
882  }
883  }
884 
885  if( notInArray )
886  AddHierarchicalReference( path, m_prefix, aUnitSelection );
887 }
888 
889 
890 SCH_FIELD* SCH_COMPONENT::GetField( int aFieldNdx ) const
891 {
892  const SCH_FIELD* field;
893 
894  if( (unsigned) aFieldNdx < m_Fields.size() )
895  field = &m_Fields[aFieldNdx];
896  else
897  field = NULL;
898 
899  wxASSERT( field );
900 
901  // use cast to remove const-ness
902  return (SCH_FIELD*) field;
903 }
904 
905 
906 wxString SCH_COMPONENT::GetFieldText( const wxString& aFieldName, SCH_EDIT_FRAME* aFrame ) const
907 {
908  for( unsigned int ii = 0; ii < m_Fields.size(); ii++ )
909  {
910  if( aFieldName == m_Fields[ii].GetName() )
911  return m_Fields[ii].GetText();
912  }
913 
914  return wxEmptyString;
915 }
916 
917 
918 void SCH_COMPONENT::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
919 {
920  for( SCH_FIELD& each_field : m_Fields )
921  {
922  if( !aVisibleOnly || ( each_field.IsVisible() && !each_field.IsVoid() ) )
923  aVector.push_back( &each_field );
924  }
925 }
926 
927 
929 {
930  int newNdx = m_Fields.size();
931 
932  m_Fields.push_back( aField );
933  return &m_Fields[newNdx];
934 }
935 
936 
937 SCH_FIELD* SCH_COMPONENT::FindField( const wxString& aFieldName, bool aIncludeDefaultFields )
938 {
939  unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
940 
941  for( unsigned i = start; i<m_Fields.size(); ++i )
942  {
943  if( aFieldName == m_Fields[i].GetName( false ) )
944  {
945  return &m_Fields[i];
946  }
947  }
948 
949  return NULL;
950 }
951 
952 
953 void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
954 {
955  if( PART_SPTR part = m_part.lock() )
956  {
957  LIB_FIELDS fields;
958  part->GetFields( fields );
959 
960  for( const LIB_FIELD& field : fields )
961  {
962  // Can no longer insert an empty name, since names are now keys. The
963  // field index is not used beyond the first MANDATORY_FIELDS
964  if( field.GetName().IsEmpty() )
965  continue;
966 
967  // See if field already exists (mandatory fields always exist).
968  // for mandatory fields, the name and field id are fixed, so we use the
969  // known and fixed id to get them (more reliable than names, which can be translated)
970  // for other fields (custom fields), locate the field by same name
971  // (field id has no known meaning for custom fields)
972  int idx = field.GetId();
973  SCH_FIELD* schField;
974 
975  if( idx == REFERENCE && !aResetRef )
976  continue;
977  if( (unsigned) idx < MANDATORY_FIELDS )
978  schField = GetField( idx );
979  else
980  schField = FindField( field.GetName() );
981 
982  if( !schField )
983  {
984  SCH_FIELD fld( wxPoint( 0, 0 ), GetFieldCount(), this, field.GetName() );
985  schField = AddField( fld );
986  }
987 
988  if( aResetStyle )
989  {
990  schField->ImportValues( field );
991  schField->SetTextPos( m_Pos + field.GetTextPos() );
992  }
993 
994  schField->SetText( field.GetText() );
995  }
996  }
997 }
998 
999 
1000 LIB_PIN* SCH_COMPONENT::GetPin( const wxString& number )
1001 {
1002  if( PART_SPTR part = m_part.lock() )
1003  {
1004  return part->GetPin( number, m_unit, m_convert );
1005  }
1006  return NULL;
1007 }
1008 
1009 
1010 void SCH_COMPONENT::GetPins( std::vector<LIB_PIN*>& aPinsList )
1011 {
1012  if( m_part.expired() )
1013  {
1014  // no pins; nothing to get
1015  }
1016  else if( PART_SPTR part = m_part.lock() )
1017  {
1018  part->GetPins( aPinsList, m_unit, m_convert );
1019  }
1020  else
1021  wxFAIL_MSG( "Could not obtain PART_SPTR lock" );
1022 }
1023 
1024 
1026 {
1027  wxCHECK_RET( (aItem != NULL) && (aItem->Type() == SCH_COMPONENT_T),
1028  wxT( "Cannot swap data with invalid component." ) );
1029 
1030  SCH_COMPONENT* component = (SCH_COMPONENT*) aItem;
1031 
1032  std::swap( m_lib_id, component->m_lib_id );
1033  std::swap( m_part, component->m_part );
1034  std::swap( m_Pos, component->m_Pos );
1035  std::swap( m_unit, component->m_unit );
1036  std::swap( m_convert, component->m_convert );
1037 
1038  std::swap( m_Pins, component->m_Pins );
1039  std::swap( m_isDangling, component->m_isDangling );
1040 
1041  TRANSFORM tmp = m_transform;
1042 
1043  m_transform = component->m_transform;
1044  component->m_transform = tmp;
1045 
1046  m_Fields.swap( component->m_Fields ); // std::vector's swap()
1047 
1048  // Reparent items after copying data
1049  // (after swap(), m_Parent member does not point to the right parent):
1050  for( int ii = 0; ii < component->GetFieldCount(); ++ii )
1051  {
1052  component->GetField( ii )->SetParent( component );
1053  }
1054 
1055  for( int ii = 0; ii < GetFieldCount(); ++ii )
1056  {
1057  GetField( ii )->SetParent( this );
1058  }
1059 
1060  std::swap( m_PathsAndReferences, component->m_PathsAndReferences );
1061 }
1062 
1063 
1065 {
1066  wxArrayString reference_fields;
1067  static const wxChar separators[] = wxT( " " );
1068  PART_SPTR part = m_part.lock();
1069 
1070  // Build a reference with no annotation,
1071  // i.e. a reference ended by only one '?'
1072  wxString defRef = m_prefix;
1073 
1074  if( !IsReferenceStringValid( defRef ) )
1075  { // This is a malformed reference: reinit this reference
1076  m_prefix = defRef = wxT("U"); // Set to default ref prefix
1077  }
1078 
1079  while( defRef.Last() == '?' )
1080  defRef.RemoveLast();
1081 
1082  defRef.Append( wxT( "?" ) );
1083 
1084  wxString path;
1085 
1086  if( aSheetPath )
1087  path = GetPath( aSheetPath );
1088 
1089  for( unsigned int ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
1090  {
1091  // Break hierarchical reference in path, ref and multi selection:
1092  reference_fields = wxStringTokenize( m_PathsAndReferences[ii], separators );
1093 
1094  // For all components: if aSheetPath is not NULL,
1095  // remove annotation only for the given path
1096  if( aSheetPath == NULL || reference_fields[0].Cmp( path ) == 0 )
1097  {
1098  wxString NewHref = reference_fields[0];
1099  NewHref << wxT( " " ) << defRef << wxT( " " ) << reference_fields[2];
1100  m_PathsAndReferences[ii] = NewHref;
1101  }
1102  }
1103 
1104  // These 2 changes do not work in complex hierarchy.
1105  // When a clear annotation is made, the calling function must call a
1106  // UpdateAllScreenReferences for the active sheet.
1107  // But this call cannot made here.
1108  m_Fields[REFERENCE].SetText( defRef ); //for drawing.
1109 
1110  SetModified();
1111 }
1112 
1113 
1114 void SCH_COMPONENT::SetOrientation( int aOrientation )
1115 {
1116  TRANSFORM temp = TRANSFORM();
1117  bool transform = false;
1118 
1119  switch( aOrientation )
1120  {
1121  case CMP_ORIENT_0:
1122  case CMP_NORMAL: // default transform matrix
1123  m_transform.x1 = 1;
1124  m_transform.y2 = -1;
1125  m_transform.x2 = m_transform.y1 = 0;
1126  break;
1127 
1128  case CMP_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
1129  temp.x1 = temp.y2 = 0;
1130  temp.y1 = 1;
1131  temp.x2 = -1;
1132  transform = true;
1133  break;
1134 
1135  case CMP_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1136  temp.x1 = temp.y2 = 0;
1137  temp.y1 = -1;
1138  temp.x2 = 1;
1139  transform = true;
1140  break;
1141 
1142  case CMP_MIRROR_Y: // Mirror Y (incremental rotation)
1143  temp.x1 = -1;
1144  temp.y2 = 1;
1145  temp.y1 = temp.x2 = 0;
1146  transform = true;
1147  break;
1148 
1149  case CMP_MIRROR_X: // Mirror X (incremental rotation)
1150  temp.x1 = 1;
1151  temp.y2 = -1;
1152  temp.y1 = temp.x2 = 0;
1153  transform = true;
1154  break;
1155 
1156  case CMP_ORIENT_90:
1159  break;
1160 
1161  case CMP_ORIENT_180:
1165  break;
1166 
1167  case CMP_ORIENT_270:
1170  break;
1171 
1172  case ( CMP_ORIENT_0 + CMP_MIRROR_X ):
1175  break;
1176 
1177  case ( CMP_ORIENT_0 + CMP_MIRROR_Y ):
1180  break;
1181 
1182  case ( CMP_ORIENT_90 + CMP_MIRROR_X ):
1185  break;
1186 
1187  case ( CMP_ORIENT_90 + CMP_MIRROR_Y ):
1190  break;
1191 
1192  case ( CMP_ORIENT_180 + CMP_MIRROR_X ):
1195  break;
1196 
1197  case ( CMP_ORIENT_180 + CMP_MIRROR_Y ):
1200  break;
1201 
1202  case ( CMP_ORIENT_270 + CMP_MIRROR_X ):
1205  break;
1206 
1207  case ( CMP_ORIENT_270 + CMP_MIRROR_Y ):
1210  break;
1211 
1212  default:
1213  transform = false;
1214  wxMessageBox( wxT( "SetRotateMiroir() error: ill value" ) );
1215  break;
1216  }
1217 
1218  if( transform )
1219  {
1220  /* The new matrix transform is the old matrix transform modified by the
1221  * requested transformation, which is the temp transform (rot,
1222  * mirror ..) in order to have (in term of matrix transform):
1223  * transform coord = new_m_transform * coord
1224  * where transform coord is the coord modified by new_m_transform from
1225  * the initial value coord.
1226  * new_m_transform is computed (from old_m_transform and temp) to
1227  * have:
1228  * transform coord = old_m_transform * temp
1229  */
1230  TRANSFORM newTransform;
1231 
1232  newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1233  newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1234  newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1235  newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1236  m_transform = newTransform;
1237  }
1238 }
1239 
1240 
1242 {
1243  int type_rotate = CMP_ORIENT_0;
1244  TRANSFORM transform;
1245  int ii;
1246 
1247  #define ROTATE_VALUES_COUNT 12
1248 
1249  // list of all possibilities, but only the first 8 are actually used
1250  int rotate_value[ROTATE_VALUES_COUNT] =
1251  {
1256  CMP_MIRROR_Y + CMP_ORIENT_0, CMP_MIRROR_Y + CMP_ORIENT_90,
1257  CMP_MIRROR_Y + CMP_ORIENT_180, CMP_MIRROR_Y + CMP_ORIENT_270
1258  };
1259 
1260  // Try to find the current transform option:
1261  transform = m_transform;
1262 
1263  for( ii = 0; ii < ROTATE_VALUES_COUNT; ii++ )
1264  {
1265  type_rotate = rotate_value[ii];
1266  SetOrientation( type_rotate );
1267 
1268  if( transform == m_transform )
1269  return type_rotate;
1270  }
1271 
1272  // Error: orientation not found in list (should not happen)
1273  wxMessageBox( wxT( "Component orientation matrix internal error" ) );
1274  m_transform = transform;
1275 
1276  return CMP_NORMAL;
1277 }
1278 
1279 
1281 {
1282  return m_transform.TransformCoordinate( aPoint );
1283 }
1284 
1285 
1286 #if defined(DEBUG)
1287 
1288 void SCH_COMPONENT::Show( int nestLevel, std::ostream& os ) const
1289 {
1290  // for now, make it look like XML:
1291  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1292  << " ref=\"" << TO_UTF8( GetField( 0 )->GetName() )
1293  << '"' << " chipName=\""
1294  << GetLibId().Format() << '"' << m_Pos
1295  << " layer=\"" << m_Layer
1296  << '"' << ">\n";
1297 
1298  // skip the reference, it's been output already.
1299  for( int i = 1; i < GetFieldCount(); ++i )
1300  {
1301  wxString value = GetField( i )->GetText();
1302 
1303  if( !value.IsEmpty() )
1304  {
1305  NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
1306  << TO_UTF8( GetField( i )->GetName() )
1307  << '"' << " value=\""
1308  << TO_UTF8( value ) << "\"/>\n";
1309  }
1310  }
1311 
1312  NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
1313 }
1314 
1315 #endif
1316 
1317 
1319 {
1320  EDA_RECT bBox;
1321 
1322  if( PART_SPTR part = m_part.lock() )
1323  {
1324  bBox = part->GetBodyBoundingBox( m_unit, m_convert );
1325  }
1326  else
1327  {
1328  bBox = dummy()->GetBodyBoundingBox( m_unit, m_convert );
1329  }
1330 
1331  int x0 = bBox.GetX();
1332  int xm = bBox.GetRight();
1333 
1334  // We must reverse Y values, because matrix orientation
1335  // suppose Y axis normal for the library items coordinates,
1336  // m_transform reverse Y values, but bBox is already reversed!
1337  int y0 = -bBox.GetY();
1338  int ym = -bBox.GetBottom();
1339 
1340  // Compute the real Boundary box (rotated, mirrored ...)
1341  int x1 = m_transform.x1 * x0 + m_transform.y1 * y0;
1342  int y1 = m_transform.x2 * x0 + m_transform.y2 * y0;
1343  int x2 = m_transform.x1 * xm + m_transform.y1 * ym;
1344  int y2 = m_transform.x2 * xm + m_transform.y2 * ym;
1345 
1346  // H and W must be > 0:
1347  if( x2 < x1 )
1348  std::swap( x2, x1 );
1349 
1350  if( y2 < y1 )
1351  std::swap( y2, y1 );
1352 
1353  bBox.SetX( x1 );
1354  bBox.SetY( y1 );
1355  bBox.SetWidth( x2 - x1 );
1356  bBox.SetHeight( y2 - y1 );
1357 
1358  bBox.Offset( m_Pos );
1359  return bBox;
1360 }
1361 
1362 
1364 {
1365  EDA_RECT bbox = GetBodyBoundingBox();
1366 
1367  for( size_t i = 0; i < m_Fields.size(); i++ )
1368  {
1369  bbox.Merge( m_Fields[i].GetBoundingBox() );
1370  }
1371 
1372  return bbox;
1373 }
1374 
1375 
1377 {
1378  wxString msg;
1379 
1380  // part and alias can differ if alias is not the root
1381  if( PART_SPTR part = m_part.lock() )
1382  {
1383  if( part.get() != dummy() )
1384  {
1385  LIB_ALIAS* alias = nullptr;
1386 
1387  if( part->GetLib() && part->GetLib()->IsCache() )
1388  alias = part->GetAlias( GetLibId().Format() );
1389  else
1390  alias = part->GetAlias( GetLibId().GetLibItemName() );
1391 
1392  if( !alias )
1393  return;
1394 
1395  if( m_currentSheetPath )
1396  aList.push_back( MSG_PANEL_ITEM( _( "Reference" ),
1398  DARKCYAN ) );
1399 
1400  msg = part->IsPower() ? _( "Power symbol" ) : _( "Value" );
1401 
1402  aList.push_back( MSG_PANEL_ITEM( msg, GetField( VALUE )->GetShownText(), DARKCYAN ) );
1403 
1404  // Display component reference in library and library
1405  aList.push_back( MSG_PANEL_ITEM( _( "Name" ), GetLibId().GetLibItemName(),
1406  BROWN ) );
1407 
1408  if( alias->GetName() != part->GetName() )
1409  aList.push_back( MSG_PANEL_ITEM( _( "Alias of" ), part->GetName(), BROWN ) );
1410 
1411  if( alias->GetLib() && alias->GetLib()->IsCache() )
1412  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), alias->GetLibraryName(), RED ) );
1413  else if( !m_lib_id.GetLibNickname().empty() )
1414  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), m_lib_id.GetLibNickname(),
1415  BROWN ) );
1416  else
1417  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), _( "Undefined!!!" ), RED ) );
1418 
1419  // Display the current associated footprint, if exists.
1420  if( !GetField( FOOTPRINT )->IsVoid() )
1421  msg = GetField( FOOTPRINT )->GetShownText();
1422  else
1423  msg = _( "<Unknown>" );
1424 
1425  aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), msg, DARKRED ) );
1426 
1427  // Display description of the component, and keywords found in lib
1428  aList.push_back( MSG_PANEL_ITEM( _( "Description" ), alias->GetDescription(),
1429  DARKCYAN ) );
1430  aList.push_back( MSG_PANEL_ITEM( _( "Key words" ), alias->GetKeyWords(), DARKCYAN ) );
1431  }
1432  }
1433  else
1434  {
1435  if( m_currentSheetPath )
1436  aList.push_back( MSG_PANEL_ITEM( _( "Reference" ), GetRef( m_currentSheetPath ),
1437  DARKCYAN ) );
1438 
1439  aList.push_back( MSG_PANEL_ITEM( _( "Value" ), GetField( VALUE )->GetShownText(),
1440  DARKCYAN ) );
1441  aList.push_back( MSG_PANEL_ITEM( _( "Name" ), GetLibId().GetLibItemName(), BROWN ) );
1442 
1443  wxString libNickname = GetLibId().GetLibNickname();
1444 
1445  if( libNickname.empty() )
1446  {
1447  aList.push_back( MSG_PANEL_ITEM( _( "Library" ),
1448  _( "No library defined!!!" ), RED ) );
1449  }
1450  else
1451  {
1452  msg.Printf( _( "Symbol not found in %s!!!" ), libNickname );
1453  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), msg , RED ) );
1454  }
1455  }
1456 }
1457 
1458 
1460 {
1461  return add_component_xpm;
1462 }
1463 
1464 
1465 void SCH_COMPONENT::MirrorY( int aYaxis_position )
1466 {
1467  int dx = m_Pos.x;
1468 
1470  MIRROR( m_Pos.x, aYaxis_position );
1471  dx -= m_Pos.x; // dx,0 is the move vector for this transform
1472 
1473  for( int ii = 0; ii < GetFieldCount(); ii++ )
1474  {
1475  // Move the fields to the new position because the component itself has moved.
1476  wxPoint pos = GetField( ii )->GetTextPos();
1477  pos.x -= dx;
1478  GetField( ii )->SetTextPos( pos );
1479  }
1480 }
1481 
1482 
1483 void SCH_COMPONENT::MirrorX( int aXaxis_position )
1484 {
1485  int dy = m_Pos.y;
1486 
1488  MIRROR( m_Pos.y, aXaxis_position );
1489  dy -= m_Pos.y; // dy,0 is the move vector for this transform
1490 
1491  for( int ii = 0; ii < GetFieldCount(); ii++ )
1492  {
1493  // Move the fields to the new position because the component itself has moved.
1494  wxPoint pos = GetField( ii )->GetTextPos();
1495  pos.y -= dy;
1496  GetField( ii )->SetTextPos( pos );
1497  }
1498 }
1499 
1500 
1502 {
1503  wxPoint prev = m_Pos;
1504 
1505  RotatePoint( &m_Pos, aPosition, 900 );
1506 
1508 
1509  for( int ii = 0; ii < GetFieldCount(); ii++ )
1510  {
1511  // Move the fields to the new position because the component itself has moved.
1512  wxPoint pos = GetField( ii )->GetTextPos();
1513  pos.x -= prev.x - m_Pos.x;
1514  pos.y -= prev.y - m_Pos.y;
1515  GetField( ii )->SetTextPos( pos );
1516  }
1517 }
1518 
1519 
1520 bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData,
1521  wxPoint* aFindLocation )
1522 {
1523  wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() );
1524 
1525  // Components are searchable via the child field and pin item text.
1526  return false;
1527 }
1528 
1529 
1530 void SCH_COMPONENT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1531 {
1532  if( PART_SPTR part = m_part.lock() )
1533  {
1534  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
1535  {
1536  wxASSERT( pin->Type() == LIB_PIN_T );
1537 
1538  if( pin->GetUnit() && m_unit && ( m_unit != pin->GetUnit() ) )
1539  continue;
1540 
1541  if( pin->GetConvert() && m_convert && ( m_convert != pin->GetConvert() ) )
1542  continue;
1543 
1544  DANGLING_END_ITEM item( PIN_END, pin, GetPinPhysicalPosition( pin ), this );
1545  aItemList.push_back( item );
1546  }
1547  }
1548 }
1549 
1550 
1551 bool SCH_COMPONENT::IsDanglingStateChanged( std::vector<DANGLING_END_ITEM>& aItemList )
1552 {
1553  bool changed = false;
1554 
1555  for( size_t i = 0; i < m_Pins.size(); ++i )
1556  {
1557  bool previousState;
1559 
1560  if( i < m_isDangling.size() )
1561  {
1562  previousState = m_isDangling[ i ];
1563  m_isDangling[ i ] = true;
1564  }
1565  else
1566  {
1567  previousState = true;
1568  m_isDangling.push_back( true );
1569  }
1570 
1571  for( DANGLING_END_ITEM& each_item : aItemList )
1572  {
1573  // Some people like to stack pins on top of each other in a symbol to indicate
1574  // internal connection. While technically connected, it is not particularly useful
1575  // to display them that way, so skip any pins that are in the same symbol as this
1576  // one.
1577  if( each_item.GetParent() == this )
1578  continue;
1579 
1580  switch( each_item.GetType() )
1581  {
1582  case PIN_END:
1583  case LABEL_END:
1584  case SHEET_LABEL_END:
1585  case WIRE_START_END:
1586  case WIRE_END_END:
1587  case NO_CONNECT_END:
1588  case JUNCTION_END:
1589 
1590  if( pos == each_item.GetPosition() )
1591  m_isDangling[ i ] = false;
1592 
1593  break;
1594 
1595  default:
1596  break;
1597  }
1598 
1599  if( !m_isDangling[ i ] )
1600  break;
1601  }
1602 
1603  changed = ( changed || ( previousState != m_isDangling[ i ] ) );
1604  }
1605 
1606  while( m_isDangling.size() > m_Pins.size() )
1607  m_isDangling.pop_back();
1608 
1609  return changed;
1610 }
1611 
1612 
1614 {
1615  for( bool each : m_isDangling )
1616  {
1617  if( each )
1618  return true;
1619  }
1620  return false;
1621 }
1622 
1623 
1625 {
1626  wxCHECK_MSG( Pin != NULL && Pin->Type() == LIB_PIN_T, wxPoint( 0, 0 ),
1627  wxT( "Cannot get physical position of pin." ) );
1628 
1629  return m_transform.TransformCoordinate( Pin->GetPosition() ) + m_Pos;
1630 }
1631 
1632 
1633 bool SCH_COMPONENT::IsSelectStateChanged( const wxRect& aRect )
1634 {
1635  bool previousState = IsSelected();
1636 
1638 
1639  if( aRect.Intersects( boundingBox ) )
1640  SetFlags( SELECTED );
1641  else
1642  ClearFlags( SELECTED );
1643 
1644  return previousState != IsSelected();
1645 }
1646 
1647 
1648 void SCH_COMPONENT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
1649 {
1650  for( auto pin : m_Pins )
1651  aPoints.push_back( m_transform.TransformCoordinate( pin ) + m_Pos );
1652 }
1653 
1654 
1656 {
1657  if( PART_SPTR part = m_part.lock() )
1658  {
1659 
1660  m_Pins.clear();
1661 
1662  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
1663  {
1664  wxASSERT( pin->Type() == LIB_PIN_T );
1665 
1666  if( pin->GetUnit() && m_unit && ( m_unit != pin->GetUnit() ) )
1667  continue;
1668 
1669  if( pin->GetConvert() && m_convert && ( m_convert != pin->GetConvert() ) )
1670  continue;
1671 
1672  m_Pins.push_back( pin->GetPosition() );
1673  }
1674 
1675  // Calculate the position relative to the component.
1676  wxPoint libPosition = aPosition - m_Pos;
1677 
1678  return part->LocateDrawItem( m_unit, m_convert, aType, libPosition, m_transform );
1679  }
1680 
1681  return NULL;
1682 }
1683 
1684 
1686 {
1687  wxString tmp;
1688  tmp.Printf( _( "Symbol %s, %s" ),
1689  GetChars( GetLibId().GetLibItemName() ),
1690  GetChars( GetField( REFERENCE )->GetShownText() ) );
1691  return tmp;
1692 }
1693 
1694 
1695 SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
1696  const KICAD_T aFilterTypes[] )
1697 {
1698  KICAD_T stype;
1699 
1700  for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p )
1701  {
1702  // If caller wants to inspect component type or and component children types.
1703  if( stype == Type() )
1704  {
1705  if( SEARCH_QUIT == aInspector( this, aTestData ) )
1706  return SEARCH_QUIT;
1707  }
1708 
1709  switch( stype )
1710  {
1711  case SCH_FIELD_T:
1712  // Test the bounding boxes of fields if they are visible and not empty.
1713  for( int ii = 0; ii < GetFieldCount(); ii++ )
1714  {
1715  if( SEARCH_QUIT == aInspector( GetField( ii ), (void*) this ) )
1716  return SEARCH_QUIT;
1717  }
1718  break;
1719 
1721  if( SEARCH_QUIT == aInspector( GetField( REFERENCE ), (void*) this ) )
1722  return SEARCH_QUIT;
1723  break;
1724 
1726  if( SEARCH_QUIT == aInspector( GetField( VALUE ), (void*) this ) )
1727  return SEARCH_QUIT;
1728  break;
1729 
1731  if( SEARCH_QUIT == aInspector( GetField( FOOTPRINT ), (void*) this ) )
1732  return SEARCH_QUIT;
1733  break;
1734 
1735 
1736  case LIB_PIN_T:
1737  if( PART_SPTR part = m_part.lock() )
1738  {
1739  LIB_PINS pins;
1740 
1741  part->GetPins( pins, m_unit, m_convert );
1742 
1743  for( size_t i = 0; i < pins.size(); i++ )
1744  {
1745  if( SEARCH_QUIT == aInspector( pins[ i ], (void*) this ) )
1746  return SEARCH_QUIT;
1747  }
1748  }
1749  break;
1750 
1751  default:
1752  break;
1753  }
1754  }
1755 
1756  return SEARCH_CONTINUE;
1757 }
1758 
1759 
1761  SCH_SHEET_PATH* aSheetPath )
1762 {
1763  if( PART_SPTR part = m_part.lock() )
1764  {
1765  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
1766  {
1767  wxASSERT( pin->Type() == LIB_PIN_T );
1768 
1769  if( pin->GetUnit() && ( pin->GetUnit() != GetUnitSelection( aSheetPath ) ) )
1770  continue;
1771 
1772  if( pin->GetConvert() && ( pin->GetConvert() != GetConvert() ) )
1773  continue;
1774 
1775  wxPoint pos = GetTransform().TransformCoordinate( pin->GetPosition() ) + m_Pos;
1776 
1777  NETLIST_OBJECT* item = new NETLIST_OBJECT();
1778  item->m_SheetPathInclude = *aSheetPath;
1779  item->m_Comp = (SCH_ITEM*) pin;
1780  item->m_SheetPath = *aSheetPath;
1781  item->m_Type = NET_PIN;
1782  item->m_Link = (SCH_ITEM*) this;
1783  item->m_ElectricalPinType = pin->GetType();
1784  item->m_PinNum = pin->GetNumber();
1785  item->m_Label = pin->GetName();
1786  item->m_Start = item->m_End = pos;
1787 
1788  aNetListItems.push_back( item );
1789 
1790  if( pin->IsPowerConnection() )
1791  {
1792  // There is an associated PIN_LABEL.
1793  item = new NETLIST_OBJECT();
1794  item->m_SheetPathInclude = *aSheetPath;
1795  item->m_Comp = NULL;
1796  item->m_SheetPath = *aSheetPath;
1797  item->m_Type = NET_PINLABEL;
1798  item->m_Label = pin->GetName();
1799  item->m_Start = pos;
1800  item->m_End = item->m_Start;
1801 
1802  aNetListItems.push_back( item );
1803  }
1804  }
1805  }
1806 }
1807 
1808 
1809 bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
1810 {
1811  if( Type() != aItem.Type() )
1812  return Type() < aItem.Type();
1813 
1814  SCH_COMPONENT* component = (SCH_COMPONENT*) &aItem;
1815 
1816  EDA_RECT rect = GetBodyBoundingBox();
1817 
1818  if( rect.GetArea() != component->GetBodyBoundingBox().GetArea() )
1819  return rect.GetArea() < component->GetBodyBoundingBox().GetArea();
1820 
1821  if( m_Pos.x != component->m_Pos.x )
1822  return m_Pos.x < component->m_Pos.x;
1823 
1824  if( m_Pos.y != component->m_Pos.y )
1825  return m_Pos.y < component->m_Pos.y;
1826 
1827  return false;
1828 }
1829 
1830 
1831 bool SCH_COMPONENT::operator==( const SCH_COMPONENT& aComponent ) const
1832 {
1833  if( GetFieldCount() != aComponent.GetFieldCount() )
1834  return false;
1835 
1836  for( int i = VALUE; i < GetFieldCount(); i++ )
1837  {
1838  if( GetField( i )->GetText().Cmp( aComponent.GetField( i )->GetText() ) != 0 )
1839  return false;
1840  }
1841 
1842  return true;
1843 }
1844 
1845 
1846 bool SCH_COMPONENT::operator!=( const SCH_COMPONENT& aComponent ) const
1847 {
1848  return !( *this == aComponent );
1849 }
1850 
1851 
1853 {
1854  wxCHECK_MSG( Type() == aItem.Type(), *this,
1855  wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
1856  GetClass() );
1857 
1858  if( &aItem != this )
1859  {
1860  SCH_ITEM::operator=( aItem );
1861 
1862  SCH_COMPONENT* c = (SCH_COMPONENT*) &aItem;
1863 
1864  m_lib_id = c->m_lib_id;
1865  m_part = c->m_part;
1866  m_Pos = c->m_Pos;
1867  m_unit = c->m_unit;
1868  m_convert = c->m_convert;
1869  m_transform = c->m_transform;
1870  m_Pins = c->m_Pins;
1871 
1873 
1874  m_Fields = c->m_Fields; // std::vector's assignment operator.
1875 
1876  // Reparent fields after assignment to new component.
1877  for( int ii = 0; ii < GetFieldCount(); ++ii )
1878  {
1879  GetField( ii )->SetParent( this );
1880  }
1881  }
1882 
1883  return *this;
1884 }
1885 
1886 
1887 bool SCH_COMPONENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
1888 {
1889  EDA_RECT bBox = GetBodyBoundingBox();
1890  bBox.Inflate( aAccuracy );
1891 
1892  if( bBox.Contains( aPosition ) )
1893  return true;
1894 
1895  return false;
1896 }
1897 
1898 
1899 bool SCH_COMPONENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
1900 {
1902  return false;
1903 
1904  EDA_RECT rect = aRect;
1905 
1906  rect.Inflate( aAccuracy );
1907 
1908  if( aContained )
1909  return rect.Contains( GetBodyBoundingBox() );
1910 
1911  return rect.Intersects( GetBodyBoundingBox() );
1912 }
1913 
1914 
1915 bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
1916 {
1917  wxPoint new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_Pos );
1918  return std::find( m_Pins.begin(), m_Pins.end(), new_pos ) != m_Pins.end();
1919 }
1920 
1921 
1923 {
1924  SCH_FIELD* rf = GetField( REFERENCE );
1925  return ! rf->GetText().StartsWith( wxT( "#" ) );
1926 }
1927 
1928 
1929 void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
1930 {
1931  TRANSFORM temp;
1932 
1933  if( PART_SPTR part = m_part.lock() )
1934  {
1935  temp = GetTransform();
1936 
1937  part->Plot( aPlotter, GetUnit(), GetConvert(), m_Pos, temp );
1938 
1939  for( size_t i = 0; i < m_Fields.size(); i++ )
1940  {
1941  m_Fields[i].Plot( aPlotter );
1942  }
1943  }
1944 }
Definition of the SCH_SHEET class for Eeschema.
LIB_ALIAS * LoadSymbol(const wxString &aNickname, const wxString &aAliasName)
Load a LIB_ALIAS having aAliasName from the library given by aNickname.
void UpdateFields(bool aResetStyle, bool aResetRef=false)
Restores fields to the original library values.
bool HitTest(const wxPoint &aPosition, int aAccuracy) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item...
bool IsValid() const
Definition: lib_id.h:175
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:106
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
void SetTimeStamp(timestamp_t aNewTimeStamp)
Change the time stamp to aNewTimeStamp and updates the reference path.
void Offset(int dx, int dy)
Definition: eda_rect.h:128
Class SCH_FIELD instances are attached to a component and provide a place for the component&#39;s value...
Definition: sch_field.h:56
SCH_LAYER_ID m_Layer
void SetModified()
long timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
Definition: base_struct.h:155
void GetMsgPanelInfo(std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it&#39;s internal state for displ...
void Rotate(wxPoint aPosition) override
Function Rotate rotates the item around aPosition 90 degrees in the clockwise direction.
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
Part library alias object definition.
SCH_FIELD * FindField(const wxString &aFieldName, bool aIncludeDefaultFields=true)
Search for a SCH_FIELD with aFieldName.
bool IsMoving() const
Definition: base_struct.h:229
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:179
wxString GetAliasDescription() const
Return information about the aliased parts.
timestamp_t m_TimeStamp
Time stamp used for logical links.
Definition: base_struct.h:180
void Plot(PLOTTER *aPlotter) override
Function Plot plots the schematic item to aPlotter.
TRANSFORM & GetTransform() const
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
void SetTransform(const TRANSFORM &aTransform)
PNG memory record (file in memory).
Definition: bitmap_types.h:41
void UpdateUnit(int aUnit)
Change the unit number to aUnit without setting any internal flags.
wxString GetPath(const SCH_SHEET_PATH *sheet) const
const wxPoint & GetTextPos() const
Definition: eda_text.h:222
int GetOrientation()
Get the display symbol orientation.
int y2
Definition: transform.h:51
EDA_ITEM * GetCurItem() const
Definition: base_screen.h:233
SCH_SHEET_PATH m_SheetPathInclude
Define a symbol library graphical text item.
Definition: lib_text.h:44
bool Contains(const wxPoint &aPoint) const
Function Contains.
SCH_FIELDS m_Fields
Variable length list of fields.
Definition: sch_component.h:91
const SCH_SHEET_PATH * m_currentSheetPath
A temporary sheet path is required to generate the correct reference designator string in complex hie...
wxPoint GetScreenCoord(const wxPoint &aPoint)
Returns the coordinate points relative to the orientation of the symbol to aPoint.
void ImportValues(const LIB_FIELD &aSource)
Function ImportValues copy parameters from a LIB_FIELD source.
Definition: sch_field.cpp:222
bool Resolve(PART_LIBS *aLibs)
Assigns the current LIB_PART from aLibs which this symbol is based on.
static bool sort_by_libid(const SCH_COMPONENT *ref, SCH_COMPONENT *cmp)
const wxString GetLibraryName()
wxArrayString m_PathsAndReferences
Defines the hierarchical path and reference of the component.
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:120
wxPoint m_Pos
Name and library where symbol was loaded from, i.e. "74xx:74LS00".
Definition: sch_component.h:77
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
void GetConnectionPoints(std::vector< wxPoint > &aPoints) const override
Function GetConnectionPoints add all the connection points for this item to aPoints.
int GetUnitSelection(SCH_SHEET_PATH *aSheet)
const EDA_RECT GetBodyBoundingBox(int aUnit, int aConvert) const
Get the symbol bounding box excluding fields.
bool IsCache() const
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Function GetEndPoints adds the schematic item end points to aItemList if the item has end points...
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED) override
Function Draw Draw a schematic item.
Definition: sch_field.cpp:119
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:221
int x2
Definition: transform.h:50
void MirrorX(int aXaxis_position) override
Function MirrorX mirrors item relative to the X axis about aXaxis_position.
bool IsSelected() const
Definition: base_struct.h:232
LIB_PIN * GetPin(const wxString &number)
Find a symbol pin by number.
int x1
Definition: transform.h:48
static const wxString GetDefaultFieldName(int aFieldNdx)
Function GetDefaultFieldName returns a default symbol field name for field aFieldNdx for all componen...
Schematic editor (Eeschema) main window.
SCH_SHEET_PATH m_SheetPath
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.
ELECTRICAL_PINTYPE m_ElectricalPinType
void SetUnitSelection(SCH_SHEET_PATH *aSheet, int aUnitSelection)
void SwapData(SCH_ITEM *aItem) override
Function SwapData swap the internal data structures aItem with the schematic item.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:212
int GetUnitCount() const
Return the number of units per package of the symbol.
std::vector< bool > m_isDangling
One isDangling per pin.
Definition: sch_component.h:95
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
EDA_RECT GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the fields.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
NETLIST_ITEM_T m_Type
std::vector< wxPoint > m_Pins
Definition: sch_component.h:96
PART_LIB * GetLib()
EDA_ITEM * m_Comp
#define abs(a)
Definition: auxiliary.h:84
const string & str
Definition: json11.cpp:596
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
Definition: colors.h:54
The base class for drawable items used by schematic library components.
Definition: lib_draw_item.h:66
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
wxString GetAliasDocumentation() const
Return the documentation text for the given part alias.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Class NETLIST_OBJECT_LIST is a container holding and owning NETLIST_OBJECTs, which are connected item...
wxString Path() const
Function Path the path uses the time stamps which do not changes even when editing sheet parameters a...
void SetConvert(int aConvert)
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:133
bool IsSelectStateChanged(const wxRect &aRect) override
Function IsSelectStateChanged checks if the selection state of an item inside aRect has changed...
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
#define IS_NEW
New item, just created.
Definition: base_struct.h:109
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:100
Class SCH_COLLECTOR.
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
BOX2I boundingBox(T aObject)
boundingBox template method
Definition: shape_index.h:59
int GetConvert() const
int y1
Definition: transform.h:49
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:111
#define SELECTED
Definition: base_struct.h:116
timestamp_t GetNewTimeStamp()
Definition: common.cpp:160
void SetLibId(const LIB_ID &aName, PART_LIBS *aLibs=NULL)
wxString wx_str() const
Definition: utf8.cpp:48
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1098
double GetArea() const
Function GetArea returns the area of the rectangle.
void UpdatePinCache()
Updates the local cache of pin positions.
Class for tranforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
PART_REF m_part
points into the PROJECT&#39;s libraries to the LIB_PART for this component
Definition: sch_component.h:93
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:264
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
bool empty() const
Definition: utf8.h:108
void SetHeight(int val)
Definition: eda_rect.h:133
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:224
static void ResolveAll(const SCH_COLLECTOR &aComponents, PART_LIBS *aLibs)
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:37
bool IsMouseCaptured() const
const UTF8 & GetLibItemName() const
Definition: lib_id.h:118
Subclass of DIALOG_SCH_FIND_BASE, which is generated by wxFormBuilder.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:128
std::shared_ptr< LIB_PART > PART_SPTR
shared pointer to LIB_PART
void SetLayer(SCH_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
bool operator<(const SCH_ITEM &aItem) const override
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
wxString GetDescription() const
SCH_COMPONENT(const wxPoint &pos=wxPoint(0, 0), SCH_ITEM *aParent=NULL)
PART_SPTR SharedPtr()
std::string toUTFTildaText(const wxString &txt)
Function toUTFTildaText convert a wxString to UTF8 and replace any control characters with a ~...
Define a library symbol object.
LIB_ALIAS * FindAlias(const wxString &aName) const
Find LIB_ALIAS by aName.
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
bool IsDangling() const override
Return whether any pin in this symbol is dangling.
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:118
EDA_RECT * GetClipBox()
void GetNetListItem(NETLIST_OBJECT_LIST &aNetListItems, SCH_SHEET_PATH *aSheetPath) override
Function GetNetListItem creates a new NETLIST_OBJECT for the schematic object and adds it to aNetList...
void SetX(int val)
Definition: eda_rect.h:130
wxLogTrace helper definitions.
LIB_PART * FindLibPart(const LIB_ID &aLibId, const wxString &aLibraryName=wxEmptyString)
Search all libraries in the list for a part.
Definition: colors.h:60
wxString GetText(GRAPHIC_PINSHAPE shape)
Definition: pin_shape.cpp:33
void SetUnit(int aUnit)
Change the unit number to aUnit.
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData, wxPoint *aFindLocation) override
Function Matches compares the item against the search criteria in aSearchData.
int GetBottom() const
Definition: eda_rect.h:122
int GetUnit() const
Class SCH_SHEET_PATH.
bool IsInNetlist() const
static PART_DRAW_OPTIONS Default()
wxString GetFieldText(const wxString &aFieldName, SCH_EDIT_FRAME *aFrame) const
Search for a field named aFieldName and returns text associated with this field.
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Clear exiting component annotation.
int GetRight() const
Definition: eda_rect.h:119
void SetWidth(int val)
Definition: eda_rect.h:132
const wxString GetRef(const SCH_SHEET_PATH *aSheet)
Return the reference for the given sheet path.
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
int SetLibItemName(const UTF8 &aLibItemName, bool aTestForRev=true)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition: lib_id.cpp:232
void SetEndPosition(const wxPoint &aPosition)
Definition: lib_rectangle.h:67
void SetY(int val)
Definition: eda_rect.h:131
bool operator==(const SCH_COMPONENT &aComponent) const
LIB_PART * GetPart() const
Get the shared LIB_PART.
SCH_ITEM & operator=(const SCH_ITEM &aItem)
wxPoint GetPosition() const override
Return the current draw object position.
Definition: lib_pin.h:462
void Move(const wxPoint &aPosition) override
Move a draw object to aPosition.
A collection of PART_LIB objects.
int m_unit
The unit for multiple part per package components.
Definition: sch_component.h:82
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.
bool IsDanglingStateChanged(std::vector< DANGLING_END_ITEM > &aItemList) override
Test if the component&#39;s dangling state has changed for all pins.
Base plotter engine class.
Definition: plotter.h:96
wxString GetDocFileName() const
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
Definition the SCH_COMPONENT class for Eeschema.
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_draw_item.h:60
void GetPins(std::vector< LIB_PIN * > &aPinsList)
Populate a vector with all the pins.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
see class PGM_BASE
const wxChar *const traceFindItem
Flag to enable find debug tracing.
const wxString & GetName() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int GetFieldCount() const
Return the number of fields in this symbol.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Definition: sch_field.cpp:252
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
void AddHierarchicalReference(const wxString &aPath, const wxString &aRef, int aMulti)
Add a full hierarchical reference to this symbol.
bool IsVisible() const
Definition: eda_text.h:174
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void MirrorY(int aYaxis_position) override
Function MirrorY mirrors item relative to the Y axis about aYaxis_position.
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED) override
Function Draw Draw a schematic item.
#define ROTATE_VALUES_COUNT
void SetText(const wxString &aText) override
Sets the text item string to aText.
Definition: lib_text.cpp:343
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:257
STATUS_FLAGS m_Flags
Flag bits for editing and other uses.
Definition: base_struct.h:186
size_t i
Definition: json11.cpp:597
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
int GetX() const
Definition: eda_rect.h:109
const LIB_ID & GetLibId() const
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:193
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:162
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
UTF8 Format() const
Definition: lib_id.cpp:263
int GetY() const
Definition: eda_rect.h:110
virtual wxString GetClass() const override
Function GetClass returns the class name.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:265
const wxString & GetName() const
bool operator!=(const SCH_COMPONENT &aComponent) const
int m_convert
The alternate body style for components that have more than one body style defined.
Definition: sch_component.h:83
Class DANGLING_END_ITEM is a helper class used to store the state of schematic items that can be conn...
Definition for part library class.
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
SEARCH_RESULT
Definition: base_struct.h:64
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.
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:101
wxString GetClass() const override
Function GetClass returns the class name.
Definition of the NETLIST_OBJECT class.
Message panel definition file.
AUTOPLACED m_fieldsAutoplaced
indicates status of field autoplacement
Definition: sch_component.h:98
wxString m_prefix
C, R, U, Q etc - the first character which typically indicates what the component is...
Definition: sch_component.h:86
SCH_ITEM * m_Link
#define VALUE
Object used to load, save, search, and otherwise manipulate symbol library files. ...
wxString GetKeyWords() const
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
TRANSFORM m_transform
The rotation/mirror transformation matrix.
Definition: sch_component.h:90
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
bool doIsConnected(const wxPoint &aPosition) const override
Function doIsConnected provides the object specific test to see if it is connected to aPosition...
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
static void UpdateAllPinCaches(const SCH_COLLECTOR &aComponents)
Update the pin cache for all components in aComponents.
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:58
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:214
virtual void SetText(const wxString &aText)
Definition: eda_text.h:139
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
#define IS_MOVED
Item being moved.
Definition: base_struct.h:108
wxPoint GetPinPhysicalPosition(const LIB_PIN *Pin) const
Definition: colors.h:62