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