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 <jean-pierre.charras@gipsa-lab.inpg.fr>
10  * Copyright (C) 1992-2011 Wayne Stambaugh <stambaughw@verizon.net>
11  * Copyright (C) 1992-2011 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 
197 {
198  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
199  {
200  if( componentFlatList[ii].GetRefStr()[0] == '#' )
201  {
202  componentFlatList[ii].m_IsNew = true;
203  componentFlatList[ii].m_NumRef = 0;
204  }
205  }
206 }
207 
208 
209 void SCH_REFERENCE_LIST::GetRefsInUse( int aIndex, std::vector< int >& aIdList, int aMinRefId )
210 {
211  aIdList.clear();
212 
213  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
214  {
215  if( ( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) == 0 )
216  && ( componentFlatList[ii].m_NumRef >= aMinRefId ) )
217  aIdList.push_back( componentFlatList[ii].m_NumRef );
218  }
219 
220  sort( aIdList.begin(), aIdList.end() );
221 
222  // Ensure each reference number appears only once. If there are components with
223  // multiple parts per package the same number will be stored for each part.
224  std::vector< int >::iterator it = unique( aIdList.begin(), aIdList.end() );
225 
226  // Using the C++ unique algorithm only moves the duplicate entries to the end of
227  // of the array. This removes the duplicate entries from the array.
228  aIdList.resize( it - aIdList.begin() );
229 }
230 
231 
232 int SCH_REFERENCE_LIST::GetLastReference( int aIndex, int aMinValue )
233 {
234  int lastNumber = aMinValue;
235 
236  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
237  {
238  // search only for the current reference prefix:
239  if( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) != 0 )
240  continue;
241 
242  // update max value for the current reference prefix
243  if( lastNumber < componentFlatList[ii].m_NumRef )
244  lastNumber = componentFlatList[ii].m_NumRef;
245  }
246 
247  return lastNumber;
248 }
249 
250 
251 int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue )
252 {
253  int expectedId = aFirstValue;
254 
255  // We search for expected Id a value >= aFirstValue.
256  // Skip existing Id < aFirstValue
257  unsigned ii = 0;
258 
259  for( ; ii < aIdList.size(); ii++ )
260  {
261  if( expectedId <= aIdList[ii] )
262  break;
263  }
264 
265  // Ids are sorted by increasing value, from aFirstValue
266  // So we search from aFirstValue the first not used value, i.e. the first hole in list.
267  for( ; ii < aIdList.size(); ii++ )
268  {
269  if( expectedId != aIdList[ii] ) // This id is not yet used.
270  {
271  // Insert this free Id, in order to keep list sorted
272  aIdList.insert( aIdList.begin() + ii, expectedId );
273  return expectedId;
274  }
275 
276  expectedId++;
277  }
278 
279  // All existing Id are tested, and all values are found in use.
280  // So Create a new one.
281  aIdList.push_back( expectedId );
282  return expectedId;
283 }
284 
285 
286 void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
287  SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
288 {
289  if ( componentFlatList.size() == 0 )
290  return;
291 
292  int LastReferenceNumber = 0;
293  int NumberOfUnits, Unit;
294 
295  // Components with an invisible reference (power...) always are re-annotated.
297 
298  /* calculate index of the first component with the same reference prefix
299  * than the current component. All components having the same reference
300  * prefix will receive a reference number with consecutive values:
301  * IC .. will be set to IC4, IC4, IC5 ...
302  */
303  unsigned first = 0;
304 
305  // calculate the last used number for this reference prefix:
306 #ifdef USE_OLD_ALGO
307  int minRefId = 0;
308 
309  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
310  if( aUseSheetNum )
311  minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId;
312 
313  LastReferenceNumber = GetLastReference( first, minRefId );
314 #else
315  int minRefId = 1;
316 
317  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
318  if( aUseSheetNum )
319  minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId + 1;
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 #endif
326  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
327  {
328  if( componentFlatList[ii].m_Flag )
329  continue;
330 
331  // Check whether this component is in aLockedUnitMap.
332  SCH_REFERENCE_LIST* lockedList = NULL;
333  for( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair : aLockedUnitMap )
334  {
335  unsigned n_refs = pair.second.GetCount();
336  for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
337  {
338  SCH_REFERENCE &thisRef = pair.second[thisRefI];
339 
340  if( thisRef.IsSameInstance( componentFlatList[ii] ) )
341  {
342  lockedList = &pair.second;
343  break;
344  }
345  }
346  if( lockedList != NULL ) break;
347  }
348 
349  if( ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 )
350  || ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) ) )
351  {
352  // New reference found: we need a new ref number for this reference
353  first = ii;
354 #ifdef USE_OLD_ALGO
355  minRefId = 0;
356 
357  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
358  if( aUseSheetNum )
359  minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId;
360 
361  LastReferenceNumber = componentFlatList.GetLastReference( ii, minRefId );
362 #else
363  minRefId = 1;
364 
365  // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
366  if( aUseSheetNum )
367  minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId + 1;
368 
369  GetRefsInUse( first, idList, minRefId );
370 #endif
371  }
372 
373  // Annotation of one part per package components (trivial case).
374  if( componentFlatList[ii].GetLibPart()->GetUnitCount() <= 1 )
375  {
376  if( componentFlatList[ii].m_IsNew )
377  {
378 #ifdef USE_OLD_ALGO
379  LastReferenceNumber++;
380 #else
381  LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
382 #endif
383  componentFlatList[ii].m_NumRef = LastReferenceNumber;
384  }
385 
386  componentFlatList[ii].m_Unit = 1;
387  componentFlatList[ii].m_Flag = 1;
388  componentFlatList[ii].m_IsNew = false;
389  continue;
390  }
391 
392  // Annotation of multi-unit parts ( n units per part ) (complex case)
393  NumberOfUnits = componentFlatList[ii].GetLibPart()->GetUnitCount();
394 
395  if( componentFlatList[ii].m_IsNew )
396  {
397 #ifdef USE_OLD_ALGO
398  LastReferenceNumber++;
399 #else
400  LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
401 #endif
402  componentFlatList[ii].m_NumRef = LastReferenceNumber;
403 
404  if( !componentFlatList[ii].IsUnitsLocked() )
405  componentFlatList[ii].m_Unit = 1;
406 
407  componentFlatList[ii].m_Flag = 1;
408  }
409 
410  // If this component is in aLockedUnitMap, copy the annotation to all
411  // components that are not it
412  if( lockedList != NULL )
413  {
414  unsigned n_refs = lockedList->GetCount();
415  for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
416  {
417  SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
418  if( thisRef.IsSameInstance( componentFlatList[ii] ) )
419  {
420  // This is the component we're currently annotating. Hold the unit!
421  componentFlatList[ii].m_Unit = thisRef.m_Unit;
422  }
423 
424  if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue;
425  if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue;
426 
427  // Find the matching component
428  for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
429  {
430  if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue;
431  componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
432  componentFlatList[jj].m_Unit = thisRef.m_Unit;
433  componentFlatList[jj].m_IsNew = false;
434  componentFlatList[jj].m_Flag = 1;
435  break;
436  }
437  }
438  }
439 
440  else
441  {
442  /* search for others units of this component.
443  * we search for others parts that have the same value and the same
444  * reference prefix (ref without ref number)
445  */
446  for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
447  {
448  if( componentFlatList[ii].m_Unit == Unit )
449  continue;
450 
451  int found = FindUnit( ii, Unit );
452 
453  if( found >= 0 )
454  continue; // this unit exists for this reference (unit already annotated)
455 
456  // Search a component to annotate ( same prefix, same value, not annotated)
457  for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
458  {
459  if( componentFlatList[jj].m_Flag ) // already tested
460  continue;
461 
462  if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
463  continue;
464 
465  if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
466  continue;
467 
468  if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
469  continue;
470 
471  if( !componentFlatList[jj].m_IsNew )
472  continue;
473 
474  // Component without reference number found, annotate it if possible
475  if( !componentFlatList[jj].IsUnitsLocked()
476  || ( componentFlatList[jj].m_Unit == Unit ) )
477  {
478  componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
479  componentFlatList[jj].m_Unit = Unit;
480  componentFlatList[jj].m_Flag = 1;
481  componentFlatList[jj].m_IsNew = false;
482  break;
483  }
484  }
485  }
486  }
487  }
488 }
489 
490 
491 int SCH_REFERENCE_LIST::CheckAnnotation( wxArrayString* aMessageList )
492 {
493  int error = 0;
494  wxString tmp;
495  wxString msg;
496 
498 
499  // Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1.
500  SplitReferences();
501 
502  // count not yet annotated items or annotation error.
503  for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
504  {
505  msg.Empty();
506  tmp.Empty();
507 
508  if( componentFlatList[ii].m_IsNew ) // Not yet annotated
509  {
510  if( componentFlatList[ii].m_NumRef >= 0 )
511  tmp << componentFlatList[ii].m_NumRef;
512  else
513  tmp = wxT( "?" );
514 
515 
516  if( ( componentFlatList[ii].m_Unit > 0 )
517  && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
518  {
519  msg.Printf( _( "Item not annotated: %s%s (unit %d)\n" ),
520  GetChars( componentFlatList[ii].GetRef() ),
521  GetChars( tmp ),
522  componentFlatList[ii].m_Unit );
523  }
524  else
525  {
526  msg.Printf( _( "Item not annotated: %s%s\n" ),
527  GetChars( componentFlatList[ii].GetRef() ),
528  GetChars( tmp ) );
529  }
530 
531  if( aMessageList )
532  aMessageList->Add( msg + wxT( "\n" ) );
533 
534  error++;
535  break;
536  }
537 
538  // Error if unit number selected does not exist ( greater than the number of
539  // parts in the component ). This can happen if a component has changed in a
540  // library after a previous annotation.
541  if( std::max( componentFlatList[ii].GetLibPart()->GetUnitCount(), 1 )
542  < componentFlatList[ii].m_Unit )
543  {
544  if( componentFlatList[ii].m_NumRef >= 0 )
545  tmp << componentFlatList[ii].m_NumRef;
546  else
547  tmp = wxT( "?" );
548 
549  msg.Printf( _( "Error item %s%s unit %d and no more than %d parts\n" ),
550  GetChars( componentFlatList[ii].GetRef() ),
551  GetChars( tmp ),
552  componentFlatList[ii].m_Unit,
553  componentFlatList[ii].GetLibPart()->GetUnitCount() );
554 
555  if( aMessageList )
556  aMessageList->Add( msg );
557 
558  error++;
559  break;
560  }
561  }
562 
563  if( error )
564  return error;
565 
566  // count the duplicated elements (if all are annotated)
567  int imax = componentFlatList.size() - 1;
568 
569  for( int ii = 0; (ii < imax) && (error < 4); ii++ )
570  {
571  msg.Empty();
572  tmp.Empty();
573 
574  if( ( componentFlatList[ii].CompareRef( componentFlatList[ii + 1] ) != 0 )
575  || ( componentFlatList[ii].m_NumRef != componentFlatList[ii + 1].m_NumRef ) )
576  continue;
577 
578  // Same reference found. If same unit, error!
579  if( componentFlatList[ii].m_Unit == componentFlatList[ii + 1].m_Unit )
580  {
581  if( componentFlatList[ii].m_NumRef >= 0 )
582  tmp << componentFlatList[ii].m_NumRef;
583  else
584  tmp = wxT( "?" );
585 
586  if( ( componentFlatList[ii].m_Unit > 0 )
587  && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
588  {
589  msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
590  GetChars( componentFlatList[ii].GetRef() ),
591  GetChars( tmp ),
592  componentFlatList[ii].m_Unit );
593  }
594  else
595  {
596  msg.Printf( _( "Multiple item %s%s\n" ),
597  GetChars( componentFlatList[ii].GetRef() ),
598  GetChars( tmp ) );
599  }
600 
601  if( aMessageList )
602  aMessageList->Add( msg );
603 
604  error++;
605  continue;
606  }
607 
608  /* Test error if units are different but number of parts per package
609  * too high (ex U3 ( 1 part) and we find U3B this is an error) */
610  if( componentFlatList[ii].GetLibPart()->GetUnitCount()
611  != componentFlatList[ii + 1].GetLibPart()->GetUnitCount() )
612  {
613  if( componentFlatList[ii].m_NumRef >= 0 )
614  tmp << componentFlatList[ii].m_NumRef;
615  else
616  tmp = wxT( "?" );
617 
618  if( ( componentFlatList[ii].m_Unit > 0 )
619  && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
620  {
621  msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
622  GetChars( componentFlatList[ii].GetRef() ),
623  GetChars( tmp ),
624  componentFlatList[ii].m_Unit );
625  }
626  else
627  {
628  msg.Printf( _( "Multiple item %s%s\n" ),
629  GetChars( componentFlatList[ii].GetRef() ),
630  GetChars( tmp ) );
631  }
632 
633  if( aMessageList )
634  aMessageList->Add( msg );
635 
636  error++;
637  }
638 
639  // Error if values are different between units, for the same reference
640  int next = ii + 1;
641 
642  if( componentFlatList[ii].CompareValue( componentFlatList[next] ) != 0 )
643  {
644  msg.Printf( _( "Different values for %s%d%s (%s) and %s%d%s (%s)" ),
645  GetChars( componentFlatList[ii].GetRef() ),
646  componentFlatList[ii].m_NumRef,
648  componentFlatList[ii].m_Unit ) ),
649  GetChars( componentFlatList[ii].m_Value->GetText() ),
650  GetChars( componentFlatList[next].GetRef() ),
651  componentFlatList[next].m_NumRef,
653  componentFlatList[next].m_Unit ) ),
654  GetChars( componentFlatList[next].m_Value->GetText() ) );
655 
656  if( aMessageList )
657  aMessageList->Add( msg + wxT( "\n" ));
658 
659  error++;
660  }
661  }
662 
663  // count the duplicated time stamps
664  SortByTimeStamp();
665 
666  for( int ii = 0; ( ii < imax ) && ( error < 4 ); ii++ )
667  {
668  if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
669  || ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() ) )
670  continue;
671 
672  // Same time stamp found.
673  wxString full_path;
674 
675  full_path.Printf( wxT( "%s%8.8X" ),
676  GetChars( componentFlatList[ii].GetSheetPath().Path() ),
677  componentFlatList[ii].m_TimeStamp );
678 
679  msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ),
680  GetChars( full_path ),
681  GetChars( componentFlatList[ii].GetRef() ), componentFlatList[ii].m_NumRef,
682  GetChars( componentFlatList[ii + 1].GetRef() ),
683  componentFlatList[ii + 1].m_NumRef );
684 
685  if( aMessageList )
686  aMessageList->Add( msg + wxT( "\n" ));
687 
688  error++;
689  }
690 
691  return error;
692 }
693 
694 
696  SCH_SHEET_PATH& aSheetPath )
697 {
698  wxASSERT( aComponent != NULL && aLibPart != NULL );
699 
700  m_RootCmp = aComponent;
701  m_Entry = aLibPart;
702  m_Unit = aComponent->GetUnitSelection( &aSheetPath );
703  m_SheetPath = aSheetPath;
704  m_IsNew = false;
705  m_Flag = 0;
706  m_TimeStamp = aComponent->GetTimeStamp();
707  m_CmpPos = aComponent->GetPosition();
708  m_SheetNum = 0;
709 
710  if( aComponent->GetRef( &aSheetPath ).IsEmpty() )
711  aComponent->SetRef( &aSheetPath, wxT( "DefRef?" ) );
712 
713  wxString ref = aComponent->GetRef( &aSheetPath );
714  SetRef( ref );
715 
716  m_NumRef = -1;
717 
718  if( aComponent->GetField( VALUE )->GetText().IsEmpty() )
719  aComponent->GetField( VALUE )->SetText( wxT( "~" ) );
720 
721  m_Value = aComponent->GetField( VALUE );
722 }
723 
724 
726 {
727  if( m_NumRef < 0 )
728  m_Ref += wxChar( '?' );
729  else
730  m_Ref = TO_UTF8( GetRef() << m_NumRef );
731 
732  m_RootCmp->SetRef( &m_SheetPath, FROM_UTF8( m_Ref.c_str() ) );
735 }
736 
737 
739 {
740  std::string refText = GetRefStr();
741 
742  m_NumRef = -1;
743 
744  int ll = refText.length() - 1;
745 
746  if( refText[ll] == '?' )
747  {
748  m_IsNew = true;
749 
750  if( !IsUnitsLocked() )
751  m_Unit = 0x7FFFFFFF;
752 
753  refText.erase( ll ); // delete last char
754 
755  SetRefStr( refText );
756  }
757  else if( isdigit( refText[ll] ) == 0 )
758  {
759  m_IsNew = true;
760 
761  if( !IsUnitsLocked() )
762  m_Unit = 0x7FFFFFFF;
763  }
764  else
765  {
766  while( ll >= 0 )
767  {
768  if( (refText[ll] <= ' ' ) || isdigit( refText[ll] ) )
769  ll--;
770  else
771  {
772  if( isdigit( refText[ll + 1] ) )
773  {
774  // null terminated C string into cp
775  const char* cp = refText.c_str() + ll + 1;
776 
777  m_NumRef = atoi( cp );
778  }
779 
780  refText.erase( ll+1 ); // delete from ll+1 to end
781  break;
782  }
783  }
784 
785  SetRefStr( refText );
786  }
787 }
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 SetRef(const SCH_SHEET_PATH *sheet, const wxString &ref)
Set the reference, for the given sheet path.
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
Function GetField returns a field.
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 id to aUnit has maening only for multiple parts per package Also set the modified fla...
static bool sortByYPosition(const SCH_REFERENCE &item1, const SCH_REFERENCE &item2)
Class 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...
time_t GetTimeStamp() const
Definition: base_struct.h:204
void ResetHiddenReferences()
Function ResetHiddenReferences clears the annotation for all references that have an invisible refere...
Field Value of part, i.e. "3.3K".
SCH_SHEET_PATH m_SheetPath
The sheet path for this reference.
wxString GetRef() const
const wxString GetRef(const SCH_SHEET_PATH *sheet)
Function GetRef returns the reference, for the given sheet path.
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)...
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Function SubReference.
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:68
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)
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