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-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include <fctsys.h>
31 #include <pgm_base.h>
32 #include <class_drawpanel.h>
33 #include <gr_basic.h>
34 #include <kicad_string.h>
35 #include <richio.h>
36 #include <schframe.h>
37 #include <plot_common.h>
38 #include <msgpanel.h>
39 #include <bitmaps.h>
40 
41 #include <general.h>
42 #include <class_library.h>
43 #include <lib_rectangle.h>
44 #include <lib_pin.h>
45 #include <lib_text.h>
46 #include <sch_component.h>
47 #include <sch_sheet.h>
48 #include <sch_sheet_path.h>
49 #include <class_netlist_object.h>
50 #include <lib_draw_item.h>
51 #include <symbol_lib_table.h>
52 
54 
55 #include <wx/tokenzr.h>
56 #include <iostream>
57 
58 #define NULL_STRING "_NONAME_"
59 
65 std::string toUTFTildaText( const wxString& txt )
66 {
67  std::string ret = TO_UTF8( txt );
68 
69  for( std::string::iterator it = ret.begin(); it!=ret.end(); ++it )
70  {
71  if( (unsigned char) *it <= ' ' )
72  *it = '~';
73  }
74  return ret;
75 }
76 
77 
91 static LIB_PART* dummy()
92 {
93  static LIB_PART* part;
94 
95  if( !part )
96  {
97  part = new LIB_PART( wxEmptyString );
98 
99  LIB_RECTANGLE* square = new LIB_RECTANGLE( part );
100 
101  square->Move( wxPoint( -200, 200 ) );
102  square->SetEndPosition( wxPoint( 200, -200 ) );
103 
104  LIB_TEXT* text = new LIB_TEXT( part );
105 
106  text->SetTextSize( wxSize( 150, 150 ) );
107  text->SetText( wxString( wxT( "??" ) ) );
108 
109  part->AddDrawItem( square );
110  part->AddDrawItem( text );
111  }
112 
113  return part;
114 }
115 
116 
118  SCH_ITEM( aParent, SCH_COMPONENT_T )
119 {
120  Init( aPos );
121  m_currentSheetPath = NULL;
123 }
124 
125 
127  int convert, const wxPoint& pos, bool setNewItemFlag ) :
128  SCH_ITEM( NULL, SCH_COMPONENT_T )
129 {
130  Init( pos );
131 
132  m_unit = unit;
133  m_convert = convert;
134  m_lib_id.SetLibItemName( TO_UTF8( aPart.GetName() ), false );
135  m_part = aPart.SharedPtr();
136  m_currentSheetPath = NULL;
138 
140 
141  if( setNewItemFlag )
142  m_Flags = IS_NEW | IS_MOVED;
143 
144  // Import user defined fields from the library component:
145  LIB_FIELDS libFields;
146 
147  aPart.GetFields( libFields );
148 
149  for( LIB_FIELDS::iterator it = libFields.begin(); it!=libFields.end(); ++it )
150  {
151  // Can no longer insert an empty name, since names are now keys. The
152  // field index is not used beyond the first MANDATORY_FIELDS
153  if( it->GetName().IsEmpty() )
154  continue;
155 
156  // See if field already exists (mandatory fields always exist).
157  // for mandatory fields, the name and field id are fixed, so we use the
158  // known and fixed id to get them (more reliable than names, which can be translated)
159  // for other fields (custom fields), locate the field by same name
160  // (field id has no known meaning for custom fields)
161  int idx = it->GetId();
162  SCH_FIELD* schField;
163 
164  if( idx < MANDATORY_FIELDS )
165  schField = GetField( idx );
166  else
167  schField = FindField( it->GetName() );
168 
169  if( !schField )
170  {
171  SCH_FIELD fld( wxPoint( 0, 0 ), GetFieldCount(), this, it->GetName() );
172  schField = AddField( fld );
173  }
174 
175  schField->ImportValues( *it );
176  schField->SetText( it->GetText() );
177 
178  // Now the field is initialized, place it to the right position:
179  schField->SetTextPos( m_Pos + it->GetTextPos() );
180  }
181 
182  wxString msg = aPart.GetReferenceField().GetText();
183 
184  if( msg.IsEmpty() )
185  msg = wxT( "U" );
186 
187  m_prefix = msg;
188 
189  // update the reference -- just the prefix for now.
190  msg += wxT( "?" );
191  SetRef( sheet, msg );
192 
193  // Use the schematic component name instead of the library value field name.
194  GetField( VALUE )->SetText( FROM_UTF8( GetLibId().GetLibItemName() ) );
195 }
196 
197 
199  SCH_ITEM( aComponent )
200 {
201  m_currentSheetPath = NULL;
202  m_Parent = aComponent.m_Parent;
203  m_Pos = aComponent.m_Pos;
204  m_unit = aComponent.m_unit;
205  m_convert = aComponent.m_convert;
206  m_lib_id = aComponent.m_lib_id;
207  m_part = aComponent.m_part;
208 
209  SetTimeStamp( aComponent.m_TimeStamp );
210 
211  m_transform = aComponent.m_transform;
212  m_prefix = aComponent.m_prefix;
214  m_Fields = aComponent.m_Fields;
215 
216  // Re-parent the fields, which before this had aComponent as parent
217  for( int i = 0; i<GetFieldCount(); ++i )
218  {
219  GetField( i )->SetParent( this );
220  }
221 
222  m_isDangling = aComponent.m_isDangling;
224 }
225 
226 
227 void SCH_COMPONENT::Init( const wxPoint& pos )
228 {
229  m_Pos = pos;
230  m_unit = 0; // In multi unit chip - which unit to draw.
231  m_convert = 0; // De Morgan Handling
232 
233  // The rotation/mirror transformation matrix. pos normal
235 
236  // construct only the mandatory fields, which are the first 4 only.
237  for( int i = 0; i < MANDATORY_FIELDS; ++i )
238  {
239  SCH_FIELD field( pos, i, this, TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
240 
241  if( i == REFERENCE )
242  field.SetLayer( LAYER_REFERENCEPART );
243  else if( i == VALUE )
244  field.SetLayer( LAYER_VALUEPART );
245 
246  // else keep LAYER_FIELDS from SCH_FIELD constructor
247 
248  // SCH_FIELD's implicitly created copy constructor is called in here
249  AddField( field );
250  }
251 
252  m_prefix = wxString( wxT( "U" ) );
253 }
254 
255 
257 {
258  return new SCH_COMPONENT( *this );
259 }
260 
261 
262 void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, PART_LIBS* aLibs )
263 {
264  if( m_lib_id != aLibId )
265  {
266  m_lib_id = aLibId;
267  SetModified();
268 
269  if( aLibs )
270  Resolve( aLibs );
271  else
272  m_part.reset();
273  }
274 }
275 
276 
277 void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aSymLibTable )
278 {
279  if( m_lib_id != aLibId )
280  {
281  wxCHECK_RET( aSymLibTable, "No symbol library table provided." );
282 
283  m_lib_id = aLibId;
284  SetModified();
285 
286  LIB_ALIAS* alias = aSymLibTable->LoadSymbol( m_lib_id.GetLibNickname(),
288 
289  if( alias && alias->GetPart() )
290  m_part = alias->GetPart()->SharedPtr();
291  else
292  m_part.reset();
293  }
294 }
295 
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->GetDescription();
310  }
311 
312  return wxEmptyString;
313 }
314 
320 {
321  if( PART_SPTR part = m_part.lock() )
322  {
323  LIB_ALIAS* alias = part->GetAlias( GetLibId().GetLibItemName() );
324 
325  if( !alias )
326  return wxEmptyString;
327 
328  return alias->GetDocFileName();
329  }
330 
331  return wxEmptyString;
332 }
333 
335 {
336  // I've never been happy that the actual individual PART_LIB is left up to
337  // flimsy search path ordering. None-the-less find a part based on that design:
338  if( LIB_PART* part = aLibs->FindLibPart( m_lib_id ) )
339  {
340  m_part = part->SharedPtr();
341  return true;
342  }
343 
344  return false;
345 }
346 
347 // Helper sort function, used in SCH_COMPONENT::ResolveAll, to sort
348 // sch component by lib_id
349 static bool sort_by_libid( const SCH_COMPONENT* ref, SCH_COMPONENT* cmp )
350 {
351  return ref->GetLibId() < cmp->GetLibId();
352 }
353 
355  const SCH_COLLECTOR& aComponents, PART_LIBS* aLibs )
356 {
357  // Usually, many components use the same part lib.
358  // to avoid too long calculation time the list of components is grouped
359  // and once the lib part is found for one member of a group, it is also
360  // set for all other members of this group
361  std::vector<SCH_COMPONENT*> cmp_list;
362 
363  // build the cmp list.
364  for( int i = 0; i < aComponents.GetCount(); ++i )
365  {
366  SCH_COMPONENT* cmp = dynamic_cast<SCH_COMPONENT*>( aComponents[i] );
367  wxASSERT( cmp );
368 
369  if( cmp ) // cmp == NULL should not occur.
370  cmp_list.push_back( cmp );
371  }
372 
373  // sort it by lib part. Cmp will be grouped by same lib part.
374  std::sort( cmp_list.begin(), cmp_list.end(), sort_by_libid );
375 
376  LIB_ID curr_libid;
377 
378  for( unsigned ii = 0; ii < cmp_list.size (); ++ii )
379  {
380  SCH_COMPONENT* cmp = cmp_list[ii];
381  curr_libid = cmp->m_lib_id;
382  cmp->Resolve( aLibs );
383 
384  // Propagate the m_part pointer to other members using the same lib_id
385  for( unsigned jj = ii+1; jj < cmp_list.size (); ++jj )
386  {
387  SCH_COMPONENT* next_cmp = cmp_list[jj];
388 
389  if( curr_libid != next_cmp->m_lib_id )
390  break;
391 
392  next_cmp->m_part = cmp->m_part;
393  ii = jj;
394  }
395  }
396 }
397 
398 
399 void SCH_COMPONENT::SetUnit( int aUnit )
400 {
401  if( m_unit != aUnit )
402  {
403  m_unit = aUnit;
404  SetModified();
405  }
406 }
407 
408 void SCH_COMPONENT::UpdateUnit( int aUnit )
409 {
410  m_unit = aUnit;
411 }
412 
413 
414 void SCH_COMPONENT::SetConvert( int aConvert )
415 {
416  if( m_convert != aConvert )
417  {
418  m_convert = aConvert;
419  SetModified();
420  }
421 }
422 
423 
424 void SCH_COMPONENT::SetTransform( const TRANSFORM& aTransform )
425 {
426  if( m_transform != aTransform )
427  {
428  m_transform = aTransform;
429  SetModified();
430  }
431 }
432 
433 
435 {
436  if( PART_SPTR part = m_part.lock() )
437  {
438  return part->GetUnitCount();
439  }
440 
441  return 0;
442 }
443 
444 
445 void SCH_COMPONENT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset,
446  GR_DRAWMODE aDrawMode, COLOR4D aColor,
447  bool aDrawPinText )
448 {
449  auto opts = PART_DRAW_OPTIONS::Default();
450  opts.draw_mode = aDrawMode;
451  opts.color = aColor;
452  opts.transform = m_transform;
453  opts.show_pin_text = aDrawPinText;
454  opts.draw_visible_fields = false;
455  opts.draw_hidden_fields = false;
456 
457  if( PART_SPTR part = m_part.lock() )
458  {
459  // Draw pin targets if part is being dragged
460  bool dragging = aPanel->GetScreen()->GetCurItem() == this && aPanel->IsMouseCaptured();
461 
462  if( !dragging )
463  {
464  opts.dangling = m_isDangling;
465  }
466 
467  part->Draw( aPanel, aDC, m_Pos + aOffset, m_unit, m_convert, opts );
468  }
469  else // Use dummy() part if the actual cannot be found.
470  {
471  dummy()->Draw( aPanel, aDC, m_Pos + aOffset, 0, 0, opts );
472  }
473 
474  SCH_FIELD* field = GetField( REFERENCE );
475 
476  if( field->IsVisible() && !field->IsMoving() )
477  {
478  field->Draw( aPanel, aDC, aOffset, aDrawMode );
479  }
480 
481  for( int ii = VALUE; ii < GetFieldCount(); ii++ )
482  {
483  field = GetField( ii );
484 
485  if( field->IsMoving() )
486  continue;
487 
488  field->Draw( aPanel, aDC, aOffset, aDrawMode );
489  }
490 
491 #if 0
492  // Only for testing purposes, draw the component bounding box
493  {
495  GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN );
496 #if 1
497  if( GetField( REFERENCE )->IsVisible() )
498  {
499  boundingBox = GetField( REFERENCE )->GetBoundingBox();
500  GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN );
501  }
502 
503  if( GetField( VALUE )->IsVisible() )
504  {
505  boundingBox = GetField( VALUE )->GetBoundingBox();
506  GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN );
507  }
508 #endif
509  }
510 #endif
511 }
512 
513 
514 void SCH_COMPONENT::AddHierarchicalReference( const wxString& aPath,
515  const wxString& aRef,
516  int aMulti )
517 {
518  wxString h_path, h_ref;
519  wxStringTokenizer tokenizer;
520  wxString separators( wxT( " " ) );
521 
522  // Search for an existing path and remove it if found (should not occur)
523  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
524  {
525  tokenizer.SetString( m_PathsAndReferences[ii], separators );
526  h_path = tokenizer.GetNextToken();
527 
528  if( h_path.Cmp( aPath ) == 0 )
529  {
530  m_PathsAndReferences.RemoveAt( ii );
531  ii--;
532  }
533  }
534 
535  h_ref = aPath + wxT( " " ) + aRef;
536  h_ref << wxT( " " ) << aMulti;
537  m_PathsAndReferences.Add( h_ref );
538 }
539 
540 
541 wxString SCH_COMPONENT::GetPath( const SCH_SHEET_PATH* sheet ) const
542 {
543  wxCHECK_MSG( sheet != NULL, wxEmptyString,
544  wxT( "Cannot get component path with invalid sheet object." ) );
545 
546  wxString str;
547 
548  str.Printf( wxT( "%8.8lX" ), (long unsigned) m_TimeStamp );
549  return sheet->Path() + str;
550 }
551 
552 
553 const wxString SCH_COMPONENT::GetRef( const SCH_SHEET_PATH* sheet )
554 {
555  wxString path = GetPath( sheet );
556  wxString h_path, h_ref;
557  wxStringTokenizer tokenizer;
558  wxString separators( wxT( " " ) );
559 
560  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
561  {
562  tokenizer.SetString( m_PathsAndReferences[ii], separators );
563  h_path = tokenizer.GetNextToken();
564 
565  if( h_path.Cmp( path ) == 0 )
566  {
567  h_ref = tokenizer.GetNextToken();
568 
569  /* printf( "GetRef hpath: %s\n",
570  * TO_UTF8( m_PathsAndReferences[ii] ) ); */
571  return h_ref;
572  }
573  }
574 
575  // if it was not found in m_Paths array, then see if it is in
576  // m_Field[REFERENCE] -- if so, use this as a default for this path.
577  // this will happen if we load a version 1 schematic file.
578  // it will also mean that multiple instances of the same sheet by default
579  // all have the same component references, but perhaps this is best.
580  if( !GetField( REFERENCE )->GetText().IsEmpty() )
581  {
582  SetRef( sheet, GetField( REFERENCE )->GetText() );
583  return GetField( REFERENCE )->GetText();
584  }
585 
586  return m_prefix;
587 }
588 
589 
590 /* Function IsReferenceStringValid (static function)
591  * Tests for an acceptable reference string
592  * An acceptable reference string must support unannotation
593  * i.e starts by letter
594  * returns true if OK
595  */
596 bool SCH_COMPONENT::IsReferenceStringValid( const wxString& aReferenceString )
597 {
598  wxString text = aReferenceString;
599  bool ok = true;
600 
601  // Try to unannotate this reference
602  while( !text.IsEmpty() && ( text.Last() == '?' || isdigit( text.Last() ) ) )
603  text.RemoveLast();
604 
605  if( text.IsEmpty() )
606  ok = false;
607 
608  // Add here other constraints
609  // Currently:no other constraint
610 
611  return ok;
612 }
613 
614 
615 void SCH_COMPONENT::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref )
616 {
617  wxString path = GetPath( sheet );
618 
619  bool notInArray = true;
620 
621  wxString h_path, h_ref;
622  wxStringTokenizer tokenizer;
623  wxString separators( wxT( " " ) );
624 
625  // check to see if it is already there before inserting it
626  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
627  {
628  tokenizer.SetString( m_PathsAndReferences[ii], separators );
629  h_path = tokenizer.GetNextToken();
630 
631  if( h_path.Cmp( path ) == 0 )
632  {
633  // just update the reference text, not the timestamp.
634  h_ref = h_path + wxT( " " ) + ref;
635  h_ref += wxT( " " );
636  tokenizer.GetNextToken(); // Skip old reference
637  h_ref += tokenizer.GetNextToken(); // Add part selection
638 
639  // Add the part selection
640  m_PathsAndReferences[ii] = h_ref;
641  notInArray = false;
642  }
643  }
644 
645  if( notInArray )
646  AddHierarchicalReference( path, ref, m_unit );
647 
648  SCH_FIELD* rf = GetField( REFERENCE );
649 
650  if( rf->GetText().IsEmpty()
651  || ( abs( rf->GetTextPos().x - m_Pos.x ) +
652  abs( rf->GetTextPos().y - m_Pos.y ) > 10000 ) )
653  {
654  // move it to a reasonable position
655  rf->SetTextPos( m_Pos + wxPoint( 50, 50 ) );
656  }
657 
658  rf->SetText( ref ); // for drawing.
659 
660  // Reinit the m_prefix member if needed
661  wxString prefix = ref;
662 
663  if( IsReferenceStringValid( prefix ) )
664  {
665  while( prefix.Last() == '?' || isdigit( prefix.Last() ) )
666  prefix.RemoveLast();
667  }
668  else
669  {
670  prefix = wxT( "U" ); // Set to default ref prefix
671  }
672 
673  if( m_prefix != prefix )
674  m_prefix = prefix;
675 }
676 
677 
678 void SCH_COMPONENT::SetTimeStamp( time_t aNewTimeStamp )
679 {
680  wxString string_timestamp, string_oldtimestamp;
681 
682  string_timestamp.Printf( wxT( "%08lX" ), (long unsigned) aNewTimeStamp );
683  string_oldtimestamp.Printf( wxT( "%08lX" ), (long unsigned) m_TimeStamp );
684  EDA_ITEM::SetTimeStamp( aNewTimeStamp );
685 
686  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
687  {
688  m_PathsAndReferences[ii].Replace( string_oldtimestamp.GetData(),
689  string_timestamp.GetData() );
690  }
691 }
692 
693 
695 {
696  wxString path = GetPath( aSheet );
697  wxString h_path, h_multi;
698  wxStringTokenizer tokenizer;
699  wxString separators( wxT( " " ) );
700 
701  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
702  {
703  tokenizer.SetString( m_PathsAndReferences[ii], separators );
704  h_path = tokenizer.GetNextToken();
705 
706  if( h_path.Cmp( path ) == 0 )
707  {
708  tokenizer.GetNextToken(); // Skip reference
709  h_multi = tokenizer.GetNextToken();
710  long imulti = 1;
711  h_multi.ToLong( &imulti );
712  return imulti;
713  }
714  }
715 
716  // if it was not found in m_Paths array, then use m_unit.
717  // this will happen if we load a version 1 schematic file.
718  return m_unit;
719 }
720 
721 
722 void SCH_COMPONENT::SetUnitSelection( SCH_SHEET_PATH* aSheet, int aUnitSelection )
723 {
724  wxString path = GetPath( aSheet );
725 
726  bool notInArray = true;
727 
728  wxString h_path, h_ref;
729  wxStringTokenizer tokenizer;
730  wxString separators( wxT( " " ) );
731 
732  //check to see if it is already there before inserting it
733  for( unsigned ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
734  {
735  tokenizer.SetString( m_PathsAndReferences[ii], separators );
736  h_path = tokenizer.GetNextToken();
737 
738  if( h_path.Cmp( path ) == 0 )
739  {
740  //just update the unit selection.
741  h_ref = h_path + wxT( " " );
742  h_ref += tokenizer.GetNextToken(); // Add reference
743  h_ref += wxT( " " );
744  h_ref << aUnitSelection; // Add part selection
745 
746  // Ann the part selection
747  m_PathsAndReferences[ii] = h_ref;
748  notInArray = false;
749  }
750  }
751 
752  if( notInArray )
753  AddHierarchicalReference( path, m_prefix, aUnitSelection );
754 }
755 
756 
757 SCH_FIELD* SCH_COMPONENT::GetField( int aFieldNdx ) const
758 {
759  const SCH_FIELD* field;
760 
761  if( (unsigned) aFieldNdx < m_Fields.size() )
762  field = &m_Fields[aFieldNdx];
763  else
764  field = NULL;
765 
766  wxASSERT( field );
767 
768  // use cast to remove const-ness
769  return (SCH_FIELD*) field;
770 }
771 
772 wxString SCH_COMPONENT::GetFieldText( wxString aFieldName, bool aIncludeDefaultFields ) const
773 {
774  // Field name for comparison
775  wxString cmpFieldName;
776 
777  if( aIncludeDefaultFields )
778  {
779 
780  // Default field names
781  for ( unsigned int i=0; i<MANDATORY_FIELDS; i++)
782  {
783  cmpFieldName = TEMPLATE_FIELDNAME::GetDefaultFieldName( i );
784 
785  if( cmpFieldName.Cmp( aFieldName ) == 0 )
786  {
787  return m_Fields[i].GetText();
788  }
789  }
790  }
791 
792  // Search custom fields
793  for( unsigned int ii=MANDATORY_FIELDS; ii<m_Fields.size(); ii++ )
794  {
795  cmpFieldName = m_Fields[ii].GetName();
796 
797  if( cmpFieldName.Cmp( aFieldName ) == 0 )
798  {
799  return m_Fields[ii].GetText();
800  }
801  }
802 
803  return wxEmptyString;
804 }
805 
806 
807 void SCH_COMPONENT::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
808 {
809  for( SCH_FIELD& each_field : m_Fields )
810  {
811  if( !aVisibleOnly || ( each_field.IsVisible() && !each_field.IsVoid() ) )
812  aVector.push_back( &each_field );
813  }
814 }
815 
816 
818 {
819  int newNdx = m_Fields.size();
820 
821  m_Fields.push_back( aField );
822  return &m_Fields[newNdx];
823 }
824 
825 /*
826  * Find and return compnent field with the given name
827  * @aFieldName is the name of the field to search for
828  * @aIncludeDefaultFields excludes default fields from search if set to false
829  */
830 SCH_FIELD* SCH_COMPONENT::FindField( const wxString& aFieldName, bool aIncludeDefaultFields )
831 {
832  unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
833 
834  for( unsigned i = start; i<m_Fields.size(); ++i )
835  {
836  if( aFieldName == m_Fields[i].GetName( false ) )
837  {
838  return &m_Fields[i];
839  }
840  }
841 
842  return NULL;
843 }
844 
845 
846 LIB_PIN* SCH_COMPONENT::GetPin( const wxString& number )
847 {
848  if( PART_SPTR part = m_part.lock() )
849  {
850  return part->GetPin( number, m_unit, m_convert );
851  }
852  return NULL;
853 }
854 
855 
856 void SCH_COMPONENT::GetPins( std::vector<LIB_PIN*>& aPinsList )
857 {
858  if( PART_SPTR part = m_part.lock() )
859  {
860  part->GetPins( aPinsList, m_unit, m_convert );
861  }
862  else
863  wxFAIL_MSG( "Could not obtain PART_SPTR lock" );
864 }
865 
866 
868 {
869  wxCHECK_RET( (aItem != NULL) && (aItem->Type() == SCH_COMPONENT_T),
870  wxT( "Cannot swap data with invalid component." ) );
871 
872  SCH_COMPONENT* component = (SCH_COMPONENT*) aItem;
873 
874  std::swap( m_lib_id, component->m_lib_id );
875  std::swap( m_part, component->m_part );
876  std::swap( m_Pos, component->m_Pos );
877  std::swap( m_unit, component->m_unit );
878  std::swap( m_convert, component->m_convert );
879 
880  TRANSFORM tmp = m_transform;
881 
882  m_transform = component->m_transform;
883  component->m_transform = tmp;
884 
885  m_Fields.swap( component->m_Fields ); // std::vector's swap()
886 
887  // Reparent items after copying data
888  // (after swap(), m_Parent member does not point to the right parent):
889  for( int ii = 0; ii < component->GetFieldCount(); ++ii )
890  {
891  component->GetField( ii )->SetParent( component );
892  }
893 
894  for( int ii = 0; ii < GetFieldCount(); ++ii )
895  {
896  GetField( ii )->SetParent( this );
897  }
898 
899  std::swap( m_PathsAndReferences, component->m_PathsAndReferences );
900 }
901 
902 
904 {
905  bool keepMulti = false;
906  wxArrayString reference_fields;
907 
908  static const wxChar separators[] = wxT( " " );
909 
910  PART_SPTR part = m_part.lock();
911 
912  if( part && part->UnitsLocked() )
913  keepMulti = true;
914 
915  // Build a reference with no annotation,
916  // i.e. a reference ended by only one '?'
917  wxString defRef = m_prefix;
918 
919  if( IsReferenceStringValid( defRef ) )
920  {
921  while( defRef.Last() == '?' )
922  defRef.RemoveLast();
923  }
924  else
925  { // This is a malformed reference: reinit this reference
926  m_prefix = defRef = wxT("U"); // Set to default ref prefix
927  }
928 
929  defRef.Append( wxT( "?" ) );
930 
931  wxString multi = wxT( "1" );
932 
933  // For components with units locked,
934  // we cannot remove all annotations: part selection must be kept
935  // For all components: if aSheetPath is not NULL,
936  // remove annotation only for the given path
937  if( keepMulti || aSheetPath )
938  {
939  wxString NewHref;
940  wxString path;
941 
942  if( aSheetPath )
943  path = GetPath( aSheetPath );
944 
945  for( unsigned int ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
946  {
947  // Break hierarchical reference in path, ref and multi selection:
948  reference_fields = wxStringTokenize( m_PathsAndReferences[ii], separators );
949 
950  if( aSheetPath == NULL || reference_fields[0].Cmp( path ) == 0 )
951  {
952  if( keepMulti ) // Get and keep part selection
953  multi = reference_fields[2];
954 
955  NewHref = reference_fields[0];
956  NewHref << wxT( " " ) << defRef << wxT( " " ) << multi;
957  m_PathsAndReferences[ii] = NewHref;
958  }
959  }
960  }
961  else
962  {
963  // Clear reference strings, but does not free memory because a new annotation
964  // will reuse it
965  m_PathsAndReferences.Empty();
966  m_unit = 1;
967  }
968 
969  // These 2 changes do not work in complex hierarchy.
970  // When a clear annotation is made, the calling function must call a
971  // UpdateAllScreenReferences for the active sheet.
972  // But this call cannot made here.
973  m_Fields[REFERENCE].SetText( defRef ); //for drawing.
974 
975  SetModified();
976 }
977 
978 
979 void SCH_COMPONENT::SetOrientation( int aOrientation )
980 {
981  TRANSFORM temp = TRANSFORM();
982  bool transform = false;
983 
984  switch( aOrientation )
985  {
986  case CMP_ORIENT_0:
987  case CMP_NORMAL: // default transform matrix
988  m_transform.x1 = 1;
989  m_transform.y2 = -1;
991  break;
992 
993  case CMP_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation)
994  temp.x1 = temp.y2 = 0;
995  temp.y1 = 1;
996  temp.x2 = -1;
997  transform = true;
998  break;
999 
1000  case CMP_ROTATE_CLOCKWISE: // Rotate - (incremental rotation)
1001  temp.x1 = temp.y2 = 0;
1002  temp.y1 = -1;
1003  temp.x2 = 1;
1004  transform = true;
1005  break;
1006 
1007  case CMP_MIRROR_Y: // Mirror Y (incremental rotation)
1008  temp.x1 = -1;
1009  temp.y2 = 1;
1010  temp.y1 = temp.x2 = 0;
1011  transform = true;
1012  break;
1013 
1014  case CMP_MIRROR_X: // Mirror X (incremental rotation)
1015  temp.x1 = 1;
1016  temp.y2 = -1;
1017  temp.y1 = temp.x2 = 0;
1018  transform = true;
1019  break;
1020 
1021  case CMP_ORIENT_90:
1024  break;
1025 
1026  case CMP_ORIENT_180:
1030  break;
1031 
1032  case CMP_ORIENT_270:
1035  break;
1036 
1037  case ( CMP_ORIENT_0 + CMP_MIRROR_X ):
1040  break;
1041 
1042  case ( CMP_ORIENT_0 + CMP_MIRROR_Y ):
1045  break;
1046 
1047  case ( CMP_ORIENT_90 + CMP_MIRROR_X ):
1050  break;
1051 
1052  case ( CMP_ORIENT_90 + CMP_MIRROR_Y ):
1055  break;
1056 
1057  case ( CMP_ORIENT_180 + CMP_MIRROR_X ):
1060  break;
1061 
1062  case ( CMP_ORIENT_180 + CMP_MIRROR_Y ):
1065  break;
1066 
1067  case ( CMP_ORIENT_270 + CMP_MIRROR_X ):
1070  break;
1071 
1072  case ( CMP_ORIENT_270 + CMP_MIRROR_Y ):
1075  break;
1076 
1077  default:
1078  transform = false;
1079  wxMessageBox( wxT( "SetRotateMiroir() error: ill value" ) );
1080  break;
1081  }
1082 
1083  if( transform )
1084  {
1085  /* The new matrix transform is the old matrix transform modified by the
1086  * requested transformation, which is the temp transform (rot,
1087  * mirror ..) in order to have (in term of matrix transform):
1088  * transform coord = new_m_transform * coord
1089  * where transform coord is the coord modified by new_m_transform from
1090  * the initial value coord.
1091  * new_m_transform is computed (from old_m_transform and temp) to
1092  * have:
1093  * transform coord = old_m_transform * temp
1094  */
1095  TRANSFORM newTransform;
1096 
1097  newTransform.x1 = m_transform.x1 * temp.x1 + m_transform.x2 * temp.y1;
1098  newTransform.y1 = m_transform.y1 * temp.x1 + m_transform.y2 * temp.y1;
1099  newTransform.x2 = m_transform.x1 * temp.x2 + m_transform.x2 * temp.y2;
1100  newTransform.y2 = m_transform.y1 * temp.x2 + m_transform.y2 * temp.y2;
1101  m_transform = newTransform;
1102  }
1103 }
1104 
1105 
1107 {
1108  int type_rotate = CMP_ORIENT_0;
1109  TRANSFORM transform;
1110  int ii;
1111 
1112  #define ROTATE_VALUES_COUNT 12
1113 
1114  // list of all possibilities, but only the first 8 are actually used
1115  int rotate_value[ROTATE_VALUES_COUNT] =
1116  {
1122  CMP_MIRROR_Y + CMP_ORIENT_180, CMP_MIRROR_Y + CMP_ORIENT_270
1123  };
1124 
1125  // Try to find the current transform option:
1126  transform = m_transform;
1127 
1128  for( ii = 0; ii < ROTATE_VALUES_COUNT; ii++ )
1129  {
1130  type_rotate = rotate_value[ii];
1131  SetOrientation( type_rotate );
1132 
1133  if( transform == m_transform )
1134  return type_rotate;
1135  }
1136 
1137  // Error: orientation not found in list (should not happen)
1138  wxMessageBox( wxT( "Component orientation matrix internal error" ) );
1139  m_transform = transform;
1140 
1141  return CMP_NORMAL;
1142 }
1143 
1144 
1146 {
1147  return m_transform.TransformCoordinate( aPoint );
1148 }
1149 
1150 
1151 #if defined(DEBUG)
1152 
1153 void SCH_COMPONENT::Show( int nestLevel, std::ostream& os ) const
1154 {
1155  // for now, make it look like XML:
1156  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1157  << " ref=\"" << TO_UTF8( GetField( 0 )->GetName() )
1158  << '"' << " chipName=\""
1159  << GetLibId().Format() << '"' << m_Pos
1160  << " layer=\"" << m_Layer
1161  << '"' << ">\n";
1162 
1163  // skip the reference, it's been output already.
1164  for( int i = 1; i < GetFieldCount(); ++i )
1165  {
1166  wxString value = GetField( i )->GetText();
1167 
1168  if( !value.IsEmpty() )
1169  {
1170  NestedSpace( nestLevel + 1, os ) << "<field" << " name=\""
1171  << TO_UTF8( GetField( i )->GetName() )
1172  << '"' << " value=\""
1173  << TO_UTF8( value ) << "\"/>\n";
1174  }
1175  }
1176 
1177  NestedSpace( nestLevel, os ) << "</" << TO_UTF8( GetClass().Lower() ) << ">\n";
1178 }
1179 
1180 #endif
1181 
1182 
1183 bool SCH_COMPONENT::Save( FILE* f ) const
1184 {
1185  std::string name1;
1186  std::string name2;
1187  wxArrayString reference_fields;
1188 
1189  static wxString delimiters( wxT( " " ) );
1190 
1191  // this is redundant with the AR entries below, but it makes the
1192  // files backwards-compatible.
1193  if( m_PathsAndReferences.GetCount() > 0 )
1194  {
1195  reference_fields = wxStringTokenize( m_PathsAndReferences[0], delimiters );
1196 
1197  name1 = toUTFTildaText( reference_fields[1] );
1198  }
1199  else
1200  {
1201  if( GetField( REFERENCE )->GetText().IsEmpty() )
1202  name1 = toUTFTildaText( m_prefix );
1203  else
1204  name1 = toUTFTildaText( GetField( REFERENCE )->GetText() );
1205  }
1206 
1207  wxString part_name = FROM_UTF8( GetLibId().GetLibItemName() );
1208 
1209  if( part_name.size() )
1210  {
1211  name2 = toUTFTildaText( part_name );
1212  }
1213  else
1214  {
1215  name2 = NULL_STRING;
1216  }
1217 
1218  if( fprintf( f, "$Comp\n" ) == EOF )
1219  return false;
1220 
1221  if( fprintf( f, "L %s %s\n", name2.c_str(), name1.c_str() ) == EOF )
1222  return false;
1223 
1224  // Generate unit number, convert and time stamp
1225  if( fprintf( f, "U %d %d %8.8lX\n", m_unit, m_convert, (unsigned long)m_TimeStamp ) == EOF )
1226  return false;
1227 
1228  // Save the position
1229  if( fprintf( f, "P %d %d\n", m_Pos.x, m_Pos.y ) == EOF )
1230  return false;
1231 
1232  /* If this is a complex hierarchy; save hierarchical references.
1233  * but for simple hierarchies it is not necessary.
1234  * the reference inf is already saved
1235  * this is useful for old Eeschema version compatibility
1236  */
1237  if( m_PathsAndReferences.GetCount() > 1 )
1238  {
1239  for( unsigned int ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
1240  {
1241  /*format:
1242  * AR Path="/140/2" Ref="C99" Part="1"
1243  * where 140 is the uid of the containing sheet
1244  * and 2 is the timestamp of this component.
1245  * (timestamps are actually 8 hex chars)
1246  * Ref is the conventional component reference for this 'path'
1247  * Part is the conventional component part selection for this 'path'
1248  */
1249  reference_fields = wxStringTokenize( m_PathsAndReferences[ii], delimiters );
1250 
1251  if( fprintf( f, "AR Path=\"%s\" Ref=\"%s\" Part=\"%s\" \n",
1252  TO_UTF8( reference_fields[0] ),
1253  TO_UTF8( reference_fields[1] ),
1254  TO_UTF8( reference_fields[2] ) ) == EOF )
1255  return false;
1256  }
1257  }
1258 
1259  // update the ugly field index, which I would like to see go away someday soon.
1260  for( unsigned i = 0; i<m_Fields.size(); ++i )
1261  {
1262  SCH_FIELD* fld = GetField( i );
1263  fld->SetId( i ); // we don't need field Ids, please be gone.
1264  }
1265 
1266  // Fixed fields:
1267  // Save mandatory fields even if they are blank,
1268  // because the visibility, size and orientation are set from libary editor.
1269  for( unsigned i = 0; i<MANDATORY_FIELDS; ++i )
1270  {
1271  SCH_FIELD* fld = GetField( i );
1272  if( !fld->Save( f ) )
1273  return false;
1274  }
1275 
1276  // User defined fields:
1277  // The *policy* about which user defined fields are part of a symbol is now
1278  // only in the dialog editors. No policy should be enforced here, simply
1279  // save all the user defined fields, they are present because a dialog editor
1280  // thought they should be. If you disagree, go fix the dialog editors.
1281  for( unsigned i = MANDATORY_FIELDS; i<m_Fields.size(); ++i )
1282  {
1283  SCH_FIELD* fld = GetField( i );
1284 
1285  if( !fld->Save( f ) )
1286  return false;
1287  }
1288 
1289  // Unit number, position, box ( old standard )
1290  if( fprintf( f, "\t%-4d %-4d %-4d\n", m_unit, m_Pos.x, m_Pos.y ) == EOF )
1291  return false;
1292 
1293  if( fprintf( f, "\t%-4d %-4d %-4d %-4d\n",
1295  return false;
1296 
1297  if( fprintf( f, "$EndComp\n" ) == EOF )
1298  return false;
1299 
1300  return true;
1301 }
1302 
1303 
1304 bool SCH_COMPONENT::Load( LINE_READER& aLine, wxString& aErrorMsg )
1305 {
1306  // Remark: avoid using sscanf to read texts entered by user
1307  // which are UTF8 encoded, because sscanf does not work well on Windows
1308  // with some UTF8 values.
1309  char name1[256], char1[256], char2[256], char3[256];
1310  int newfmt = 0;
1311  char* ptcar;
1312  wxString fieldName;
1313  char* line = aLine.Line();
1314  unsigned long timeStamp;
1315 
1316  m_convert = 1;
1317 
1318  if( line[0] == '$' )
1319  {
1320  newfmt = 1;
1321 
1322  if( !(line = aLine.ReadLine()) )
1323  return true;
1324  }
1325 
1326  // Parse the first line of description:
1327  // like "L partname ref" (for instance "L 74LS00 U4"
1328  // They are UTF8 texts, so do not use sscanf
1329 
1330  line += 1;
1331 
1332  if( *line == ' ' )
1333  line++;
1334 
1335  // line points the first parameter
1336  wxString buffer( FROM_UTF8( line ) );
1337  wxStringTokenizer tokenizer( buffer, wxT( " \r\n" ) );
1338 
1339  if( tokenizer.CountTokens() < 2 )
1340  {
1341  aErrorMsg.Printf( wxT( "Eeschema component description error at line %d, aborted" ),
1342  aLine.LineNumber() );
1343  aErrorMsg << wxT( "\n" ) << FROM_UTF8( line );
1344  return false;
1345  }
1346 
1347  wxString partname = tokenizer.NextToken();
1348  partname.Replace( wxT("~"), wxT(" ") ); // all spaces were replaced by ~ in files.
1349 
1350  if( partname != NULL_STRING )
1351  {
1352  m_lib_id.SetLibItemName( TO_UTF8( partname ), false );
1353 
1354  if( !newfmt )
1355  GetField( VALUE )->SetText( partname );
1356  }
1357  else
1358  {
1359  m_lib_id.clear();
1360  GetField( VALUE )->Empty();
1362  GetField( VALUE )->SetVisible( false );
1363  }
1364 
1365  wxString reference = tokenizer.NextToken();
1366  reference.Replace( wxT("~"), wxT(" ") ); // all spaces were replaced by ~ in files.
1367  reference.Trim( true );
1368  reference.Trim( false );
1369 
1370  if( reference != NULL_STRING )
1371  {
1372  wxString prefix = reference;
1373  // Build reference prefix from the actual reference by removing trailing digits
1374  // (Perhaps outdated code, only for very old schematic files)
1375  while( prefix.Length() )
1376  {
1377  if( ( prefix.Last() < '0' || prefix.Last() > '9') && prefix.Last() != '?' )
1378  break;
1379 
1380  prefix.RemoveLast();
1381  }
1382 
1383  // Avoid a prefix containing trailing/leading spaces
1384  prefix.Trim( true );
1385  prefix.Trim( false );
1386 
1387  if( prefix.IsEmpty() )
1388  m_prefix = wxT( "U" );
1389  else
1390  m_prefix = prefix;
1391 
1392  if( !newfmt )
1393  GetField( REFERENCE )->SetText( reference );
1394  }
1395  else
1396  {
1397  GetField( REFERENCE )->SetVisible( false );
1398  }
1399 
1400  /* Parse component description
1401  * These lines begin with:
1402  * "P" = Position
1403  * U = Num Unit and Conversion
1404  * "Fn" = Fields (0 .. n = = number of field)
1405  * "Ar" = Alternate reference in the case of multiple sheets referring to
1406  * one schematic file.
1407  */
1408  for( ; ; )
1409  {
1410  if( !(line = aLine.ReadLine()) )
1411  return false;
1412 
1413  if( line[0] == 'U' )
1414  {
1415  sscanf( line + 1, "%d %d %lX", &m_unit, &m_convert, &timeStamp );
1416  m_TimeStamp = (time_t)timeStamp;
1417  }
1418  else if( line[0] == 'P' )
1419  {
1420  sscanf( line + 1, "%d %d", &m_Pos.x, &m_Pos.y );
1421 
1422  // Set fields position to a default position (that is the
1423  // component position. For existing fields, the real position
1424  // will be set later
1425  for( int i = 0; i<GetFieldCount(); i++ )
1426  {
1427  if( GetField( i )->GetText().IsEmpty() )
1428  GetField( i )->SetTextPos( m_Pos );
1429  }
1430  }
1431  else if( line[0] == 'A' && line[1] == 'R' )
1432  {
1433  /* format:
1434  * AR Path="/9086AF6E/67452AA0" Ref="C99" Part="1"
1435  * where 9086AF6E is the unique timestamp of the containing sheet
1436  * and 67452AA0 is the timestamp of this component.
1437  * C99 is the reference given this path.
1438  */
1439  int ii;
1440  ptcar = line + 2;
1441 
1442  //copy the path.
1443  ii = ReadDelimitedText( name1, ptcar, 255 );
1444  ptcar += ii + 1;
1445  wxString path = FROM_UTF8( name1 );
1446 
1447  // copy the reference
1448  ii = ReadDelimitedText( name1, ptcar, 255 );
1449  ptcar += ii + 1;
1450  wxString ref = FROM_UTF8( name1 );
1451 
1452  // copy the multi, if exists
1453  ii = ReadDelimitedText( name1, ptcar, 255 );
1454 
1455  if( name1[0] == 0 ) // Nothing read, put a default value
1456  sprintf( name1, "%d", m_unit );
1457 
1458  int multi = atoi( name1 );
1459 
1460  if( multi < 0 || multi > 26 )
1461  multi = 1;
1462 
1463  AddHierarchicalReference( path, ref, multi );
1464  GetField( REFERENCE )->SetText( ref );
1465  }
1466  else if( line[0] == 'F' )
1467  {
1468  int fieldNdx;
1469 
1470  wxString fieldText;
1473 
1474  ptcar = (char*) aLine;
1475 
1476  while( *ptcar && (*ptcar != '"') )
1477  ptcar++;
1478 
1479  if( *ptcar != '"' )
1480  {
1481  aErrorMsg.Printf( wxT( "Eeschema file library field F at line %d, aborted" ),
1482  aLine.LineNumber() );
1483  return false;
1484  }
1485 
1486  ptcar += ReadDelimitedText( &fieldText, ptcar );
1487 
1488  if( *ptcar == 0 )
1489  {
1490  aErrorMsg.Printf( wxT( "Component field F at line %d, aborted" ),
1491  aLine.LineNumber() );
1492  return false;
1493  }
1494 
1495  fieldNdx = atoi( line + 2 );
1496 
1497  ReadDelimitedText( &fieldName, ptcar );
1498 
1499  if( fieldName.IsEmpty() )
1500  fieldName = TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldNdx );
1501 
1502  if( fieldNdx >= GetFieldCount() )
1503  {
1504  // The first MANDATOR_FIELDS _must_ be constructed within
1505  // the SCH_COMPONENT constructor. This assert is simply here
1506  // to guard against a change in that constructor.
1507  wxASSERT( GetFieldCount() >= MANDATORY_FIELDS );
1508 
1509  // Ignore the _supplied_ fieldNdx. It is not important anymore
1510  // if within the user defined fields region (i.e. >= MANDATORY_FIELDS).
1511  // We freely renumber the index to fit the next available field slot.
1512 
1513  fieldNdx = GetFieldCount(); // new has this index after insertion
1514 
1515  SCH_FIELD field( wxPoint( 0, 0 ),
1516  -1, // field id is not relavant for user defined fields
1517  this, fieldName );
1518 
1519  AddField( field );
1520  }
1521  else
1522  {
1523  GetField( fieldNdx )->SetName( fieldName );
1524  }
1525 
1526  GetField( fieldNdx )->SetText( fieldText );
1527  memset( char3, 0, sizeof(char3) );
1528  int ii, x, y, w, attr;
1529 
1530  if( ( ii = sscanf( ptcar, "%255s %d %d %d %X %255s %255s", char1, &x, &y, &w, &attr,
1531  char2, char3 ) ) < 4 )
1532  {
1533  aErrorMsg.Printf( wxT( "Component Field error line %d, aborted" ),
1534  aLine.LineNumber() );
1535  continue;
1536  }
1537 
1538  GetField( fieldNdx )->SetTextPos( wxPoint( x, y ) );
1539  GetField( fieldNdx )->SetVisible( !attr );
1540 
1541  if( (w == 0 ) || (ii == 4) )
1542  w = GetDefaultTextSize();
1543 
1544  GetField( fieldNdx )->SetTextSize( wxSize( w, w ) );
1545  GetField( fieldNdx )->SetTextAngle( TEXT_ANGLE_HORIZ );
1546 
1547  if( char1[0] == 'V' )
1548  GetField( fieldNdx )->SetTextAngle( TEXT_ANGLE_VERT );
1549 
1550  if( ii >= 7 )
1551  {
1552  if( *char2 == 'L' )
1553  hjustify = GR_TEXT_HJUSTIFY_LEFT;
1554  else if( *char2 == 'R' )
1555  hjustify = GR_TEXT_HJUSTIFY_RIGHT;
1556 
1557  if( char3[0] == 'B' )
1558  vjustify = GR_TEXT_VJUSTIFY_BOTTOM;
1559  else if( char3[0] == 'T' )
1560  vjustify = GR_TEXT_VJUSTIFY_TOP;
1561 
1562  GetField( fieldNdx )->SetItalic( char3[1] == 'I' );
1563  GetField( fieldNdx )->SetBold( char3[2] == 'B' );
1564  GetField( fieldNdx )->SetHorizJustify( hjustify );
1565  GetField( fieldNdx )->SetVertJustify( vjustify );
1566  }
1567 
1568  if( fieldNdx == REFERENCE )
1569  if( GetField( fieldNdx )->GetText()[0] == '#' )
1570  GetField( fieldNdx )->SetVisible( false );
1571  }
1572  else
1573  {
1574  break;
1575  }
1576  }
1577 
1578  if( sscanf( line, "%d %d %d", &m_unit, &m_Pos.x, &m_Pos.y ) != 3 )
1579  {
1580  aErrorMsg.Printf( wxT( "Component unit & pos error at line %d, aborted" ),
1581  aLine.LineNumber() );
1582  return false;
1583  }
1584 
1585  if( !(line = aLine.ReadLine()) ||
1586  sscanf( line, "%d %d %d %d",
1587  &m_transform.x1,
1588  &m_transform.y1,
1589  &m_transform.x2,
1590  &m_transform.y2 ) != 4 )
1591  {
1592  aErrorMsg.Printf( wxT( "Component orient error at line %d, aborted" ),
1593  aLine.LineNumber() );
1594  return false;
1595  }
1596 
1597  if( newfmt )
1598  {
1599  if( !(line = aLine.ReadLine()) )
1600  return false;
1601 
1602  if( strncasecmp( "$End", line, 4 ) != 0 )
1603  {
1604  aErrorMsg.Printf( wxT( "Component End expected at line %d, aborted" ),
1605  aLine.LineNumber() );
1606  return false;
1607  }
1608  }
1609 
1610  // ensure flags (mainly used in edit) are cleared.
1611  // some changes have set the modified flag
1612  m_Flags = 0;
1613 
1614  return true;
1615 }
1616 
1617 
1619 {
1620  EDA_RECT bBox;
1621 
1622  if( PART_SPTR part = m_part.lock() )
1623  {
1624  bBox = part->GetBodyBoundingBox( m_unit, m_convert );
1625  }
1626  else
1627  {
1628  bBox = dummy()->GetBodyBoundingBox( m_unit, m_convert );
1629  }
1630 
1631  int x0 = bBox.GetX();
1632  int xm = bBox.GetRight();
1633 
1634  // We must reverse Y values, because matrix orientation
1635  // suppose Y axis normal for the library items coordinates,
1636  // m_transform reverse Y values, but bBox is already reversed!
1637  int y0 = -bBox.GetY();
1638  int ym = -bBox.GetBottom();
1639 
1640  // Compute the real Boundary box (rotated, mirrored ...)
1641  int x1 = m_transform.x1 * x0 + m_transform.y1 * y0;
1642  int y1 = m_transform.x2 * x0 + m_transform.y2 * y0;
1643  int x2 = m_transform.x1 * xm + m_transform.y1 * ym;
1644  int y2 = m_transform.x2 * xm + m_transform.y2 * ym;
1645 
1646  // H and W must be > 0:
1647  if( x2 < x1 )
1648  std::swap( x2, x1 );
1649 
1650  if( y2 < y1 )
1651  std::swap( y2, y1 );
1652 
1653  bBox.SetX( x1 );
1654  bBox.SetY( y1 );
1655  bBox.SetWidth( x2 - x1 );
1656  bBox.SetHeight( y2 - y1 );
1657 
1658  bBox.Offset( m_Pos );
1659  return bBox;
1660 }
1661 
1662 
1664 {
1665  EDA_RECT bbox = GetBodyBoundingBox();
1666 
1667  for( size_t i = 0; i < m_Fields.size(); i++ )
1668  {
1669  bbox.Merge( m_Fields[i].GetBoundingBox() );
1670  }
1671 
1672  return bbox;
1673 }
1674 
1675 
1677 {
1678  // part and alias can differ if alias is not the root
1679  if( PART_SPTR part = m_part.lock() )
1680  {
1681  LIB_ALIAS* alias = part->GetAlias( FROM_UTF8( GetLibId().GetLibItemName() ) );
1682 
1683  if( !alias )
1684  return;
1685 
1686  if( m_currentSheetPath )
1687  aList.push_back( MSG_PANEL_ITEM( _( "Reference" ),
1689  DARKCYAN ) );
1690 
1691  wxString msg = part->IsPower() ? _( "Power symbol" ) : _( "Value" );
1692 
1693  aList.push_back( MSG_PANEL_ITEM( msg, GetField( VALUE )->GetShownText(), DARKCYAN ) );
1694 
1695  // Display component reference in library and library
1696  aList.push_back( MSG_PANEL_ITEM( _( "Component" ), FROM_UTF8( GetLibId().GetLibItemName() ),
1697  BROWN ) );
1698 
1699  if( alias->GetName() != part->GetName() )
1700  aList.push_back( MSG_PANEL_ITEM( _( "Alias of" ), part->GetName(), BROWN ) );
1701 
1702  aList.push_back( MSG_PANEL_ITEM( _( "Library" ), alias->GetLibraryName(), BROWN ) );
1703 
1704  // Display the current associated footprint, if exists.
1705  if( !GetField( FOOTPRINT )->IsVoid() )
1706  msg = GetField( FOOTPRINT )->GetShownText();
1707  else
1708  msg = _( "<Unknown>" );
1709 
1710  aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), msg, DARKRED ) );
1711 
1712  // Display description of the component, and keywords found in lib
1713  aList.push_back( MSG_PANEL_ITEM( _( "Description" ), alias->GetDescription(), DARKCYAN ) );
1714  aList.push_back( MSG_PANEL_ITEM( _( "Key Words" ), alias->GetKeyWords(), DARKCYAN ) );
1715  }
1716 }
1717 
1718 
1720 {
1721  return add_component_xpm;
1722 }
1723 
1724 
1725 void SCH_COMPONENT::MirrorY( int aYaxis_position )
1726 {
1727  int dx = m_Pos.x;
1728 
1730  MIRROR( m_Pos.x, aYaxis_position );
1731  dx -= m_Pos.x; // dx,0 is the move vector for this transform
1732 
1733  for( int ii = 0; ii < GetFieldCount(); ii++ )
1734  {
1735  // Move the fields to the new position because the component itself has moved.
1736  wxPoint pos = GetField( ii )->GetTextPos();
1737  pos.x -= dx;
1738  GetField( ii )->SetTextPos( pos );
1739  }
1740 }
1741 
1742 
1743 void SCH_COMPONENT::MirrorX( int aXaxis_position )
1744 {
1745  int dy = m_Pos.y;
1746 
1748  MIRROR( m_Pos.y, aXaxis_position );
1749  dy -= m_Pos.y; // dy,0 is the move vector for this transform
1750 
1751  for( int ii = 0; ii < GetFieldCount(); ii++ )
1752  {
1753  // Move the fields to the new position because the component itself has moved.
1754  wxPoint pos = GetField( ii )->GetTextPos();
1755  pos.y -= dy;
1756  GetField( ii )->SetTextPos( pos );
1757  }
1758 }
1759 
1760 
1762 {
1763  wxPoint prev = m_Pos;
1764 
1765  RotatePoint( &m_Pos, aPosition, 900 );
1766 
1768 
1769  for( int ii = 0; ii < GetFieldCount(); ii++ )
1770  {
1771  // Move the fields to the new position because the component itself has moved.
1772  wxPoint pos = GetField( ii )->GetTextPos();
1773  pos.x -= prev.x - m_Pos.x;
1774  pos.y -= prev.y - m_Pos.y;
1775  GetField( ii )->SetTextPos( pos );
1776  }
1777 }
1778 
1779 
1780 bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData,
1781  wxPoint* aFindLocation )
1782 {
1783  wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() );
1784 
1785  // Components are searchable via the child field and pin item text.
1786  return false;
1787 }
1788 
1789 
1790 void SCH_COMPONENT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1791 {
1792  if( PART_SPTR part = m_part.lock() )
1793  {
1794  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
1795  {
1796  wxASSERT( pin->Type() == LIB_PIN_T );
1797 
1798  if( pin->GetUnit() && m_unit && ( m_unit != pin->GetUnit() ) )
1799  continue;
1800 
1801  if( pin->GetConvert() && m_convert && ( m_convert != pin->GetConvert() ) )
1802  continue;
1803 
1804  DANGLING_END_ITEM item( PIN_END, pin, GetPinPhysicalPosition( pin ) );
1805  aItemList.push_back( item );
1806  }
1807  }
1808 }
1809 
1810 
1811 bool SCH_COMPONENT::IsPinDanglingStateChanged( std::vector<DANGLING_END_ITEM> &aItemList,
1812  LIB_PINS& aLibPins, unsigned aPin )
1813 {
1814  bool previousState;
1815 
1816  if( aPin < m_isDangling.size() )
1817  {
1818  previousState = m_isDangling[aPin];
1819  m_isDangling[aPin] = true;
1820  }
1821  else
1822  {
1823  previousState = true;
1824  m_isDangling.push_back( true );
1825  }
1826 
1827  wxPoint pin_position = GetPinPhysicalPosition( aLibPins[aPin] );
1828 
1829  for( DANGLING_END_ITEM& each_item : aItemList )
1830  {
1831  // Some people like to stack pins on top of each other in a symbol to indicate
1832  // internal connection. While technically connected, it is not particularly useful
1833  // to display them that way, so skip any pins that are in the same symbol as this
1834  // one.
1835  //
1836  // Do not make this exception for hidden pins, because those actually make internal
1837  // connections to a power net.
1838  const LIB_PIN* item_pin = dynamic_cast<const LIB_PIN*>( each_item.GetItem() );
1839 
1840  if( item_pin
1841  && ( !item_pin->IsPowerConnection() || !IsInNetlist() )
1842  && std::find( aLibPins.begin(), aLibPins.end(), item_pin) != aLibPins.end() )
1843  continue;
1844 
1845  switch( each_item.GetType() )
1846  {
1847  case PIN_END:
1848  case LABEL_END:
1849  case SHEET_LABEL_END:
1850  case WIRE_START_END:
1851  case WIRE_END_END:
1852  case NO_CONNECT_END:
1853  case JUNCTION_END:
1854  if( pin_position == each_item.GetPosition() )
1855  m_isDangling[aPin] = false;
1856  break;
1857  default:
1858  break;
1859  }
1860  if( !m_isDangling[aPin] )
1861  break;
1862  }
1863 
1864  return previousState != m_isDangling[aPin];
1865 }
1866 
1867 
1868 bool SCH_COMPONENT::IsDanglingStateChanged( std::vector<DANGLING_END_ITEM>& aItemList )
1869 {
1870  bool changed = false;
1871  LIB_PINS libPins;
1872  if( PART_SPTR part = m_part.lock() )
1873  part->GetPins( libPins, m_unit, m_convert );
1874  for( size_t i = 0; i < libPins.size(); ++i )
1875  {
1876  if( IsPinDanglingStateChanged( aItemList, libPins, i ) )
1877  changed = true;
1878  }
1879  return changed;
1880 }
1881 
1882 
1884 {
1885  for( bool each : m_isDangling )
1886  {
1887  if( each )
1888  return true;
1889  }
1890  return false;
1891 }
1892 
1893 
1895 {
1896  wxCHECK_MSG( Pin != NULL && Pin->Type() == LIB_PIN_T, wxPoint( 0, 0 ),
1897  wxT( "Cannot get physical position of pin." ) );
1898 
1899  return m_transform.TransformCoordinate( Pin->GetPosition() ) + m_Pos;
1900 }
1901 
1902 
1903 bool SCH_COMPONENT::IsSelectStateChanged( const wxRect& aRect )
1904 {
1905  bool previousState = IsSelected();
1906 
1908 
1909  if( aRect.Intersects( boundingBox ) )
1910  SetFlags( SELECTED );
1911  else
1912  ClearFlags( SELECTED );
1913 
1914  return previousState != IsSelected();
1915 }
1916 
1917 
1918 void SCH_COMPONENT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
1919 {
1920  if( PART_SPTR part = m_part.lock() )
1921  {
1922  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
1923  {
1924  wxCHECK_RET( pin->Type() == LIB_PIN_T,
1925  wxT( "GetNextPin() did not return a pin object. Bad programmer!" ) );
1926 
1927  // Skip items not used for this part.
1928  if( m_unit && pin->GetUnit() && ( pin->GetUnit() != m_unit ) )
1929  continue;
1930 
1931  if( m_convert && pin->GetConvert() && ( pin->GetConvert() != m_convert ) )
1932  continue;
1933 
1934  // Calculate the pin position relative to the component position and orientation.
1935  aPoints.push_back( m_transform.TransformCoordinate( pin->GetPosition() ) + m_Pos );
1936  }
1937  }
1938  else
1939  {
1940  wxCHECK_RET( 0,
1941  wxT( "Cannot add connection points to list. Cannot find component <" ) +
1942  FROM_UTF8( GetLibId().GetLibItemName() ) +
1943  wxT( "> in any of the loaded libraries." ) );
1944  }
1945 }
1946 
1947 
1949 {
1950  if( PART_SPTR part = m_part.lock() )
1951  {
1952  // Calculate the position relative to the component.
1953  wxPoint libPosition = aPosition - m_Pos;
1954 
1955  return part->LocateDrawItem( m_unit, m_convert, aType, libPosition, m_transform );
1956  }
1957 
1958  return NULL;
1959 }
1960 
1961 
1963 {
1964  wxString tmp;
1965  tmp.Printf( _( "Component %s, %s" ),
1966  FROM_UTF8( GetLibId().GetLibItemName() ),
1967  GetChars( GetField( REFERENCE )->GetShownText() ) );
1968  return tmp;
1969 }
1970 
1971 
1972 SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
1973  const KICAD_T aFilterTypes[] )
1974 {
1975  KICAD_T stype;
1976 
1977  for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p )
1978  {
1979  // If caller wants to inspect component type or and component children types.
1980  if( stype == Type() )
1981  {
1982  if( SEARCH_QUIT == aInspector( this, aTestData ) )
1983  return SEARCH_QUIT;
1984  }
1985 
1986  switch( stype )
1987  {
1988  case SCH_FIELD_T:
1989  // Test the bounding boxes of fields if they are visible and not empty.
1990  for( int ii = 0; ii < GetFieldCount(); ii++ )
1991  {
1992  if( SEARCH_QUIT == aInspector( GetField( ii ), (void*) this ) )
1993  return SEARCH_QUIT;
1994  }
1995  break;
1996 
1998  if( SEARCH_QUIT == aInspector( GetField( REFERENCE ), (void*) this ) )
1999  return SEARCH_QUIT;
2000  break;
2001 
2003  if( SEARCH_QUIT == aInspector( GetField( VALUE ), (void*) this ) )
2004  return SEARCH_QUIT;
2005  break;
2006 
2008  if( SEARCH_QUIT == aInspector( GetField( FOOTPRINT ), (void*) this ) )
2009  return SEARCH_QUIT;
2010  break;
2011 
2012 
2013  case LIB_PIN_T:
2014  if( PART_SPTR part = m_part.lock() )
2015  {
2016  LIB_PINS pins;
2017 
2018  part->GetPins( pins, m_unit, m_convert );
2019 
2020  for( size_t i = 0; i < pins.size(); i++ )
2021  {
2022  if( SEARCH_QUIT == aInspector( pins[ i ], (void*) this ) )
2023  return SEARCH_QUIT;
2024  }
2025  }
2026  break;
2027 
2028  default:
2029  break;
2030  }
2031  }
2032 
2033  return SEARCH_CONTINUE;
2034 }
2035 
2036 
2038  SCH_SHEET_PATH* aSheetPath )
2039 {
2040  if( PART_SPTR part = m_part.lock() )
2041  {
2042  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
2043  {
2044  wxASSERT( pin->Type() == LIB_PIN_T );
2045 
2046  if( pin->GetUnit() && ( pin->GetUnit() != GetUnitSelection( aSheetPath ) ) )
2047  continue;
2048 
2049  if( pin->GetConvert() && ( pin->GetConvert() != GetConvert() ) )
2050  continue;
2051 
2052  wxPoint pos = GetTransform().TransformCoordinate( pin->GetPosition() ) + m_Pos;
2053 
2054  NETLIST_OBJECT* item = new NETLIST_OBJECT();
2055  item->m_SheetPathInclude = *aSheetPath;
2056  item->m_Comp = (SCH_ITEM*) pin;
2057  item->m_SheetPath = *aSheetPath;
2058  item->m_Type = NET_PIN;
2059  item->m_Link = (SCH_ITEM*) this;
2060  item->m_ElectricalPinType = pin->GetType();
2061  item->m_PinNum = pin->GetNumber();
2062  item->m_Label = pin->GetName();
2063  item->m_Start = item->m_End = pos;
2064 
2065  aNetListItems.push_back( item );
2066 
2067  if( pin->IsPowerConnection() )
2068  {
2069  // There is an associated PIN_LABEL.
2070  item = new NETLIST_OBJECT();
2071  item->m_SheetPathInclude = *aSheetPath;
2072  item->m_Comp = NULL;
2073  item->m_SheetPath = *aSheetPath;
2074  item->m_Type = NET_PINLABEL;
2075  item->m_Label = pin->GetName();
2076  item->m_Start = pos;
2077  item->m_End = item->m_Start;
2078 
2079  aNetListItems.push_back( item );
2080  }
2081  }
2082  }
2083 }
2084 
2085 
2086 bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
2087 {
2088  if( Type() != aItem.Type() )
2089  return Type() < aItem.Type();
2090 
2091  SCH_COMPONENT* component = (SCH_COMPONENT*) &aItem;
2092 
2093  EDA_RECT rect = GetBodyBoundingBox();
2094 
2095  if( rect.GetArea() != component->GetBodyBoundingBox().GetArea() )
2096  return rect.GetArea() < component->GetBodyBoundingBox().GetArea();
2097 
2098  if( m_Pos.x != component->m_Pos.x )
2099  return m_Pos.x < component->m_Pos.x;
2100 
2101  if( m_Pos.y != component->m_Pos.y )
2102  return m_Pos.y < component->m_Pos.y;
2103 
2104  return false;
2105 }
2106 
2107 
2108 bool SCH_COMPONENT::operator==( const SCH_COMPONENT& aComponent ) const
2109 {
2110  if( GetFieldCount() != aComponent.GetFieldCount() )
2111  return false;
2112 
2113  for( int i = VALUE; i < GetFieldCount(); i++ )
2114  {
2115  if( GetField( i )->GetText().Cmp( aComponent.GetField( i )->GetText() ) != 0 )
2116  return false;
2117  }
2118 
2119  return true;
2120 }
2121 
2122 
2123 bool SCH_COMPONENT::operator!=( const SCH_COMPONENT& aComponent ) const
2124 {
2125  return !( *this == aComponent );
2126 }
2127 
2128 
2130 {
2131  wxCHECK_MSG( Type() == aItem.Type(), *this,
2132  wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
2133  GetClass() );
2134 
2135  if( &aItem != this )
2136  {
2137  SCH_ITEM::operator=( aItem );
2138 
2139  SCH_COMPONENT* c = (SCH_COMPONENT*) &aItem;
2140 
2141  m_lib_id = c->m_lib_id;
2142  m_part = c->m_part;
2143  m_Pos = c->m_Pos;
2144  m_unit = c->m_unit;
2145  m_convert = c->m_convert;
2146  m_transform = c->m_transform;
2147 
2149 
2150  m_Fields = c->m_Fields; // std::vector's assignment operator.
2151 
2152  // Reparent fields after assignment to new component.
2153  for( int ii = 0; ii < GetFieldCount(); ++ii )
2154  {
2155  GetField( ii )->SetParent( this );
2156  }
2157  }
2158 
2159  return *this;
2160 }
2161 
2162 
2163 bool SCH_COMPONENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
2164 {
2165  EDA_RECT bBox = GetBodyBoundingBox();
2166  bBox.Inflate( aAccuracy );
2167 
2168  if( bBox.Contains( aPosition ) )
2169  return true;
2170 
2171  return false;
2172 }
2173 
2174 
2175 bool SCH_COMPONENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
2176 {
2178  return false;
2179 
2180  EDA_RECT rect = aRect;
2181 
2182  rect.Inflate( aAccuracy );
2183 
2184  if( aContained )
2185  return rect.Contains( GetBodyBoundingBox() );
2186 
2187  return rect.Intersects( GetBodyBoundingBox() );
2188 }
2189 
2190 
2191 bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
2192 {
2193  std::vector< wxPoint > pts;
2194 
2195  GetConnectionPoints( pts );
2196 
2197  for( size_t i = 0; i < pts.size(); i++ )
2198  {
2199  if( pts[i] == aPosition )
2200  return true;
2201  }
2202 
2203  return false;
2204 }
2205 
2206 
2208 {
2209  SCH_FIELD* rf = GetField( REFERENCE );
2210  return ! rf->GetText().StartsWith( wxT( "#" ) );
2211 }
2212 
2213 
2214 void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
2215 {
2216  TRANSFORM temp;
2217 
2218  if( PART_SPTR part = m_part.lock() )
2219  {
2220  temp = GetTransform();
2221 
2222  part->Plot( aPlotter, GetUnit(), GetConvert(), m_Pos, temp );
2223 
2224  for( size_t i = 0; i < m_Fields.size(); i++ )
2225  {
2226  m_Fields[i].Plot( aPlotter );
2227  }
2228  }
2229 }
void SetTextAngle(double aAngle)
Definition: eda_text.h:156
Definition of the SCH_SHEET class for Eeschema.
LIB_ALIAS * LoadSymbol(const wxString &aNickname, const wxString &aAliasName)
Function LoadSymbol.
bool HitTest(const wxPoint &aPosition, int aAccuracy) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item...
int GetCount() const
Function GetCount returns the number of objects in the list.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: common.h:91
void Offset(int dx, int dy)
Class SCH_FIELD instances are attached to a component and provide a place for the component's value...
Definition: sch_field.h:56
SCH_LAYER_ID m_Layer
void SetModified()
void GetMsgPanelInfo(std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
void Rotate(wxPoint aPosition) override
Function Rotate rotates the item around aPosition 90 degrees in the clockwise direction.
const wxString traceFindItem
Flag to enable find item tracing using the WXTRACE environment variable.
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
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)
Function FindField searches for SCH_FIELD with aFieldName and returns it if found, else NULL.
bool IsMoving() const
Definition: base_struct.h:218
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:168
wxString GetAliasDescription() const
Return information about the aliased parts.
EDA_TEXT_HJUSTIFY_T
Definition: eda_text.h:47
void Plot(PLOTTER *aPlotter) override
Function Plot plots the schematic item to aPlotter.
TRANSFORM & GetTransform() const
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
void SetTransform(const TRANSFORM &aTransform)
PNG memory record (file in memory).
Definition: bitmap_types.h:38
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
void UpdateUnit(int aUnit)
change the unit id to aUnit has maening only for multiple parts per package Do not change the modifie...
wxString GetPath(const SCH_SHEET_PATH *sheet) const
const wxPoint & GetTextPos() const
Definition: eda_text.h:224
int GetOrientation()
Function GetOrientation Used to display component orientation (in dialog editor or info) ...
int y2
Definition: transform.h:51
EDA_ITEM * GetCurItem() const
SCH_SHEET_PATH m_SheetPathInclude
Class LIB_TEXT defines a component library graphical text item.
Definition: lib_text.h:45
time_t m_TimeStamp
Time stamp used for logical links.
Definition: base_struct.h:169
unsigned long timeStamp(wxXmlNode *aTree)
Make a unique time stamp.
bool Contains(const wxPoint &aPoint) const
Function Contains.
SCH_FIELDS m_Fields
Variable length list of fields.
Definition: sch_component.h:91
const SCH_SHEET_PATH * m_currentSheetPath
A temporary sheet path is required to generate the correct reference designator string in complex hei...
wxPoint GetScreenCoord(const wxPoint &aPoint)
Function GetScreenCoord Returns the coordinated point relative to the orientation of the component of...
void ImportValues(const LIB_FIELD &aSource)
Function ImportValues copy parameters from a LIB_FIELD source.
Definition: sch_field.cpp:221
bool Resolve(PART_LIBS *aLibs)
Function Resolve [re-]assigns the current LIB_PART from aLibs which this component is based on...
static bool sort_by_libid(const SCH_COMPONENT *ref, SCH_COMPONENT *cmp)
const wxString GetLibraryName()
wxArrayString m_PathsAndReferences
Defines the hierarchical path and reference of the component.
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:124
wxPoint m_Pos
Name and library where symbol was loaded from, i.e. "74xx:74LS00".
Definition: sch_component.h:77
void SetItalic(bool isItalic)
Definition: eda_text.h:169
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors...
void GetConnectionPoints(std::vector< wxPoint > &aPoints) const override
Function GetConnectionPoints add all the connection points for this item to aPoints.
bool Save(FILE *aFile) const override
Function Save writes the data structures for this object out to a FILE in "*.sch" format...
int GetUnitSelection(SCH_SHEET_PATH *aSheet)
const EDA_RECT GetBodyBoundingBox(int aUnit, int aConvert) const
Function GetBodyBoundingBox.
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Function GetEndPoints adds the schematic item end points to aItemList if the item has end points...
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED) override
Function Draw Draw a schematic item.
Definition: sch_field.cpp:118
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:223
void SetVisible(bool aVisible)
Definition: eda_text.h:175
time_t GetNewTimeStamp()
Definition: common.cpp:166
int x2
Definition: transform.h:50
void MirrorX(int aXaxis_position) override
Function MirrorX mirrors item relative to the X axis about aXaxis_position.
bool IsSelected() const
Definition: base_struct.h:221
bool IsVoid() const
Function IsVoid returns true if the field is either empty or holds "~".
Definition: sch_field.h:116
bool Save(FILE *aFile) const override
Function Save writes the data structures for this object out to a FILE in "*.sch" format...
Definition: sch_field.cpp:314
LIB_PIN * GetPin(const wxString &number)
Function GetPin finds a component 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...
void SetRef(const SCH_SHEET_PATH *sheet, const wxString &ref)
Set the reference, for the given sheet path.
SCH_SHEET_PATH m_SheetPath
LIB_ITEM * GetDrawItem(const wxPoint &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Function GetDrawItem().
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:214
int GetUnitCount() const
Function GetUnitCount returns the number of parts per package of the component.
std::vector< bool > m_isDangling
One isDangling per pin.
Definition: sch_component.h:95
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
EDA_RECT GetBodyBoundingBox() const
Function GetBodyBoundingBox Return a bounding box for the component body but not the fields...
Class LIB_ID.
Definition: lib_id.h:56
NETLIST_ITEM_T m_Type
#define abs(a)
Definition: auxiliary.h:84
#define TEXT_ANGLE_VERT
Definition: common.h:92
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
wxString GetFieldText(wxString aFieldName, bool aIncludeDefaultFields=true) const
Returns text associated with a given field (if such a field exists) is the name of the field...
search types array terminator (End Of Types)
Definition: typeinfo.h:94
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:90
Definition: colors.h:54
void SetTimeStamp(time_t aNewTimeStamp)
Definition: base_struct.h:203
Class LIB_ITEM is the base class for drawable items used by schematic library components.
Definition: lib_draw_item.h:77
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Function GetFields populates a std::vector with SCH_FIELDs.
wxString GetAliasDocumentation() const
Function GetAliasDocumentation Return the documentation text for the given part alias.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Class NETLIST_OBJECT_LIST is a container holding and owning NETLIST_OBJECTs, which are connected item...
wxString Path() const
Function Path the path uses the time stamps which do not changes even when editing sheet parameters a...
void SetConvert(int aConvert)
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:135
bool IsSelectStateChanged(const wxRect &aRect) override
Function IsSelectStateChanged checks if the selection state of an item inside aRect has changed...
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
#define IS_NEW
New item, just created.
Definition: base_struct.h:113
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:104
Class SCH_COLLECTOR.
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
BOX2I boundingBox(T aObject)
boundingBox template method
Definition: shape_index.h:59
int GetConvert() const
int y1
Definition: transform.h:49
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:111
#define SELECTED
Definition: base_struct.h:120
void SetLibId(const LIB_ID &aName, PART_LIBS *aLibs=NULL)
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1077
void SetTimeStamp(time_t aNewTimeStamp)
Function SetTimeStamp changes the time stamp to aNewTimeStamp updates the reference path...
double GetArea() const
Function GetArea returns the area of the rectangle.
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:93
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:253
SCH_FIELD * GetField(int aFieldNdx) const
Function GetField returns a field.
void SetHeight(int val)
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:213
static void ResolveAll(const SCH_COLLECTOR &aComponents, PART_LIBS *aLibs)
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
bool IsMouseCaptured() const
const wxString & GetName() const
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
Subclass of DIALOG_SCH_FIND_BASE, which is generated by wxFormBuilder.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
wxPoint GetPinPhysicalPosition(LIB_PIN *Pin)
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:194
std::shared_ptr< LIB_PART > PART_SPTR
shared pointer to LIB_PART
void SetLayer(SCH_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
bool operator<(const SCH_ITEM &aItem) const override
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
wxString GetDescription() const
SCH_COMPONENT(const wxPoint &pos=wxPoint(0, 0), SCH_ITEM *aParent=NULL)
PART_SPTR SharedPtr()
std::string toUTFTildaText(const wxString &txt)
Function toUTFTildaText convert a wxString to UTF8 and replace any control characters with a ~...
void Empty()
Definition: eda_text.h:231
Class LIB_PART defines a library part object.
SCH_FIELD * AddField(const SCH_FIELD &aField)
Function AddField adds a field to the component.
bool IsDangling() const override
Return whether any pin has dangling status.
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:122
EDA_RECT * GetClipBox()
void GetNetListItem(NETLIST_OBJECT_LIST &aNetListItems, SCH_SHEET_PATH *aSheetPath) override
Function GetNetListItem creates a new NETLIST_OBJECT for the schematic object and adds it to aNetList...
void SetX(int val)
Common plot library Plot settings, and plotting engines (Postscript, Gerber, HPGL and DXF) ...
LIB_PART * FindLibPart(const LIB_ID &aLibId, const wxString &aLibraryName=wxEmptyString)
Function FindLibPart searches all libraries in the list for a part.
wxString GetText(GRAPHIC_PINSHAPE shape)
Definition: pin_shape.cpp:33
void SetUnit(int aUnit)
change the unit id to aUnit has maening only for multiple parts per package Also set the modified fla...
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData, wxPoint *aFindLocation) override
Function Matches compares the item against the search criteria in aSearchData.
int GetBottom() const
int GetUnit() const
Class SCH_SHEET_PATH.
bool IsInNetlist() const
static PART_DRAW_OPTIONS Default()
void clear()
Function clear.
Definition: lib_id.cpp:114
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Function ClearAnnotation clears exiting component annotation ( i.i IC23 changed to IC...
int GetRight() const
void SetWidth(int val)
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
bool Load(LINE_READER &aLine, wxString &aErrorMsg) override
Function Load reads a schematic item from aLine in a .sch file.
int SetLibItemName(const UTF8 &aLibItemName, bool aTestForRev=true)
Function SetLibItemName.
Definition: lib_id.cpp:232
void SetEndPosition(const wxPoint &aPosition)
Definition: lib_rectangle.h:62
void SetY(int val)
bool operator==(const SCH_COMPONENT &aComponent) const
LIB_PART * GetPart() const
Function GetPart gets the shared LIB_PART.
SCH_ITEM & operator=(const SCH_ITEM &aItem)
EDA_TEXT_VJUSTIFY_T
Definition: eda_text.h:54
wxPoint GetPosition() const override
Function GetPosition returns the current draw object position.
Definition: lib_pin.h:471
void Move(const wxPoint &aPosition) override
Function Move moves a draw object to aPosition.
Class PART_LIBS is a collection of PART_LIBs.
Definition of the NETLIST_OBJECT class.
int m_unit
The unit for multiple part per package components.
Definition: sch_component.h:82
Field Value of part, i.e. "3.3K".
void Init(const wxPoint &pos=wxPoint(0, 0))
bool IsDanglingStateChanged(std::vector< DANGLING_END_ITEM > &aItemList) override
Test if the component's dangling state has changed for all pins.
Base plotter engine class.
Definition: plot_common.h:86
wxString GetDocFileName() const
const wxString GetRef(const SCH_SHEET_PATH *sheet)
Function GetRef returns the reference, for the given sheet path.
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
Definition the SCH_COMPONENT class for Eeschema.
#define NULL_STRING
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_draw_item.h:70
void GetPins(std::vector< LIB_PIN * > &aPinsList)
Function GetPins populate a vector with all the pins.
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter...
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
see class PGM_BASE
const wxString & GetName() const
int GetFieldCount() const
Function GetFieldCount returns the number of fields in this component.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Definition: sch_field.cpp:251
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...
static double square(int x)
Definition: trigo.cpp:138
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:193
void AddHierarchicalReference(const wxString &aPath, const wxString &aRef, int aMulti)
Function AddHierarchicalReference adds a full hierarchical reference (path + local reference) ...
bool IsVisible() const
Definition: eda_text.h:176
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void MirrorY(int aYaxis_position) override
Function MirrorY mirrors item relative to the Y axis about aYaxis_position.
bool IsPinDanglingStateChanged(std::vector< DANGLING_END_ITEM > &aItemList, LIB_PINS &aLibPins, unsigned aPin)
Test if the component's dangling state has changed for one given pin index.
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED) override
Virtual function, from the base class SCH_ITEM::Draw.
#define ROTATE_VALUES_COUNT
void SetText(const wxString &aText) override
Sets the text item string to aText.
Definition: lib_text.cpp:488
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:261
STATUS_FLAGS m_Flags
Flag bits for editing and other uses.
Definition: base_struct.h:175
Class EDA_RECT handles the component boundary box.
void SetName(const wxString &aName)
Definition: sch_field.h:85
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
int GetX() const
const LIB_ID & GetLibId() const
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:188
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
UTF8 Format() const
Function Format.
Definition: lib_id.cpp:263
int GetY() const
virtual wxString GetClass() const override
Function GetClass returns the class name.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:254
bool IsPowerConnection() const
Return whether this pin forms an implicit power connection: i.e., is hidden and of type POWER_IN...
Definition: lib_pin.h:378
bool operator!=(const SCH_COMPONENT &aComponent) const
int m_convert
The alternate body style for components that have more than one body style defined.
Definition: sch_component.h:83
Class DANGLING_END_ITEM is a helper class used to store the state of schematic items that can be conn...
Definition for part library class.
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
void SetId(int aId)
Definition: sch_field.h:89
int ReadDelimitedText(wxString *aDest, const char *aSource)
Function ReadDelimitedText copies bytes from aSource delimited string segment to aDest wxString...
Definition: string.cpp:43
SEARCH_RESULT
Definition: base_struct.h:68
static bool IsReferenceStringValid(const wxString &aReferenceString)
Function IsReferenceStringValid (static) Tests for an acceptable reference string An acceptable refer...
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
const UTF8 & GetLibNickname() const
Function GetLibNickname.
Definition: lib_id.h:108
wxString GetClass() const override
Function GetClass returns the class name.
Message panel definition file.
AUTOPLACED m_fieldsAutoplaced
indicates status of field autoplacement
Definition: sch_component.h:97
wxString m_prefix
C, R, U, Q etc - the first character which typically indicates what the component is...
Definition: sch_component.h:86
void SetBold(bool aBold)
Definition: eda_text.h:172
wxString GetKeyWords() const
TRANSFORM m_transform
The rotation/mirror transformation matrix.
Definition: sch_component.h:90
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
bool doIsConnected(const wxPoint &aPosition) const override
Function doIsConnected provides the object specific test to see if it is connected to aPosition...
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
void GetFields(LIB_FIELDS &aList)
Function GetFields returns a list of fields withing this part.
int GetDefaultTextSize()
Default size for text in general.
virtual void SetText(const wxString &aText)
Definition: eda_text.h:141
void SetOrientation(int aOrientation)
Function SetOrientation computes the new transform matrix based on aOrientation for the component whi...
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
#define IS_MOVED
Item being moved.
Definition: base_struct.h:112
Definition: colors.h:62