KiCad PCB EDA Suite
component_references_lister.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 1992-2011 jean-pierre Charras <jp.charras at wanadoo.fr>
10  * Copyright (C) 1992-2011 Wayne Stambaugh <stambaughw@verizon.net>
11  * Copyright (C) 1992-2017 KiCad Developers, see change_log.txt for contributors.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, you may find one here:
25  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
26  * or you may search the http://www.gnu.org website for the version 2 license,
27  * or you may write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29  */
30 
31 
32 #include <wx/regex.h>
33 #include <algorithm>
34 #include <vector>
35 
36 #include <fctsys.h>
37 #include <kicad_string.h>
38 #include <schframe.h>
39 #include <sch_reference_list.h>
40 #include <sch_component.h>
41 
42 
43 //#define USE_OLD_ALGO
44 
45 
46 void SCH_REFERENCE_LIST::RemoveItem( unsigned int aIndex )
47 {
48  if( aIndex < componentFlatList.size() )
49  componentFlatList.erase( componentFlatList.begin() + aIndex );
50 }
51 
52 
54  const SCH_REFERENCE& item2 )
55 {
56  int ii = item1.CompareRef( item2 );
57 
58  if( ii == 0 )
59  ii = item1.m_SheetNum - item2.m_SheetNum;
60  if( ii == 0 )
61  ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
62  if( ii == 0 )
63  ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
64  if( ii == 0 )
65  ii = item1.m_TimeStamp - item2.m_TimeStamp;
66 
67  return ii < 0;
68 }
69 
71  const SCH_REFERENCE& item2 )
72 {
73  int ii = item1.CompareRef( item2 );
74 
75  if( ii == 0 )
76  ii = item1.m_SheetNum - item2.m_SheetNum;
77  if( ii == 0 )
78  ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
79  if( ii == 0 )
80  ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
81  if( ii == 0 )
82  ii = item1.m_TimeStamp - item2.m_TimeStamp;
83 
84  return ii < 0;
85 }
86 
87 
89  const SCH_REFERENCE& item2 )
90 {
91  int ii = item1.CompareRef( item2 );
92  if( ii == 0 )
93  ii = item1.CompareValue( item2 );
94  if( ii == 0 )
95  ii = item1.m_Unit - item2.m_Unit;
96  if( ii == 0 )
97  ii = item1.m_SheetNum - item2.m_SheetNum;
98  if( ii == 0 )
99  ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
100  if( ii == 0 )
101  ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
102  if( ii == 0 )
103  ii = item1.m_TimeStamp - item2.m_TimeStamp;
104 
105  return ii < 0;
106 }
107 
108 
110  const SCH_REFERENCE& item2 )
111 {
112  int ii;
113 
114  ii = RefDesStringCompare( item1.GetRef(), item2.GetRef() );
115 
116  if( ii == 0 )
117  {
118  ii = item1.m_RootCmp->GetField( VALUE )->GetText().CmpNoCase( item2.m_RootCmp->GetField( VALUE )->GetText() );
119  }
120 
121  if( ii == 0 )
122  {
123  ii = item1.m_Unit - item2.m_Unit;
124  }
125 
126  return ii < 0;
127 }
128 
129 
131  const SCH_REFERENCE& item2 )
132 {
133  int ii = item1.m_SheetPath.Cmp( item2.m_SheetPath );
134 
135  if( ii == 0 )
136  ii = item1.m_TimeStamp - item2.m_TimeStamp;
137 
138  return ii < 0;
139 }
140 
141 int SCH_REFERENCE_LIST::FindUnit( size_t aIndex, int aUnit )
142 {
143  int NumRef;
144 
145  NumRef = componentFlatList[aIndex].m_NumRef;
146 
147  for( size_t ii = 0; ii < componentFlatList.size(); ii++ )
148  {
149  if( ( aIndex == ii )
150  || ( componentFlatList[ii].m_IsNew )
151  || ( componentFlatList[ii].m_NumRef != NumRef )
152  || ( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) != 0 ) )
153  continue;
154 
155  if( componentFlatList[ii].m_Unit == aUnit )
156  return (int) ii;
157  }
158 
159  return -1;
160 }
161 
162 
164 {
165  SCH_COMPONENT* libItem;
166  wxString oldName;
167  wxString currName;
168 
169  // The component list **MUST** be sorted by reference and by unit number
170  // in order to find all parts of a component
172 
173  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
174  {
175 
176  libItem = componentFlatList[ii].m_RootCmp;
177  if( libItem == NULL )
178  continue;
179 
180  currName = componentFlatList[ii].GetRef();
181 
182  if( !oldName.IsEmpty() )
183  {
184  if( oldName == currName ) // currName is a subpart of oldName: remove it
185  {
186  componentFlatList.erase( componentFlatList.begin() + ii );
187  ii--;
188  }
189  }
190 
191  oldName = currName;
192  }
193 }
194 
195 
196 void SCH_REFERENCE_LIST::GetRefsInUse( int aIndex, std::vector< int >& aIdList, int aMinRefId )
197 {
198  aIdList.clear();
199 
200  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
201  {
202  if( ( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) == 0 )
203  && ( componentFlatList[ii].m_NumRef >= aMinRefId ) )
204  aIdList.push_back( componentFlatList[ii].m_NumRef );
205  }
206 
207  sort( aIdList.begin(), aIdList.end() );
208 
209  // Ensure each reference number appears only once. If there are components with
210  // multiple parts per package the same number will be stored for each part.
211  std::vector< int >::iterator it = unique( aIdList.begin(), aIdList.end() );
212 
213  // Using the C++ unique algorithm only moves the duplicate entries to the end of
214  // of the array. This removes the duplicate entries from the array.
215  aIdList.resize( it - aIdList.begin() );
216 }
217 
218 
219 int SCH_REFERENCE_LIST::GetLastReference( int aIndex, int aMinValue )
220 {
221  int lastNumber = aMinValue;
222 
223  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
224  {
225  // search only for the current reference prefix:
226  if( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) != 0 )
227  continue;
228 
229  // update max value for the current reference prefix
230  if( lastNumber < componentFlatList[ii].m_NumRef )
231  lastNumber = componentFlatList[ii].m_NumRef;
232  }
233 
234  return lastNumber;
235 }
236 
237 
238 int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue )
239 {
240  int expectedId = aFirstValue;
241 
242  // We search for expected Id a value >= aFirstValue.
243  // Skip existing Id < aFirstValue
244  unsigned ii = 0;
245 
246  for( ; ii < aIdList.size(); ii++ )
247  {
248  if( expectedId <= aIdList[ii] )
249  break;
250  }
251 
252  // Ids are sorted by increasing value, from aFirstValue
253  // So we search from aFirstValue the first not used value, i.e. the first hole in list.
254  for( ; ii < aIdList.size(); ii++ )
255  {
256  if( expectedId != aIdList[ii] ) // This id is not yet used.
257  {
258  // Insert this free Id, in order to keep list sorted
259  aIdList.insert( aIdList.begin() + ii, expectedId );
260  return expectedId;
261  }
262 
263  expectedId++;
264  }
265 
266  // All existing Id are tested, and all values are found in use.
267  // So Create a new one.
268  aIdList.push_back( expectedId );
269  return expectedId;
270 }
271 
272 
273 void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
274  SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
275 {
276  if ( componentFlatList.size() == 0 )
277  return;
278 
279  int LastReferenceNumber = 0;
280  int NumberOfUnits, Unit;
281 
282  /* calculate index of the first component with the same reference prefix
283  * than the current component. All components having the same reference
284  * prefix will receive a reference number with consecutive values:
285  * IC .. will be set to IC4, IC4, IC5 ...
286  */
287  unsigned first = 0;
288 
289  // calculate the last used number for this reference prefix:
290 #ifdef USE_OLD_ALGO
291  int minRefId = 0;
292 
293  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
294  if( aUseSheetNum )
295  minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId;
296 
297  LastReferenceNumber = GetLastReference( first, minRefId );
298 #else
299  int minRefId = 1;
300 
301  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
302  if( aUseSheetNum )
303  minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId + 1;
304 
305  // This is the list of all Id already in use for a given reference prefix.
306  // Will be refilled for each new reference prefix.
307  std::vector<int>idList;
308  GetRefsInUse( first, idList, minRefId );
309 #endif
310  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
311  {
312  if( componentFlatList[ii].m_Flag )
313  continue;
314 
315  // Check whether this component is in aLockedUnitMap.
316  SCH_REFERENCE_LIST* lockedList = NULL;
317  for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : aLockedUnitMap )
318  {
319  unsigned n_refs = pair.second.GetCount();
320  for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
321  {
322  SCH_REFERENCE &thisRef = pair.second[thisRefI];
323 
324  if( thisRef.IsSameInstance( componentFlatList[ii] ) )
325  {
326  lockedList = &pair.second;
327  break;
328  }
329  }
330  if( lockedList != NULL ) break;
331  }
332 
333  if( ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 )
334  || ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) ) )
335  {
336  // New reference found: we need a new ref number for this reference
337  first = ii;
338 #ifdef USE_OLD_ALGO
339  minRefId = 0;
340 
341  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
342  if( aUseSheetNum )
343  minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId;
344 
345  LastReferenceNumber = componentFlatList.GetLastReference( ii, minRefId );
346 #else
347  minRefId = 1;
348 
349  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
350  if( aUseSheetNum )
351  minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId + 1;
352 
353  GetRefsInUse( first, idList, minRefId );
354 #endif
355  }
356 
357  // Annotation of one part per package components (trivial case).
358  if( componentFlatList[ii].GetLibPart()->GetUnitCount() <= 1 )
359  {
360  if( componentFlatList[ii].m_IsNew )
361  {
362 #ifdef USE_OLD_ALGO
363  LastReferenceNumber++;
364 #else
365  LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
366 #endif
367  componentFlatList[ii].m_NumRef = LastReferenceNumber;
368  }
369 
370  componentFlatList[ii].m_Unit = 1;
371  componentFlatList[ii].m_Flag = 1;
372  componentFlatList[ii].m_IsNew = false;
373  continue;
374  }
375 
376  // Annotation of multi-unit parts ( n units per part ) (complex case)
377  NumberOfUnits = componentFlatList[ii].GetLibPart()->GetUnitCount();
378 
379  if( componentFlatList[ii].m_IsNew )
380  {
381 #ifdef USE_OLD_ALGO
382  LastReferenceNumber++;
383 #else
384  LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
385 #endif
386  componentFlatList[ii].m_NumRef = LastReferenceNumber;
387 
388  if( !componentFlatList[ii].IsUnitsLocked() )
389  componentFlatList[ii].m_Unit = 1;
390 
391  componentFlatList[ii].m_Flag = 1;
392  }
393 
394  // If this component is in aLockedUnitMap, copy the annotation to all
395  // components that are not it
396  if( lockedList != NULL )
397  {
398  unsigned n_refs = lockedList->GetCount();
399  for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
400  {
401  SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
402  if( thisRef.IsSameInstance( componentFlatList[ii] ) )
403  {
404  // This is the component we're currently annotating. Hold the unit!
405  componentFlatList[ii].m_Unit = thisRef.m_Unit;
406  }
407 
408  if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue;
409  if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue;
410 
411  // Find the matching component
412  for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
413  {
414  if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue;
415  componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
416  componentFlatList[jj].m_Unit = thisRef.m_Unit;
417  componentFlatList[jj].m_IsNew = false;
418  componentFlatList[jj].m_Flag = 1;
419  break;
420  }
421  }
422  }
423 
424  else
425  {
426  /* search for others units of this component.
427  * we search for others parts that have the same value and the same
428  * reference prefix (ref without ref number)
429  */
430  for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
431  {
432  if( componentFlatList[ii].m_Unit == Unit )
433  continue;
434 
435  int found = FindUnit( ii, Unit );
436 
437  if( found >= 0 )
438  continue; // this unit exists for this reference (unit already annotated)
439 
440  // Search a component to annotate ( same prefix, same value, not annotated)
441  for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
442  {
443  if( componentFlatList[jj].m_Flag ) // already tested
444  continue;
445 
446  if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
447  continue;
448 
449  if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
450  continue;
451 
452  if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
453  continue;
454 
455  if( !componentFlatList[jj].m_IsNew )
456  continue;
457 
458  // Component without reference number found, annotate it if possible
459  if( !componentFlatList[jj].IsUnitsLocked()
460  || ( componentFlatList[jj].m_Unit == Unit ) )
461  {
462  componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
463  componentFlatList[jj].m_Unit = Unit;
464  componentFlatList[jj].m_Flag = 1;
465  componentFlatList[jj].m_IsNew = false;
466  break;
467  }
468  }
469  }
470  }
471  }
472 }
473 
474 
475 int SCH_REFERENCE_LIST::CheckAnnotation( wxArrayString* aMessageList )
476 {
477  int error = 0;
478  wxString tmp;
479  wxString msg;
480 
482 
483  // Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1.
484  SplitReferences();
485 
486  // count not yet annotated items or annotation error.
487  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
488  {
489  msg.Empty();
490  tmp.Empty();
491 
492  if( componentFlatList[ii].m_IsNew ) // Not yet annotated
493  {
494  if( componentFlatList[ii].m_NumRef >= 0 )
495  tmp << componentFlatList[ii].m_NumRef;
496  else
497  tmp = wxT( "?" );
498 
499 
500  if( ( componentFlatList[ii].m_Unit > 0 )
501  && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
502  {
503  msg.Printf( _( "Item not annotated: %s%s (unit %d)\n" ),
504  GetChars( componentFlatList[ii].GetRef() ),
505  GetChars( tmp ),
506  componentFlatList[ii].m_Unit );
507  }
508  else
509  {
510  msg.Printf( _( "Item not annotated: %s%s\n" ),
511  GetChars( componentFlatList[ii].GetRef() ),
512  GetChars( tmp ) );
513  }
514 
515  if( aMessageList )
516  aMessageList->Add( msg + wxT( "\n" ) );
517 
518  error++;
519  break;
520  }
521 
522  // Error if unit number selected does not exist ( greater than the number of
523  // parts in the component ). This can happen if a component has changed in a
524  // library after a previous annotation.
525  if( std::max( componentFlatList[ii].GetLibPart()->GetUnitCount(), 1 )
526  < componentFlatList[ii].m_Unit )
527  {
528  if( componentFlatList[ii].m_NumRef >= 0 )
529  tmp << componentFlatList[ii].m_NumRef;
530  else
531  tmp = wxT( "?" );
532 
533  msg.Printf( _( "Error item %s%s unit %d and no more than %d parts\n" ),
534  GetChars( componentFlatList[ii].GetRef() ),
535  GetChars( tmp ),
536  componentFlatList[ii].m_Unit,
537  componentFlatList[ii].GetLibPart()->GetUnitCount() );
538 
539  if( aMessageList )
540  aMessageList->Add( msg );
541 
542  error++;
543  break;
544  }
545  }
546 
547  if( error )
548  return error;
549 
550  // count the duplicated elements (if all are annotated)
551  int imax = componentFlatList.size() - 1;
552 
553  for( int ii = 0; (ii < imax) && (error < 4); ii++ )
554  {
555  msg.Empty();
556  tmp.Empty();
557 
558  if( ( componentFlatList[ii].CompareRef( componentFlatList[ii + 1] ) != 0 )
559  || ( componentFlatList[ii].m_NumRef != componentFlatList[ii + 1].m_NumRef ) )
560  continue;
561 
562  // Same reference found. If same unit, error!
563  if( componentFlatList[ii].m_Unit == componentFlatList[ii + 1].m_Unit )
564  {
565  if( componentFlatList[ii].m_NumRef >= 0 )
566  tmp << componentFlatList[ii].m_NumRef;
567  else
568  tmp = wxT( "?" );
569 
570  if( ( componentFlatList[ii].m_Unit > 0 )
571  && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
572  {
573  msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
574  GetChars( componentFlatList[ii].GetRef() ),
575  GetChars( tmp ),
576  componentFlatList[ii].m_Unit );
577  }
578  else
579  {
580  msg.Printf( _( "Multiple item %s%s\n" ),
581  GetChars( componentFlatList[ii].GetRef() ),
582  GetChars( tmp ) );
583  }
584 
585  if( aMessageList )
586  aMessageList->Add( msg );
587 
588  error++;
589  continue;
590  }
591 
592  /* Test error if units are different but number of parts per package
593  * too high (ex U3 ( 1 part) and we find U3B this is an error) */
594  if( componentFlatList[ii].GetLibPart()->GetUnitCount()
595  != componentFlatList[ii + 1].GetLibPart()->GetUnitCount() )
596  {
597  if( componentFlatList[ii].m_NumRef >= 0 )
598  tmp << componentFlatList[ii].m_NumRef;
599  else
600  tmp = wxT( "?" );
601 
602  if( ( componentFlatList[ii].m_Unit > 0 )
603  && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
604  {
605  msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
606  GetChars( componentFlatList[ii].GetRef() ),
607  GetChars( tmp ),
608  componentFlatList[ii].m_Unit );
609  }
610  else
611  {
612  msg.Printf( _( "Multiple item %s%s\n" ),
613  GetChars( componentFlatList[ii].GetRef() ),
614  GetChars( tmp ) );
615  }
616 
617  if( aMessageList )
618  aMessageList->Add( msg );
619 
620  error++;
621  }
622 
623  // Error if values are different between units, for the same reference
624  int next = ii + 1;
625 
626  if( componentFlatList[ii].CompareValue( componentFlatList[next] ) != 0 )
627  {
628  msg.Printf( _( "Different values for %s%d%s (%s) and %s%d%s (%s)" ),
629  GetChars( componentFlatList[ii].GetRef() ),
630  componentFlatList[ii].m_NumRef,
632  componentFlatList[ii].m_Unit ) ),
633  GetChars( componentFlatList[ii].m_Value->GetText() ),
634  GetChars( componentFlatList[next].GetRef() ),
635  componentFlatList[next].m_NumRef,
637  componentFlatList[next].m_Unit ) ),
638  GetChars( componentFlatList[next].m_Value->GetText() ) );
639 
640  if( aMessageList )
641  aMessageList->Add( msg + wxT( "\n" ));
642 
643  error++;
644  }
645  }
646 
647  // count the duplicated time stamps
648  SortByTimeStamp();
649 
650  for( int ii = 0; ( ii < imax ) && ( error < 4 ); ii++ )
651  {
652  if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
653  || ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() ) )
654  continue;
655 
656  // Same time stamp found.
657  wxString full_path;
658 
659  full_path.Printf( wxT( "%s%8.8X" ),
660  GetChars( componentFlatList[ii].GetSheetPath().Path() ),
661  componentFlatList[ii].m_TimeStamp );
662 
663  msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ),
664  GetChars( full_path ),
665  GetChars( componentFlatList[ii].GetRef() ), componentFlatList[ii].m_NumRef,
666  GetChars( componentFlatList[ii + 1].GetRef() ),
667  componentFlatList[ii + 1].m_NumRef );
668 
669  if( aMessageList )
670  aMessageList->Add( msg + wxT( "\n" ));
671 
672  error++;
673  }
674 
675  return error;
676 }
677 
678 
680  SCH_SHEET_PATH& aSheetPath )
681 {
682  wxASSERT( aComponent != NULL && aLibPart != NULL );
683 
684  m_RootCmp = aComponent;
685  m_Entry = aLibPart;
686  m_Unit = aComponent->GetUnitSelection( &aSheetPath );
687  m_SheetPath = aSheetPath;
688  m_IsNew = false;
689  m_Flag = 0;
690  m_TimeStamp = aComponent->GetTimeStamp();
691  m_CmpPos = aComponent->GetPosition();
692  m_SheetNum = 0;
693 
694  if( aComponent->GetRef( &aSheetPath ).IsEmpty() )
695  aComponent->SetRef( &aSheetPath, wxT( "DefRef?" ) );
696 
697  wxString ref = aComponent->GetRef( &aSheetPath );
698  SetRef( ref );
699 
700  m_NumRef = -1;
701 
702  if( aComponent->GetField( VALUE )->GetText().IsEmpty() )
703  aComponent->GetField( VALUE )->SetText( wxT( "~" ) );
704 
705  m_Value = aComponent->GetField( VALUE );
706 }
707 
708 
710 {
711  if( m_NumRef < 0 )
712  m_Ref += wxChar( '?' );
713  else
714  {
715  // To avoid a risk of duplicate, for power components
716  // the ref number is 0nnn instead of nnn.
717  // Just because sometimes only power components are annotated
718  if( GetLibPart() && GetLibPart()->IsPower() )
719  m_Ref = TO_UTF8( GetRef() << "0" << m_NumRef );
720  else
721  m_Ref = TO_UTF8( GetRef() << m_NumRef );
722  }
723 
727 }
728 
729 
731 {
732  std::string refText = GetRefStr();
733 
734  m_NumRef = -1;
735 
736  int ll = refText.length() - 1;
737 
738  if( refText[ll] == '?' )
739  {
740  m_IsNew = true;
741 
742  if( !IsUnitsLocked() )
743  m_Unit = 0x7FFFFFFF;
744 
745  refText.erase( ll ); // delete last char
746 
747  SetRefStr( refText );
748  }
749  else if( isdigit( refText[ll] ) == 0 )
750  {
751  m_IsNew = true;
752 
753  if( !IsUnitsLocked() )
754  m_Unit = 0x7FFFFFFF;
755  }
756  else
757  {
758  while( ll >= 0 )
759  {
760  if( (refText[ll] <= ' ' ) || isdigit( refText[ll] ) )
761  ll--;
762  else
763  {
764  if( isdigit( refText[ll + 1] ) )
765  {
766  // null terminated C string into cp
767  const char* cp = refText.c_str() + ll + 1;
768 
769  m_NumRef = atoi( cp );
770  }
771 
772  refText.erase( ll+1 ); // delete from ll+1 to end
773  break;
774  }
775  }
776 
777  SetRefStr( refText );
778  }
779 }
CITER next(CITER it)
Definition: ptree.cpp:130
const char * GetRefStr() const
wxPoint m_CmpPos
The physical position of the component in schematic used to annotate by X or Y position.
int CompareLibName(const SCH_REFERENCE &item) const
int RefDesStringCompare(const wxString &strFWord, const wxString &strSWord)
Function RefDesStringCompare acts just like the strcmp function but treats numbers within the string ...
Definition: string.cpp:365
static bool sortByTimeStamp(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
std::vector< SCH_REFERENCE > componentFlatList
void RemoveSubComponentsFromList()
Function RemoveSubComponentsFromList Remove sub components from the list, when multiples parts per pa...
int CompareValue(const SCH_REFERENCE &item) const
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 RemoveItem(unsigned int aIndex)
Function RemoveItem removes an item from the list of references.
void Split()
Function Split attempts to split the reference designator into a name (U) and number (1)...
UTF8 m_Ref
Component reference prefix, without number (for IC1, this is IC) )
int m_NumRef
The numeric part of the reference designator.
time_t m_TimeStamp
The time stamp for the reference.
int GetUnitSelection(SCH_SHEET_PATH *aSheet)
void SetUnitSelection(SCH_SHEET_PATH *aSheet, int aUnitSelection)
int m_SheetNum
The sheet number for the reference.
int CheckAnnotation(wxArrayString *aMessageList)
Function CheckAnnotation check for annotations errors.
bool IsSameInstance(const SCH_REFERENCE &other) const
Function IsSameInstance returns whether this reference refers to the same component instance (compone...
void SortByRefAndValue()
Function SortByRefAndValue sorts the list of references by value.
Class SCH_REFERENCE_LIST is used to create a flattened list of components because in a complex hierar...
void SetRefStr(const std::string &aReference)
void GetRefsInUse(int aIndex, std::vector< int > &aIdList, int aMinRefId)
Function GetRefsInUse adds all the reference designator numbers greater than aMinRefId to aIdList ski...
int m_Unit
The unit number for components with multiple parts per package.
#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
void SortByTimeStamp()
Function SortComponentsByTimeStamp sort the flat list by Time Stamp.
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
int CompareRef(const SCH_REFERENCE &item) const
SCH_COMPONENT * m_RootCmp
The component associated the reference object.
EDA_TEXT * m_Value
The component value of the reference.
void Annotate(bool aUseSheetNum, int aSheetIntervalId, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap)
Function Annotate set the reference designators in the list that have not been annotated.
static bool sortByRefAndValue(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
LIB_PART * m_Entry
The source component from a library.
void Annotate()
Function Annotate updates the annotation of the component according the the current object state...
Class LIB_PART defines a library part object.
int FindUnit(size_t aIndex, int aUnit)
Function GetUnit searches the sorted list of components for a another component with the same referen...
void SetUnit(int aUnit)
Change the unit number to aUnit.
static bool sortByYPosition(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
Class SCH_SHEET_PATH.
const wxString GetRef(const SCH_SHEET_PATH *aSheet)
Return the reference for the given sheet path.
static bool sortByReferenceOnly(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Type SCH_MULTI_UNIT_REFERENCE_MAP is used to create a map of reference designators for multi-unit par...
time_t GetTimeStamp() const
Definition: base_struct.h:218
Field Value of part, i.e. "3.3K".
SCH_SHEET_PATH m_SheetPath
The sheet path for this reference.
wxString GetRef() const
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
Definition the SCH_COMPONENT class for Eeschema.
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
#define max(a, b)
Definition: auxiliary.h:86
void SortByReferenceOnly()
Function SortByReferenceOnly sorts the list of references by reference.
void SplitReferences()
Function SplitReferences attempts to split all reference designators into a name (U) and number (1)...
const char * c_str() const
Definition: utf8.h:107
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Function SubReference.
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
wxPoint GetPosition() const override
Function GetPosition.
int Cmp(const SCH_SHEET_PATH &aSheetPathToTest) const
Function Cmp Compare if this is the same sheet path as aSheetPathToTest.
int CreateFirstFreeRefId(std::vector< int > &aIdList, int aFirstValue)
Function CreateFirstFreeRefId searches for the first free reference number in aListId of reference nu...
void SetRef(const wxString &aReference)
LIB_PART * GetLibPart() const
int GetLastReference(int aIndex, int aMinValue)
Function GetLastReference returns the last used (greatest) reference number in the reference list for...
unsigned GetCount()
Function GetCount.
Class SCH_REFERENCE is used as a helper to define a component's reference designator in a schematic...
bool m_IsNew
True if not yet annotated.
static bool sortByXPosition(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
virtual void SetText(const wxString &aText)
Definition: eda_text.h:141