KiCad PCB EDA Suite
class_libentry.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) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <fctsys.h>
27 #include <macros.h>
28 #include <kicad_string.h>
29 #include <sch_draw_panel.h>
30 #include <plotter.h>
31 #include <gr_basic.h>
32 #include <sch_screen.h>
33 #include <richio.h>
34 #include <trace_helpers.h>
35 #include <general.h>
36 #include <template_fieldnames.h>
37 #include <transform.h>
38 #include <class_library.h>
39 #include <class_libentry.h>
40 #include <lib_pin.h>
41 #include <lib_arc.h>
42 
43 
44 // the separator char between the subpart id and the reference
45 // 0 (no separator) or '.' or some other character
47 
48 // the ascii char value to calculate the subpart symbol id from the part number:
49 // 'A' or '1' usually. (to print U1.A or U1.1)
50 // if this a a digit, a number is used as id symbol
52 
53 
55 {
56  // Matches are scored by offset from front of string, so inclusion of this spacer
57  // discounts matches found after it.
58  static const wxString discount( wxT( " " ) );
59 
60  wxString text = GetKeyWords() + discount + GetDescription();
61  wxString footprint = GetFootprintField().GetText();
62 
63  if( !footprint.IsEmpty() )
64  {
65  text += discount + footprint;
66  }
67 
68  return text;
69 }
70 
71 
72 bool operator<( const LIB_PART& aItem1, const LIB_PART& aItem2 )
73 {
74  return aItem1.GetName() < aItem2.GetName();
75 }
76 
77 
80 {
81  void operator()(void const *) const
82  {
83  }
84 };
85 
86 
87 LIB_PART::LIB_PART( const wxString& aName, LIB_PART* aParent, PART_LIB* aLibrary ) :
89  m_me( this, null_deleter() )
90 {
92  m_unitCount = 1;
93  m_pinNameOffset = 40;
95  m_unitsLocked = false;
96  m_showPinNumbers = true;
97  m_showPinNames = true;
98 
99  // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present
100  // when the field editors are invoked.
101  m_drawings[LIB_FIELD_T].reserve( 4 );
106 
107  SetName( aName );
108 
109  if( aParent )
110  SetParent( aParent );
111 
112  SetLib( aLibrary );
113 }
114 
115 
116 LIB_PART::LIB_PART( const LIB_PART& aPart, PART_LIB* aLibrary ) :
117  EDA_ITEM( aPart ),
118  m_me( this, null_deleter() )
119 {
120  LIB_ITEM* newItem;
121 
122  m_library = aLibrary;
123  m_name = aPart.m_name;
124  m_FootprintList = wxArrayString( aPart.m_FootprintList );
125  m_unitCount = aPart.m_unitCount;
131  m_options = aPart.m_options;
132  m_libId = aPart.m_libId;
134  m_keyWords = aPart.m_keyWords;
136 
137  for( const LIB_ITEM& oldItem : aPart.m_drawings )
138  {
139  if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
140  continue;
141 
142  newItem = (LIB_ITEM*) oldItem.Clone();
143  newItem->SetParent( this );
144  m_drawings.push_back( newItem );
145  }
146 
147  PART_SPTR parent = aPart.m_parent.lock();
148 
149  if( parent )
150  SetParent( parent.get() );
151 }
152 
153 
155 {
156 }
157 
158 
159 int LIB_PART::Compare( const LIB_PART& aRhs ) const
160 {
161  if( m_me == aRhs.m_me )
162  return 0;
163 
164  int retv = m_name.Cmp( aRhs.m_name );
165 
166  if( retv )
167  return retv;
168 
169  retv = m_libId.compare( aRhs.m_libId );
170 
171  if( retv )
172  return retv;
173 
174  if( m_parent.lock() < aRhs.m_parent.lock() )
175  return -1;
176 
177  if( m_parent.lock() > aRhs.m_parent.lock() )
178  return 1;
179 
180  if( m_options != aRhs.m_options )
181  return ( m_options == ENTRY_NORMAL ) ? -1 : 1;
182 
183  if( m_unitCount != aRhs.m_unitCount )
184  return m_unitCount - aRhs.m_unitCount;
185 
186  if( m_drawings.size() != aRhs.m_drawings.size() )
187  return m_drawings.size() - aRhs.m_drawings.size();
188 
191 
192  while( lhsItem != m_drawings.end() )
193  {
194  if( lhsItem->Type() != rhsItem->Type() )
195  return lhsItem->Type() - rhsItem->Type();
196 
197  retv = lhsItem->compare( *rhsItem );
198 
199  if( retv )
200  return retv;
201 
202  ++lhsItem;
203  ++rhsItem;
204  }
205 
206  if( m_FootprintList.GetCount() != aRhs.m_FootprintList.GetCount() )
207  return m_FootprintList.GetCount() - aRhs.m_FootprintList.GetCount();
208 
209  for( size_t i = 0; i < m_FootprintList.GetCount(); i++ )
210  {
211  retv = m_FootprintList[i].Cmp( aRhs.m_FootprintList[i] );
212 
213  if( retv )
214  return retv;
215  }
216 
217  retv = m_description.Cmp( aRhs.m_description );
218 
219  if( retv )
220  return retv;
221 
222  retv = m_keyWords.Cmp( aRhs.m_keyWords );
223 
224  if( retv )
225  return retv;
226 
227  retv = m_docFileName.Cmp( aRhs.m_docFileName );
228 
229  if( retv )
230  return retv;
231 
232  if( m_pinNameOffset != aRhs.m_pinNameOffset )
233  return m_pinNameOffset - aRhs.m_pinNameOffset;
234 
235  if( m_unitsLocked != aRhs.m_unitsLocked )
236  return ( m_unitsLocked ) ? 1 : -1;
237 
238  if( m_showPinNames != aRhs.m_showPinNames )
239  return ( m_showPinNames ) ? 1 : -1;
240 
241  if( m_showPinNumbers != aRhs.m_showPinNumbers )
242  return ( m_showPinNumbers ) ? 1 : -1;
243 
244  return 0;
245 }
246 
247 
248 wxString LIB_PART::GetUnitReference( int aUnit )
249 {
250  return LIB_PART::SubReference( aUnit, false );
251 }
252 
253 
254 void LIB_PART::SetName( const wxString& aName )
255 {
256  wxString validatedName = LIB_ID::FixIllegalChars( aName, LIB_ID::ID_SCH );
257 
258  m_name = validatedName;
259  m_libId.SetLibItemName( validatedName, false );
260 
261  GetValueField().SetText( validatedName );
262 }
263 
264 
266 {
267  if( aParent )
268  {
269  m_parent = aParent->SharedPtr();
270 
271  // Inherit the parent mandatory field attributes.
272  for( int id=0; id<MANDATORY_FIELDS; ++id )
273  {
274  LIB_FIELD* field = GetField( id );
275 
276  // the MANDATORY_FIELDS are exactly that in RAM.
277  wxASSERT( field );
278 
279  LIB_FIELD* parentField = aParent->GetField( id );
280 
281  wxASSERT( parentField );
282 
283  wxString name = field->GetText();
284 
285  *field = *parentField;
286 
287  if( id == VALUE )
288  field->SetText( name );
289  else if( id == DATASHEET && !GetDocFileName().IsEmpty() )
290  field->SetText( GetDocFileName() );
291 
292  field->SetParent( this );
293  }
294  }
295  else
296  {
297  m_parent.reset();
298  }
299 }
300 
301 
302 std::unique_ptr< LIB_PART > LIB_PART::Flatten() const
303 {
304  std::unique_ptr< LIB_PART > retv;
305 
306  if( IsAlias() )
307  {
308  PART_SPTR parent = m_parent.lock();
309 
310  wxCHECK_MSG( parent, retv,
311  wxString::Format( "Parent of derived symbol '%s' undefined", m_name ) );
312 
313  // Copy the parent.
314  retv.reset( new LIB_PART( *parent.get() ) );
315 
316  // Now add the inherited part (this) information.
317  retv->SetName( m_name );
318 
319  const LIB_FIELD* datasheetField = GetField( DATASHEET );
320  retv->GetField( DATASHEET )->SetText( datasheetField->GetText() );
321  retv->SetDocFileName( m_docFileName );
322  retv->SetKeyWords( m_keyWords );
323  retv->SetDescription( m_description );
324  }
325  else
326  {
327  retv.reset( new LIB_PART( *this ) );
328  }
329 
330  return retv;
331 }
332 
333 
334 const wxString LIB_PART::GetLibraryName() const
335 {
336  if( m_library )
337  return m_library->GetName();
338 
339  return m_libId.GetLibNickname();
340 }
341 
342 
343 wxString LIB_PART::SubReference( int aUnit, bool aAddSeparator )
344 {
345  wxString subRef;
346 
347  if( m_subpartIdSeparator != 0 && aAddSeparator )
348  subRef << wxChar( m_subpartIdSeparator );
349 
350  if( m_subpartFirstId >= '0' && m_subpartFirstId <= '9' )
351  subRef << aUnit;
352  else
353  {
354  // use letters as notation. To allow more than 26 units, the sub ref
355  // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
356  // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
357  int u;
358  aUnit -= 1; // Unit number starts to 1. now to 0.
359 
360  while( aUnit >= 26 ) // more than one letter are needed
361  {
362  u = aUnit / 26;
363  subRef << wxChar( m_subpartFirstId + u -1 );
364  aUnit %= 26;
365  }
366 
367  u = m_subpartFirstId + aUnit;
368  subRef << wxChar( u );
369  }
370 
371  return subRef;
372 }
373 
374 
375 void LIB_PART::Print( wxDC* aDc, const wxPoint& aOffset, int aMulti, int aConvert,
376  const PART_DRAW_OPTIONS& aOpts )
377 {
378  /* draw background for filled items using background option
379  * Solid lines will be drawn after the background
380  * Note also, background is not drawn when printing in black and white
381  */
382  if( !GetGRForceBlackPenState() )
383  {
384  for( LIB_ITEM& drawItem : m_drawings )
385  {
386  if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
387  continue;
388 
389  // Do not draw items not attached to the current part
390  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
391  continue;
392 
393  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
394  continue;
395 
396  if( drawItem.Type() == LIB_FIELD_T )
397  continue;
398 
399  // Now, draw only the background for items with
400  // m_Fill == FILLED_WITH_BG_BODYCOLOR:
401  drawItem.Print( aDc, aOffset, (void*) false, aOpts.transform );
402  }
403  }
404 
405  for( LIB_ITEM& drawItem : m_drawings )
406  {
407  // Do not draw items not attached to the current part
408  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
409  continue;
410 
411  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
412  continue;
413 
414  if( drawItem.Type() == LIB_FIELD_T )
415  {
416  LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem );
417 
418  if( field.IsVisible() && !aOpts.draw_visible_fields )
419  continue;
420 
421  if( !field.IsVisible() && !aOpts.draw_hidden_fields )
422  continue;
423  }
424 
425  if( drawItem.Type() == LIB_PIN_T )
426  {
427  drawItem.Print( aDc, aOffset, (void*) &aOpts, aOpts.transform );
428  }
429  else if( drawItem.Type() == LIB_FIELD_T )
430  {
431  drawItem.Print( aDc, aOffset, (void*) NULL, aOpts.transform );
432  }
433  else
434  {
435  bool forceNoFill = drawItem.m_Fill == FILLED_WITH_BG_BODYCOLOR;
436  drawItem.Print( aDc, aOffset, (void*) forceNoFill, aOpts.transform );
437  }
438  }
439 }
440 
441 
442 void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
443  const wxPoint& aOffset, const TRANSFORM& aTransform )
444 {
445  wxASSERT( aPlotter != NULL );
446 
447  aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) );
448  bool fill = aPlotter->GetColorMode();
449 
450  // draw background for filled items using background option
451  // Solid lines will be drawn after the background
452  for( LIB_ITEM& item : m_drawings )
453  {
454  // Lib Fields are not plotted here, because this plot function
455  // is used to plot schematic items, which have they own fields
456  if( item.Type() == LIB_FIELD_T )
457  continue;
458 
459  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
460  continue;
461 
462  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
463  continue;
464 
465  if( item.m_Fill == FILLED_WITH_BG_BODYCOLOR )
466  item.Plot( aPlotter, aOffset, fill, aTransform );
467  }
468 
469  // Not filled items and filled shapes are now plotted
470  // Items that have BG fills only get re-stroked to ensure the edges are in the foreground
471  for( LIB_ITEM& item : m_drawings )
472  {
473  if( item.Type() == LIB_FIELD_T )
474  continue;
475 
476  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
477  continue;
478 
479  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
480  continue;
481 
482  item.Plot( aPlotter, aOffset, fill && ( item.m_Fill != FILLED_WITH_BG_BODYCOLOR ),
483  aTransform );
484  }
485 }
486 
487 
488 void LIB_PART::PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
489  const wxPoint& aOffset, const TRANSFORM& aTransform )
490 {
491  wxASSERT( aPlotter != NULL );
492 
493  aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
494  bool fill = aPlotter->GetColorMode();
495 
496  for( LIB_ITEM& item : m_drawings )
497  {
498  if( item.Type() != LIB_FIELD_T )
499  continue;
500 
501  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
502  continue;
503 
504  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
505  continue;
506 
507  LIB_FIELD& field = (LIB_FIELD&) item;
508 
509  // The reference is a special case: we should change the basic text
510  // to add '?' and the part id
511  wxString tmp = field.GetShownText();
512 
513  if( field.GetId() == REFERENCE )
514  {
515  wxString text = field.GetFullText( aUnit );
516  field.SetText( text );
517  }
518 
519  item.Plot( aPlotter, aOffset, fill, aTransform );
520  field.SetText( tmp );
521  }
522 }
523 
524 
526 {
527  wxASSERT( aItem != NULL );
528 
529  // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
530  // omitted when saving to disk.
531  if( aItem->Type() == LIB_FIELD_T )
532  {
533  LIB_FIELD* field = (LIB_FIELD*) aItem;
534 
535  if( field->GetId() < MANDATORY_FIELDS )
536  {
537  wxLogWarning( _(
538  "An attempt was made to remove the %s field from component %s in library %s." ),
539  GetChars( field->GetName() ), GetChars( GetName() ),
540  GetChars( GetLibraryName() ) );
541  return;
542  }
543  }
544 
545  LIB_ITEMS& items = m_drawings[ aItem->Type() ];
546 
547  for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
548  {
549  if( *i == aItem )
550  {
551  items.erase( i );
552  SetModified();
553  break;
554  }
555  }
556 }
557 
558 
560 {
561  if( !aItem )
562  return;
563 
564  m_drawings.push_back( aItem );
565 }
566 
567 
569 {
570  if( aItem == NULL )
571  {
573 
574  return (it1 != m_drawings.end( aType ) ) ? &( *( m_drawings.begin( aType ) ) ) : nullptr;
575  }
576 
577  // Search for the last item, assume aItem is of type aType
578  wxASSERT( ( aType == TYPE_NOT_INIT ) || ( aType == aItem->Type() ) );
580 
581  while( ( it != m_drawings.end( aType ) ) && ( aItem != &( *it ) ) )
582  ++it;
583 
584  // Search the next item
585  if( it != m_drawings.end( aType ) )
586  {
587  ++it;
588 
589  if( it != m_drawings.end( aType ) )
590  return &( *it );
591  }
592 
593  return NULL;
594 }
595 
596 
597 void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
598 {
599  /* Notes:
600  * when aUnit == 0: no unit filtering
601  * when aConvert == 0: no convert (shape selection) filtering
602  * when .m_Unit == 0, the body item is common to units
603  * when .m_Convert == 0, the body item is common to shapes
604  */
605  for( LIB_ITEM& item : m_drawings[ LIB_PIN_T ] )
606  {
607  // Unit filtering:
608  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
609  continue;
610 
611  // Shape filtering:
612  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
613  continue;
614 
615  aList.push_back( (LIB_PIN*) &item );
616  }
617 }
618 
619 
620 LIB_PIN* LIB_PART::GetPin( const wxString& aNumber, int aUnit, int aConvert )
621 {
622  LIB_PINS pinList;
623 
624  GetPins( pinList, aUnit, aConvert );
625 
626  for( size_t i = 0; i < pinList.size(); i++ )
627  {
628  wxASSERT( pinList[i]->Type() == LIB_PIN_T );
629 
630  if( aNumber == pinList[i]->GetNumber() )
631  return pinList[i];
632  }
633 
634  return NULL;
635 }
636 
637 
638 bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames,
639  bool aTestType, bool aTestOrientation, bool aTestLength )
640 {
641  LIB_PINS thisPinList;
642  GetPins( thisPinList, /* aUnit */ 0, /* aConvert */ 0 );
643 
644  for( LIB_PIN* eachThisPin : thisPinList )
645  {
646  wxASSERT( eachThisPin );
647  LIB_PINS otherPinList;
648  aOtherPart.GetPins( otherPinList, /* aUnit */ 0, /* aConvert */ 0 );
649  bool foundMatch = false;
650 
651  for( LIB_PIN* eachOtherPin : otherPinList )
652  {
653  wxASSERT( eachOtherPin );
654  // Same position?
655  if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
656  continue;
657 
658  // Same number?
659  if( aTestNums && ( eachThisPin->GetNumber() != eachOtherPin->GetNumber() ) )
660  continue;
661 
662  // Same name?
663  if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() ) )
664  continue;
665 
666  // Same electrical type?
667  if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() ) )
668  continue;
669 
670  // Same orientation?
671  if( aTestOrientation
672  && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() ) )
673  continue;
674 
675  // Same length?
676  if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() ) )
677  continue;
678 
679  foundMatch = true;
680  }
681 
682  if( !foundMatch )
683  {
684  // This means there was not an identical (according to the arguments)
685  // pin at the same position in the other component.
686  return true;
687  }
688  }
689 
690  // The loop never gave up, so no conflicts were found.
691  return false;
692 }
693 
694 
695 const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const
696 {
697  EDA_RECT bBox;
698  bool initialized = false;
699 
700  for( const LIB_ITEM& item : m_drawings )
701  {
702  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
703  && ( aUnit != item.m_Unit ) ) )
704  continue;
705 
706  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
707  continue;
708 
709  if ( ( item.Type() == LIB_FIELD_T ) && !( ( LIB_FIELD& ) item ).IsVisible() )
710  continue;
711 
712  if( initialized )
713  bBox.Merge( item.GetBoundingBox() );
714  else
715  {
716  bBox = item.GetBoundingBox();
717  initialized = true;
718  }
719  }
720 
721  return bBox;
722 }
723 
724 
725 void LIB_PART::ViewGetLayers( int aLayers[], int& aCount ) const
726 {
727  aCount = 6;
728  aLayers[0] = LAYER_DEVICE;
729  aLayers[1] = LAYER_DEVICE_BACKGROUND;
730  aLayers[2] = LAYER_REFERENCEPART;
731  aLayers[3] = LAYER_VALUEPART;
732  aLayers[4] = LAYER_FIELDS;
733  aLayers[5] = LAYER_SELECTION_SHADOWS;
734 }
735 
736 
737 const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
738 {
739  EDA_RECT bBox;
740  bool initialized = false;
741 
742  for( const LIB_ITEM& item : m_drawings )
743  {
744  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
745  && ( aUnit != item.m_Unit ) ) )
746  continue;
747 
748  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
749  continue;
750 
751  if( item.Type() == LIB_FIELD_T )
752  continue;
753 
754  if( initialized )
755  bBox.Merge( item.GetBoundingBox() );
756  else
757  {
758  bBox = item.GetBoundingBox();
759  initialized = true;
760  }
761  }
762 
763  return bBox;
764 }
765 
766 
768 {
769  m_drawings[ LIB_FIELD_T ].clear();
770 }
771 
772 
773 void LIB_PART::SetFields( const std::vector <LIB_FIELD>& aFields )
774 {
775  deleteAllFields();
776 
777  for( unsigned i=0; i<aFields.size(); ++i )
778  {
779  // drawings is a ptr_vector, new and copy an object on the heap.
780  LIB_FIELD* field = new LIB_FIELD( aFields[i] );
781 
782  field->SetParent( this );
783  m_drawings.push_back( field );
784  }
785 }
786 
787 
789 {
790  LIB_FIELD* field;
791 
792  // Grab the MANDATORY_FIELDS first, in expected order given by
793  // enum NumFieldType
794  for( int id=0; id<MANDATORY_FIELDS; ++id )
795  {
796  field = GetField( id );
797 
798  // the MANDATORY_FIELDS are exactly that in RAM.
799  wxASSERT( field );
800 
801  aList.push_back( *field );
802  }
803 
804  // Now grab all the rest of fields.
805  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
806  {
807  field = ( LIB_FIELD* ) &item;
808 
809  if( (unsigned) field->GetId() < MANDATORY_FIELDS )
810  continue; // was added above
811 
812  aList.push_back( *field );
813  }
814 }
815 
816 
817 LIB_FIELD* LIB_PART::GetField( int aId ) const
818 {
819  for( const LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
820  {
821  LIB_FIELD* field = ( LIB_FIELD* ) &item;
822 
823  if( field->GetId() == aId )
824  return field;
825  }
826 
827  return NULL;
828 }
829 
830 
831 LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
832 {
833  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
834  {
835  LIB_FIELD* field = ( LIB_FIELD* ) &item;
836 
837  if( field->GetName() == aFieldName )
838  return field;
839  }
840 
841  return NULL;
842 }
843 
844 
846 {
847  LIB_FIELD* field = GetField( VALUE );
848  wxASSERT( field != NULL );
849  return *field;
850 }
851 
852 
854 {
855  LIB_FIELD* field = GetField( REFERENCE );
856  wxASSERT( field != NULL );
857  return *field;
858 }
859 
860 
862 {
863  LIB_FIELD* field = GetField( FOOTPRINT );
864  wxASSERT( field != NULL );
865  return *field;
866 }
867 
868 
869 void LIB_PART::SetOffset( const wxPoint& aOffset )
870 {
871  for( LIB_ITEM& item : m_drawings )
872  item.Offset( aOffset );
873 }
874 
875 
877 {
878  m_drawings.unique();
879 }
880 
881 
883 {
884  for( const LIB_ITEM& item : m_drawings )
885  {
886  if( item.m_Convert > LIB_ITEM::LIB_CONVERT::BASE )
887  return true;
888  }
889 
890  if( PART_SPTR parent = m_parent.lock() )
891  {
892  for( const LIB_ITEM& item : parent->GetDrawItems() )
893  {
894  if( item.m_Convert > LIB_ITEM::LIB_CONVERT::BASE )
895  return true;
896  }
897  }
898 
899  return false;
900 }
901 
902 
904 {
905  for( LIB_ITEM& item : m_drawings )
906  item.ClearTempFlags();
907 }
908 
909 
911 {
912  for( LIB_ITEM& item : m_drawings )
913  item.ClearEditFlags();
914 }
915 
916 
917 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
918  KICAD_T aType, const wxPoint& aPoint )
919 {
920  for( LIB_ITEM& item : m_drawings )
921  {
922  if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
923  || ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
924  || ( ( item.Type() != aType ) && ( aType != TYPE_NOT_INIT ) ) )
925  continue;
926 
927  if( item.HitTest( aPoint ) )
928  return &item;
929  }
930 
931  return NULL;
932 }
933 
934 
935 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
936  const wxPoint& aPoint, const TRANSFORM& aTransform )
937 {
938  /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
939  * wxPoint& pt ) to search items.
940  * because this function uses DefaultTransform as orient/mirror matrix
941  * we temporary copy aTransform in DefaultTransform
942  */
943  LIB_ITEM* item;
944  TRANSFORM transform = DefaultTransform;
945  DefaultTransform = aTransform;
946 
947  item = LocateDrawItem( aUnit, aConvert, aType, aPoint );
948 
949  // Restore matrix
950  DefaultTransform = transform;
951 
952  return item;
953 }
954 
955 
956 SEARCH_RESULT LIB_PART::Visit( INSPECTOR aInspector, void* aTestData, const KICAD_T aFilterTypes[] )
957 {
958  // The part itself is never inspected, only its children
959  for( LIB_ITEM& item : m_drawings )
960  {
961  if( item.IsType( aFilterTypes ) )
962  {
963  if( aInspector( &item, aTestData ) == SEARCH_QUIT )
964  return SEARCH_QUIT;
965  }
966  }
967 
968  return SEARCH_CONTINUE;
969 }
970 
971 
972 void LIB_PART::SetUnitCount( int aCount )
973 {
974  if( m_unitCount == aCount )
975  return;
976 
977  if( aCount < m_unitCount )
978  {
980 
981  while( i != m_drawings.end() )
982  {
983  if( i->m_Unit > aCount )
984  i = m_drawings.erase( i );
985  else
986  ++i;
987  }
988  }
989  else
990  {
991  int prevCount = m_unitCount;
992 
993  // Temporary storage for new items, as adding new items directly to
994  // m_drawings may cause the buffer reallocation which invalidates the
995  // iterators
996  std::vector< LIB_ITEM* > tmp;
997 
998  for( LIB_ITEM& item : m_drawings )
999  {
1000  if( item.m_Unit != 1 )
1001  continue;
1002 
1003  for( int j = prevCount + 1; j <= aCount; j++ )
1004  {
1005  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1006  newItem->m_Unit = j;
1007  tmp.push_back( newItem );
1008  }
1009  }
1010 
1011  for( auto item : tmp )
1012  m_drawings.push_back( item );
1013  }
1014 
1015  m_unitCount = aCount;
1016 }
1017 
1018 
1020 {
1021  if( PART_SPTR parent = m_parent.lock() )
1022  return parent->GetUnitCount();
1023 
1024  return m_unitCount;
1025 }
1026 
1027 
1028 void LIB_PART::SetConversion( bool aSetConvert )
1029 {
1030  if( aSetConvert == HasConversion() )
1031  return;
1032 
1033  // Duplicate items to create the converted shape
1034  if( aSetConvert )
1035  {
1036  std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
1037 
1038  for( LIB_ITEM& item : m_drawings )
1039  {
1040  // Only pins are duplicated.
1041  if( item.Type() != LIB_PIN_T )
1042  continue;
1043 
1044  if( item.m_Convert == 1 )
1045  {
1046  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1047  newItem->m_Convert = 2;
1048  tmp.push_back( newItem );
1049  }
1050  }
1051 
1052  // Transfer the new pins to the LIB_PART.
1053  for( unsigned i = 0; i < tmp.size(); i++ )
1054  m_drawings.push_back( tmp[i] );
1055  }
1056  else
1057  {
1058  // Delete converted shape items because the converted shape does
1059  // not exist
1061 
1062  while( i != m_drawings.end() )
1063  {
1064  if( i->m_Convert > 1 )
1065  i = m_drawings.erase( i );
1066  else
1067  ++i;
1068  }
1069  }
1070 }
1071 
1072 
1073 void LIB_PART::SetSubpartIdNotation( int aSep, int aFirstId )
1074 {
1075  m_subpartFirstId = 'A';
1077 
1078  if( aSep == '.' || aSep == '-' || aSep == '_' )
1079  m_subpartIdSeparator = aSep;
1080 
1081  if( aFirstId == '1' && aSep != 0 )
1082  m_subpartFirstId = aFirstId;
1083 }
timestamp_t m_dateLastEdition
Date of the last modification.
const wxString GetName() const
Return the file name without path or extension.
LIB_FIELD & GetFootprintField()
Return reference to the footprint field.
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:366
void SetLib(PART_LIB *aLibrary)
bool PinsConflictWith(LIB_PART &aOtherPart, bool aTestNums, bool aTestNames, bool aTestType, bool aTestOrientation, bool aTestLength)
Return true if this part's pins do not match another part's pins.
void SetModified()
Definition: base_struct.cpp:98
static int m_subpartIdSeparator
the separator char between the subpart id and the reference like U1A ( m_subpartIdSeparator = 0 ) or ...
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:183
void SetConversion(bool aSetConvert)
Set or clear the alternate body style (DeMorgan) for the part.
virtual ~LIB_PART()
name of datasheet
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
bool m_showPinNumbers
Determines if part pin numbers are visible.
wxString GetName() const override
const wxString GetLibraryName() const
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
virtual void SetColor(COLOR4D color)=0
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
bool IsVisible() const
Definition: eda_text.h:170
int m_unitCount
Number of units (parts) per package.
LIB_ITEM * GetNextDrawItem(LIB_ITEM *aItem=NULL, KICAD_T aType=TYPE_NOT_INIT)
Return the next draw object pointer.
PART_LIB * m_library
Library the part belongs to if any.
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Field object used in symbol libraries.
Definition: lib_field.h:59
static int m_subpartFirstId
the ASCII char value to calculate the subpart symbol id from the part number: only 'A',...
void unique()
Remove duplicate elements in list.
Definition: multivector.h:238
LIB_ITEMS_CONTAINER m_drawings
Drawing items of this part.
LIB_FIELD & GetValueField()
Return reference to the value field.
int Compare(const LIB_PART &aRhs) const
Comparison test that can be used for operators.
int m_Unit
Unit identification for multiple parts per package.
Definition: lib_item.h:82
wxString m_docFileName
Associate doc file name.
int GetId() const
Definition: lib_field.h:135
wxString GetKeyWords() const
LIBRENTRYOPTIONS m_options
Special part features such as POWER or NORMAL.)
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Definition: eeschema.cpp:167
int compare(const LIB_ID &aLibId) const
Compare the contents of LIB_ID objects by performing a std::string comparison of the library nickname...
Definition: lib_id.cpp:316
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
bool draw_hidden_fields
Whether to draw "hidden" fields.
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
bool m_unitsLocked
True if part has multiple units and changing one unit does not automatically change another unit.
void ClearTempFlags()
Clears the status flag all draw objects in this part.
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
The base class for drawable items used by schematic library components.
Definition: lib_item.h:61
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
This file contains miscellaneous commonly used macros and functions.
void PlotLibFields(PLOTTER *aPlotter, int aUnit, int aConvert, const wxPoint &aOffset, const TRANSFORM &aTransform)
Plot Lib Fields only of the part to plotter.
void SetOffset(const wxPoint &aOffset)
Move the part aOffset.
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:189
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
#define IS_NEW
New item, just created.
Definition: base_struct.h:120
int m_pinNameOffset
The offset in mils to draw the pin name.
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0)
Return a list of pin object pointers from the draw item list.
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:108
void deleteAllFields()
PART_REF m_parent
Use for inherited symbols.
#define VALUE
void Print(wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Print part.
void operator()(void const *) const
Class for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void Plot(PLOTTER *aPlotter, int aUnit, int aConvert, const wxPoint &aOffset, const TRANSFORM &aTransform)
Plot lib part to plotter.
LIB_FIELD * FindField(const wxString &aFieldName)
Find a field within this part matching aFieldName and returns it or NULL if not found.
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:126
int GetUnitCount() const override
For items with units, return the number of units.
wxString m_name
Symbol name.
void SetUnitCount(int count)
Set the units per part count.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:225
void push_back(T *aItem)
Definition: multivector.h:169
Class LIB_PIN definition.
std::shared_ptr< LIB_PART > PART_SPTR
shared pointer to LIB_PART
PART_SPTR SharedPtr()
void SetParent(LIB_PART *aParent=nullptr)
Define a library symbol object.
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:129
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
wxLogTrace helper definitions.
wxString GetDocFileName() const
wxString GetDescription() override
LIB_PART(const wxString &aName, LIB_PART *aParent=nullptr, PART_LIB *aLibrary=nullptr)
void RemoveDuplicateDrawItems()
Remove duplicate draw items from list.
wxArrayString m_FootprintList
List of suitable footprint names for the part (wild card names accepted).
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
#define _(s)
LIB_ID m_libId
int SetLibItemName(const UTF8 &aLibItemName, bool aTestForRev=true)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition: lib_id.cpp:206
ITERATOR erase(const ITERATOR &aIterator)
Definition: multivector.h:174
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared
ITERATOR_BASE< LIB_ITEM, MULTIVECTOR< LIB_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The non-const iterator
Definition: multivector.h:160
wxString GetUnitReference(int aUnit) override
Return an identifier for aUnit for symbols with units.
Base plotter engine class.
Definition: plotter.h:97
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:101
TRANSFORM DefaultTransform
Definition: eeschema.cpp:50
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
static void SetSubpartIdNotation(int aSep, int aFirstId)
Set the separator char between the subpart id and the reference 0 (no separator) or '.
void ClearEditFlags()
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:214
size_t i
Definition: json11.cpp:649
bool IsAlias() const
const EDA_RECT GetUnitBoundingBox(int aUnit, int aConvert) const
Get the bounding box for the symbol.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: lib_field.cpp:300
static wxString SubReference(int aUnit, bool aAddSeparator=true)
wxString GetSearchText() override
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:163
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...
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, LIB_ID_TYPE aType, bool aLib=false)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:352
int m_Convert
Shape identification for alternate body styles.
Definition: lib_item.h:88
ITERATOR_BASE< const LIB_ITEM, const MULTIVECTOR< LIB_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::const_iterator > CONST_ITERATOR
The const iterator
Definition: multivector.h:162
LIB_ITEM * LocateDrawItem(int aUnit, int aConvert, KICAD_T aType, const wxPoint &aPoint)
Locate a draw object.
virtual void SetName(const wxString &aName)
wxString m_keyWords
keyword list (used for search for parts by keyword)
bool operator<(const LIB_PART &aItem1, const LIB_PART &aItem2)
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:129
Definition for part library class.
bool draw_visible_fields
Whether to draw "visible" fields.
SEARCH_RESULT
Definition: base_struct.h:54
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
Definition: gr_basic.cpp:210
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:267
LIB_FIELD * GetField(int aId) const
Return pointer to the requested field.
bool m_showPinNames
Determines if part pin names are visible.
const EDA_RECT GetBodyBoundingBox(int aUnit, int aConvert) const
Get the symbol bounding box excluding fields.
void SetFields(const std::vector< LIB_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
wxString m_description
documentation for info
Object used to load, save, search, and otherwise manipulate symbol library files.
virtual const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:124
size_t size(int aType=UNDEFINED_TYPE) const
Definition: multivector.h:207
TRANSFORM transform
Coordinate adjustment settings.
void GetFields(LIB_FIELDS &aList)
Return a list of fields within this part.
LIB_PIN * GetPin(const wxString &aNumber, int aUnit=0, int aConvert=0)
Return pin object with the requested pin aNumber.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210
void RemoveDrawItem(LIB_ITEM *aItem)
Remove draw aItem from list.
PART_SPTR m_me
< http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared
bool GetColorMode() const
Definition: plotter.h:131