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