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