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-2018 jean-pierre Charras <jp.charras at wanadoo.fr>
10  * Copyright (C) 1992-2011 Wayne Stambaugh <stambaughw@verizon.net>
11  * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.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 #include <sch_reference_list.h>
32 
33 #include <wx/regex.h>
34 #include <algorithm>
35 #include <vector>
36 #include <unordered_set>
37 
38 #include <fctsys.h>
39 #include <refdes_utils.h>
40 #include <reporter.h>
41 
42 #include <sch_component.h>
43 #include <sch_edit_frame.h>
44 
45 
46 void SCH_REFERENCE_LIST::RemoveItem( unsigned int aIndex )
47 {
48  if( aIndex < flatList.size() )
49  flatList.erase( flatList.begin() + aIndex );
50 }
51 
52 
54 {
55  int ii = item1.CompareRef( item2 );
56 
57  if( ii == 0 )
58  ii = item1.m_SheetNum - item2.m_SheetNum;
59 
60  if( ii == 0 )
61  ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
62 
63  if( ii == 0 )
64  ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
65 
66  if( ii == 0 )
67  return item1.m_Uuid < item2.m_Uuid; // ensure a deterministic sort
68  else
69  return ii < 0;
70 }
71 
72 
74 {
75  int ii = item1.CompareRef( item2 );
76 
77  if( ii == 0 )
78  ii = item1.m_SheetNum - item2.m_SheetNum;
79 
80  if( ii == 0 )
81  ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
82 
83  if( ii == 0 )
84  ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
85 
86  if( ii == 0 )
87  return item1.m_Uuid < item2.m_Uuid; // ensure a deterministic sort
88  else
89  return ii < 0;
90 }
91 
92 
94  const SCH_REFERENCE& item2 )
95 {
96  int ii = item1.CompareRef( item2 );
97 
98  if( ii == 0 )
99  ii = item1.CompareValue( item2 );
100 
101  if( ii == 0 )
102  ii = item1.m_Unit - item2.m_Unit;
103 
104  if( ii == 0 )
105  ii = item1.m_SheetNum - item2.m_SheetNum;
106 
107  if( ii == 0 )
108  ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
109 
110  if( ii == 0 )
111  ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
112 
113  if( ii == 0 )
114  return item1.m_Uuid < item2.m_Uuid; // ensure a deterministic sort
115  else
116  return ii < 0;
117 }
118 
119 
121  const SCH_REFERENCE& item2 )
122 {
123  int ii = UTIL::RefDesStringCompare( item1.GetRef(), item2.GetRef() );
124 
125  if( ii == 0 )
126  ii = item1.m_Unit - item2.m_Unit;
127 
128  if( ii == 0 )
129  return item1.m_Uuid < item2.m_Uuid; // ensure a deterministic sort
130  else
131  return ii < 0;
132 }
133 
134 
136  const SCH_REFERENCE& item2 )
137 {
138  int ii = item1.m_SheetPath.Cmp( item2.m_SheetPath );
139 
140  if( ii == 0 )
141  return item1.m_Uuid < item2.m_Uuid; // ensure a deterministic sort
142  else
143  return ii < 0;
144 }
145 
146 
147 int SCH_REFERENCE_LIST::FindUnit( size_t aIndex, int aUnit )
148 {
149  int NumRef;
150 
151  NumRef = flatList[aIndex].m_NumRef;
152 
153  for( size_t ii = 0; ii < flatList.size(); ii++ )
154  {
155  if( ( aIndex == ii )
156  || ( flatList[ii].m_IsNew )
157  || ( flatList[ii].m_NumRef != NumRef )
158  || ( flatList[aIndex].CompareRef( flatList[ii] ) != 0 ) )
159  continue;
160 
161  if( flatList[ii].m_Unit == aUnit )
162  return (int) ii;
163  }
164 
165  return -1;
166 }
167 
168 
169 int SCH_REFERENCE_LIST::FindRefByPath( const wxString& aPath ) const
170 {
171  for( size_t i = 0; i < flatList.size(); ++i )
172  {
173  if( flatList[i].GetPath() == aPath )
174  return i;
175  }
176 
177  return -1;
178 }
179 
180 
181 int SCH_REFERENCE_LIST::FindRef( const wxString& aRef ) const
182 {
183  for( size_t i = 0; i < flatList.size(); ++i )
184  {
185  if( flatList[i].GetRef() == aRef )
186  return i;
187  }
188 
189  return -1;
190 }
191 
192 
193 void SCH_REFERENCE_LIST::GetRefsInUse( int aIndex, std::vector< int >& aIdList, int aMinRefId )
194 {
195  aIdList.clear();
196 
197  for( SCH_REFERENCE& ref : flatList )
198  {
199  if( flatList[aIndex].CompareRef( ref ) == 0 && ref.m_NumRef >= aMinRefId )
200  aIdList.push_back( ref.m_NumRef );
201  }
202 
203  sort( aIdList.begin(), aIdList.end() );
204 
205  // Ensure each reference number appears only once. If there are components with
206  // multiple parts per package the same number will be stored for each part.
207  std::vector< int >::iterator it = unique( aIdList.begin(), aIdList.end() );
208 
209  // Using the C++ unique algorithm only moves the duplicate entries to the end of
210  // of the array. This removes the duplicate entries from the array.
211  aIdList.resize( it - aIdList.begin() );
212 }
213 
214 
215 int SCH_REFERENCE_LIST::GetLastReference( int aIndex, int aMinValue )
216 {
217  int lastNumber = aMinValue;
218 
219  for( SCH_REFERENCE& ref : flatList )
220  {
221  // search only for the current reference prefix:
222  if( flatList[aIndex].CompareRef( ref ) != 0 )
223  continue;
224 
225  // update max value for the current reference prefix
226  if( lastNumber < ref.m_NumRef )
227  lastNumber = ref.m_NumRef;
228  }
229 
230  return lastNumber;
231 }
232 
233 
234 int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue )
235 {
236  int expectedId = aFirstValue;
237 
238  // We search for expected Id a value >= aFirstValue.
239  // Skip existing Id < aFirstValue
240  unsigned ii = 0;
241 
242  for( ; ii < aIdList.size(); ii++ )
243  {
244  if( expectedId <= aIdList[ii] )
245  break;
246  }
247 
248  // Ids are sorted by increasing value, from aFirstValue
249  // So we search from aFirstValue the first not used value, i.e. the first hole in list.
250  for( ; ii < aIdList.size(); ii++ )
251  {
252  if( expectedId != aIdList[ii] ) // This id is not yet used.
253  {
254  // Insert this free Id, in order to keep list sorted
255  aIdList.insert( aIdList.begin() + ii, expectedId );
256  return expectedId;
257  }
258 
259  expectedId++;
260  }
261 
262  // All existing Id are tested, and all values are found in use.
263  // So Create a new one.
264  aIdList.push_back( expectedId );
265  return expectedId;
266 }
267 
268 
269 // A helper function to build a full reference string of a SCH_REFERENCE item
270 wxString buildFullReference( const SCH_REFERENCE& aItem, int aUnitNumber = -1 )
271 {
272  wxString fullref;
273  fullref = aItem.GetRef() + aItem.GetRefNumber();
274 
275  if( aUnitNumber < 0 )
276  fullref << ".." << aItem.GetUnit();
277  else
278  fullref << ".." << aUnitNumber;
279 
280  return fullref;
281 }
282 
283 
284 void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int aStartNumber,
285  SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
286 {
287  if ( flatList.size() == 0 )
288  return;
289 
290  int LastReferenceNumber = 0;
291  int NumberOfUnits, Unit;
292 
293  /* calculate index of the first component with the same reference prefix
294  * than the current component. All components having the same reference
295  * prefix will receive a reference number with consecutive values:
296  * IC .. will be set to IC4, IC4, IC5 ...
297  */
298  unsigned first = 0;
299 
300  // calculate the last used number for this reference prefix:
301  int minRefId;
302 
303  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
304  if( aUseSheetNum )
305  minRefId = flatList[first].m_SheetNum * aSheetIntervalId + 1;
306  else
307  minRefId = aStartNumber + 1;
308 
309  // For multi units components, when "keep order of multi unit" option is selected,
310  // store the list of already used full references.
311  // The algorithm try to allocate the new reference to components having the same
312  // old reference.
313  // This algo works fine as long as the previous annotation has no duplicates.
314  // But when a hierarchy is reannotated with this option, the previous anotation can
315  // have duplicate references, and obviously we must fix these duplicate.
316  // therefore do not try to allocate a full reference more than once when trying
317  // to keep this order of multi units.
318  // inUseRefs keep trace of previously allocated references
319  std::unordered_set<wxString> inUseRefs;
320 
321  // This is the list of all Id already in use for a given reference prefix.
322  // Will be refilled for each new reference prefix.
323  std::vector<int>idList;
324  GetRefsInUse( first, idList, minRefId );
325 
326  for( unsigned ii = 0; ii < flatList.size(); ii++ )
327  {
328  auto& ref_unit = flatList[ii];
329 
330  if( ref_unit.m_Flag )
331  continue;
332 
333  // Check whether this component is in aLockedUnitMap.
334  SCH_REFERENCE_LIST* lockedList = NULL;
335  for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : aLockedUnitMap )
336  {
337  unsigned n_refs = pair.second.GetCount();
338 
339  for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
340  {
341  SCH_REFERENCE &thisRef = pair.second[thisRefI];
342 
343  if( thisRef.IsSameInstance( ref_unit ) )
344  {
345  lockedList = &pair.second;
346  break;
347  }
348  }
349  if( lockedList != NULL ) break;
350  }
351 
352  if( ( flatList[first].CompareRef( ref_unit ) != 0 )
353  || ( aUseSheetNum && ( flatList[first].m_SheetNum != ref_unit.m_SheetNum ) ) )
354  {
355  // New reference found: we need a new ref number for this reference
356  first = ii;
357 
358  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
359  if( aUseSheetNum )
360  minRefId = ref_unit.m_SheetNum * aSheetIntervalId + 1;
361  else
362  minRefId = aStartNumber + 1;
363 
364  GetRefsInUse( first, idList, minRefId );
365  }
366 
367  // Annotation of one part per package components (trivial case).
368  if( ref_unit.GetLibPart()->GetUnitCount() <= 1 )
369  {
370  if( ref_unit.m_IsNew )
371  {
372  LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
373  ref_unit.m_NumRef = LastReferenceNumber;
374  }
375 
376  ref_unit.m_Unit = 1;
377  ref_unit.m_Flag = 1;
378  ref_unit.m_IsNew = false;
379  continue;
380  }
381 
382  // Annotation of multi-unit parts ( n units per part ) (complex case)
383  NumberOfUnits = ref_unit.GetLibPart()->GetUnitCount();
384 
385  if( ref_unit.m_IsNew )
386  {
387  LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
388  ref_unit.m_NumRef = LastReferenceNumber;
389 
390  if( !ref_unit.IsUnitsLocked() )
391  ref_unit.m_Unit = 1;
392 
393  ref_unit.m_Flag = 1;
394  }
395 
396  // If this component is in aLockedUnitMap, copy the annotation to all
397  // components that are not it
398  if( lockedList != NULL )
399  {
400  unsigned n_refs = lockedList->GetCount();
401 
402  for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
403  {
404  SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
405 
406  if( thisRef.IsSameInstance( ref_unit ) )
407  {
408  // This is the component we're currently annotating. Hold the unit!
409  ref_unit.m_Unit = thisRef.m_Unit;
410  // lock this new full reference
411  inUseRefs.insert( buildFullReference( ref_unit ) );
412  }
413 
414  if( thisRef.CompareValue( ref_unit ) != 0 )
415  continue;
416 
417  if( thisRef.CompareLibName( ref_unit ) != 0 )
418  continue;
419 
420  // Find the matching component
421  for( unsigned jj = ii + 1; jj < flatList.size(); jj++ )
422  {
423  if( ! thisRef.IsSameInstance( flatList[jj] ) )
424  continue;
425 
426  wxString ref_candidate = buildFullReference( ref_unit, thisRef.m_Unit );
427 
428  // propagate the new reference and unit selection to the "old" component,
429  // if this new full reference is not already used (can happens when initial
430  // multiunits components have duplicate references)
431  if( inUseRefs.find( ref_candidate ) == inUseRefs.end() )
432  {
433  flatList[jj].m_NumRef = ref_unit.m_NumRef;
434  flatList[jj].m_Unit = thisRef.m_Unit;
435  flatList[jj].m_IsNew = false;
436  flatList[jj].m_Flag = 1;
437  // lock this new full reference
438  inUseRefs.insert( ref_candidate );
439  break;
440  }
441  }
442  }
443  }
444  else
445  {
446  /* search for others units of this component.
447  * we search for others parts that have the same value and the same
448  * reference prefix (ref without ref number)
449  */
450  for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
451  {
452  if( ref_unit.m_Unit == Unit )
453  continue;
454 
455  int found = FindUnit( ii, Unit );
456 
457  if( found >= 0 )
458  continue; // this unit exists for this reference (unit already annotated)
459 
460  // Search a component to annotate ( same prefix, same value, not annotated)
461  for( unsigned jj = ii + 1; jj < flatList.size(); jj++ )
462  {
463  auto& cmp_unit = flatList[jj];
464 
465  if( cmp_unit.m_Flag ) // already tested
466  continue;
467 
468  if( cmp_unit.CompareRef( ref_unit ) != 0 )
469  continue;
470 
471  if( cmp_unit.CompareValue( ref_unit ) != 0 )
472  continue;
473 
474  if( cmp_unit.CompareLibName( ref_unit ) != 0 )
475  continue;
476 
477  if( aUseSheetNum &&
478  cmp_unit.GetSheetPath().Cmp( ref_unit.GetSheetPath() ) != 0 )
479  continue;
480 
481  if( !cmp_unit.m_IsNew )
482  continue;
483 
484  // Component without reference number found, annotate it if possible
485  if( !cmp_unit.IsUnitsLocked()
486  || ( cmp_unit.m_Unit == Unit ) )
487  {
488  cmp_unit.m_NumRef = ref_unit.m_NumRef;
489  cmp_unit.m_Unit = Unit;
490  cmp_unit.m_Flag = 1;
491  cmp_unit.m_IsNew = false;
492  break;
493  }
494  }
495  }
496  }
497  }
498 }
499 
501 {
502  int error = 0;
503  wxString tmp;
504  wxString msg;
505 
507 
508  // Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1.
509  SplitReferences();
510 
511  // count not yet annotated items or annotation error.
512  for( unsigned ii = 0; ii < flatList.size(); ii++ )
513  {
514  msg.Empty();
515  tmp.Empty();
516 
517  if( flatList[ii].m_IsNew ) // Not yet annotated
518  {
519  if( flatList[ii].m_NumRef >= 0 )
520  tmp << flatList[ii].m_NumRef;
521  else
522  tmp = wxT( "?" );
523 
524 
525  if( ( flatList[ii].m_Unit > 0 )
526  && ( flatList[ii].m_Unit < 0x7FFFFFFF ) )
527  {
528  msg.Printf( _( "Item not annotated: %s%s (unit %d)\n" ),
529  flatList[ii].GetRef(),
530  tmp,
531  flatList[ii].m_Unit );
532  }
533  else
534  {
535  msg.Printf( _( "Item not annotated: %s%s\n" ),
536  flatList[ii].GetRef(),
537  tmp );
538  }
539 
540  aReporter.Report( msg, RPT_SEVERITY_WARNING );
541  error++;
542  break;
543  }
544 
545  // Error if unit number selected does not exist ( greater than the number of
546  // parts in the component ). This can happen if a component has changed in a
547  // library after a previous annotation.
548  if( std::max( flatList[ii].GetLibPart()->GetUnitCount(), 1 )
549  < flatList[ii].m_Unit )
550  {
551  if( flatList[ii].m_NumRef >= 0 )
552  tmp << flatList[ii].m_NumRef;
553  else
554  tmp = wxT( "?" );
555 
556  msg.Printf( _( "Error: symbol %s%s unit %d and symbol has only %d units defined\n" ),
557  flatList[ii].GetRef(),
558  tmp,
559  flatList[ii].m_Unit,
560  flatList[ii].GetLibPart()->GetUnitCount() );
561 
562  aReporter.Report( msg, RPT_SEVERITY_ERROR );
563  error++;
564  break;
565  }
566  }
567 
568  if( error )
569  return error;
570 
571  // count the duplicated elements (if all are annotated)
572  int imax = flatList.size() - 1;
573 
574  for( int ii = 0; ii < imax; ii++ )
575  {
576  msg.Empty();
577  tmp.Empty();
578 
579  if( ( flatList[ii].CompareRef( flatList[ii + 1] ) != 0 )
580  || ( flatList[ii].m_NumRef != flatList[ii + 1].m_NumRef ) )
581  continue;
582 
583  // Same reference found. If same unit, error!
584  if( flatList[ii].m_Unit == flatList[ii + 1].m_Unit )
585  {
586  if( flatList[ii].m_NumRef >= 0 )
587  tmp << flatList[ii].m_NumRef;
588  else
589  tmp = wxT( "?" );
590 
591  if( ( flatList[ii].m_Unit > 0 )
592  && ( flatList[ii].m_Unit < 0x7FFFFFFF ) )
593  {
594  msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
595  flatList[ii].GetRef(),
596  tmp,
597  flatList[ii].m_Unit );
598  }
599  else
600  {
601  msg.Printf( _( "Multiple item %s%s\n" ),
602  flatList[ii].GetRef(),
603  tmp );
604  }
605 
606  aReporter.Report( msg, RPT_SEVERITY_ERROR );
607  error++;
608  continue;
609  }
610 
611  /* Test error if units are different but number of parts per package
612  * too high (ex U3 ( 1 part) and we find U3B this is an error) */
613  if( flatList[ii].GetLibPart()->GetUnitCount()
614  != flatList[ ii + 1].GetLibPart()->GetUnitCount() )
615  {
616  if( flatList[ii].m_NumRef >= 0 )
617  tmp << flatList[ii].m_NumRef;
618  else
619  tmp = wxT( "?" );
620 
621  if( ( flatList[ii].m_Unit > 0 )
622  && ( flatList[ii].m_Unit < 0x7FFFFFFF ) )
623  {
624  msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
625  flatList[ii].GetRef(),
626  tmp,
627  flatList[ii].m_Unit );
628  }
629  else
630  {
631  msg.Printf( _( "Multiple item %s%s\n" ),
632  flatList[ii].GetRef(),
633  tmp );
634  }
635 
636  aReporter.Report( msg, RPT_SEVERITY_ERROR );
637  error++;
638  }
639 
640  // Error if values are different between units, for the same reference
641  int next = ii + 1;
642 
643  if( flatList[ii].CompareValue( flatList[next] ) != 0 )
644  {
645  msg.Printf( _( "Different values for %s%d%s (%s) and %s%d%s (%s)" ),
646  flatList[ii].GetRef(),
647  flatList[ii].m_NumRef,
648  LIB_PART::SubReference( flatList[ii].m_Unit ),
649  flatList[ii].m_Value,
650  flatList[next].GetRef(),
651  flatList[next].m_NumRef,
653  flatList[next].m_Value );
654 
655  aReporter.Report( msg, RPT_SEVERITY_ERROR );
656  error++;
657  }
658  }
659 
660  return error;
661 }
662 
663 
665  const SCH_SHEET_PATH& aSheetPath )
666 {
667  wxASSERT( aComponent != NULL );
668 
669  m_RootCmp = aComponent;
670  m_Entry = aLibPart; // Warning: can be nullptr for orphan components
671  // (i.e. with a symbol library not found)
672  m_Unit = aComponent->GetUnitSelection( &aSheetPath );
673  m_Footprint = aComponent->GetFootprint( &aSheetPath );
674  m_SheetPath = aSheetPath;
675  m_IsNew = false;
676  m_Flag = 0;
677  m_Uuid = aComponent->m_Uuid;
678  m_CmpPos = aComponent->GetPosition();
679  m_SheetNum = 0;
680 
681  if( aComponent->GetRef( &aSheetPath ).IsEmpty() )
682  aComponent->SetRef( &aSheetPath, wxT( "DefRef?" ) );
683 
684  wxString ref = aComponent->GetRef( &aSheetPath );
685  SetRef( ref );
686 
687  m_NumRef = -1;
688 
689  if( aComponent->GetValue( &aSheetPath ).IsEmpty() )
690  aComponent->SetValue( &aSheetPath, wxT( "~" ) );
691 
692  m_Value = aComponent->GetValue( &aSheetPath );
693 }
694 
695 
697 {
698  if( m_NumRef < 0 )
699  m_Ref += '?';
700  else
701  m_Ref = TO_UTF8( GetRef() << GetRefNumber() );
702 
706 }
707 
708 
710 {
711  std::string refText = GetRefStr();
712 
713  m_NumRef = -1;
714 
715  int ll = refText.length() - 1;
716 
717  if( refText[ll] == '?' )
718  {
719  m_IsNew = true;
720 
721  if( !IsUnitsLocked() )
722  m_Unit = 0x7FFFFFFF;
723 
724  refText.erase( ll ); // delete last char
725 
726  SetRefStr( refText );
727  }
728  else if( isdigit( refText[ll] ) == 0 )
729  {
730  m_IsNew = true;
731 
732  if( !IsUnitsLocked() )
733  m_Unit = 0x7FFFFFFF;
734  }
735  else
736  {
737  while( ll >= 0 )
738  {
739  if( (refText[ll] <= ' ' ) || isdigit( refText[ll] ) )
740  ll--;
741  else
742  {
743  if( isdigit( refText[ll + 1] ) )
744  {
745  // null terminated C string into cp
746  const char* cp = refText.c_str() + ll + 1;
747 
748  m_NumRef = atoi( cp );
749  }
750 
751  refText.erase( ll+1 ); // delete from ll+1 to end
752  break;
753  }
754  }
755 
756  SetRefStr( refText );
757  }
758 }
759 
760 
761 wxString SCH_REFERENCE_LIST::Shorthand( std::vector<SCH_REFERENCE> aList )
762 {
763  wxString retVal;
764  size_t i = 0;
765 
766  while( i < aList.size() )
767  {
768  wxString ref = aList[ i ].GetRef();
769  int numRef = aList[ i ].m_NumRef;
770 
771  size_t range = 1;
772 
773  while( i + range < aList.size()
774  && aList[ i + range ].GetRef() == ref
775  && aList[ i + range ].m_NumRef == int( numRef + range ) )
776  {
777  range++;
778  }
779 
780  if( !retVal.IsEmpty() )
781  retVal << wxT( ", " );
782 
783  if( range == 1 )
784  {
785  retVal << ref << aList[ i ].GetRefNumber();
786  }
787  else if( range == 2 )
788  {
789  retVal << ref << aList[ i ].GetRefNumber();
790  retVal << wxT( ", " );
791  retVal << ref << aList[ i + 1 ].GetRefNumber();
792  }
793  else
794  {
795  retVal << ref << aList[ i ].GetRefNumber();
796  retVal << wxT( "-" );
797  retVal << ref << aList[ i + ( range - 1 ) ].GetRefNumber();
798  }
799 
800  i+= range;
801  }
802 
803  return retVal;
804 }
CITER next(CITER it)
Definition: ptree.cpp:126
wxPoint m_CmpPos
The physical position of the component in schematic used to annotate by X or Y position.
static bool sortByTimeStamp(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
KIID m_Uuid
UUID of the component.
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:114
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).
int FindRefByPath(const wxString &aPath) const
searches the list for a component with the given KIID path
UTF8 m_Ref
Component reference prefix, without number (for IC1, this is IC) )
int m_NumRef
The numeric part of the reference designator.
Collection of utility functions for component reference designators (refdes)
wxString m_Footprint
The footprint assigned.
const wxString GetValue(const SCH_SHEET_PATH *sheet) const
static wxString Shorthand(std::vector< SCH_REFERENCE > aList)
Function Shorthand Returns a shorthand string representing all the references in the list.
int GetUnit() const
wxString GetRefNumber() const
int m_SheetNum
The sheet number for the reference.
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
void SortByRefAndValue()
Function SortByRefAndValue sorts the list of references by value.
SCH_REFERENCE_LIST is used to create a flattened list of components because in a complex hierarchy,...
int FindRef(const wxString &aPath) const
searches the list for a component with a given reference.
void SetRefStr(const std::string &aReference)
const char * c_str() const
Definition: utf8.h:107
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.
int RefDesStringCompare(const wxString &aFirst, const wxString &aSecond)
Acts just like the strcmp function but treats numbers within the string text correctly for sorting.
wxString GetRef() const
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:100
#define NULL
const wxString GetFootprint(const SCH_SHEET_PATH *sheet) const
int CompareValue(const SCH_REFERENCE &item) const
wxString buildFullReference(const SCH_REFERENCE &aItem, int aUnitNumber=-1)
SCH_COMPONENT * m_RootCmp
The component associated the reference object.
int CompareLibName(const SCH_REFERENCE &item) const
static bool sortByRefAndValue(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
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.
Define a library symbol object.
void Annotate(bool aUseSheetNum, int aSheetIntervalId, int aStartNumber, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap)
Function Annotate set the reference designators in the list that have not been annotated.
wxString m_Value
The component value.
int FindUnit(size_t aIndex, int aUnit)
searches the sorted list of components for a another component with the same reference and a given pa...
void SetUnit(int aUnit)
Change the unit number to aUnit.
static bool sortByYPosition(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
SCH_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...
const KIID m_Uuid
Definition: base_struct.h:162
unsigned GetCount() const
Function GetCount.
SCH_SHEET_PATH m_SheetPath
The sheet path for this reference.
int CompareRef(const SCH_REFERENCE &item) const
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
const char * GetRefStr() const
void SplitReferences()
Function SplitReferences attempts to split all reference designators into a name (U) and number (1).
#define _(s)
Definition: 3d_actions.cpp:33
bool IsSameInstance(const SCH_REFERENCE &other) const
Function IsSameInstance returns whether this reference refers to the same component instance (compone...
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Schematic symbol object.
Definition: sch_component.h:80
wxPoint GetPosition() const override
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)
std::vector< SCH_REFERENCE > flatList
int GetLastReference(int aIndex, int aMinValue)
Function GetLastReference returns the last used (greatest) reference number in the reference list for...
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
int CheckAnnotation(REPORTER &aReporter)
Function CheckAnnotation check for annotations errors.
int Cmp(const SCH_SHEET_PATH &aSheetPathToTest) const
Function Cmp Compare if this is the same sheet path as aSheetPathToTest.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
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)
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.