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