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