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