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-2017 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2017 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 
30 #include <fctsys.h>
31 #include <macros.h>
32 #include <kicad_string.h>
33 #include <class_drawpanel.h>
34 #include <plot_common.h>
35 #include <gr_basic.h>
36 #include <class_sch_screen.h>
37 #include <richio.h>
38 
39 #include <general.h>
40 #include <template_fieldnames.h>
41 #include <transform.h>
42 #include <class_library.h>
43 #include <class_libentry.h>
44 #include <lib_pin.h>
45 #include <lib_arc.h>
46 #include <lib_bezier.h>
47 #include <lib_circle.h>
48 #include <lib_polyline.h>
49 #include <lib_rectangle.h>
50 #include <lib_text.h>
51 
52 
53 // the separator char between the subpart id and the reference
54 // 0 (no separator) or '.' or some other character
56 
57 // the ascii char value to calculate the subpart symbol id from the part number:
58 // 'A' or '1' usually. (to print U1.A or U1.1)
59 // if this a a digit, a number is used as id symbol
61 
62 
63 const wxChar traceSchLibMem[] = wxT( "KISCHLIBMEM" ); // public
64 
65 
66 LIB_ALIAS::LIB_ALIAS( const wxString& aName, LIB_PART* aRootPart ):
68  shared( aRootPart )
69 {
70  name = aName;
71 }
72 
73 
74 LIB_ALIAS::LIB_ALIAS( const LIB_ALIAS& aAlias, LIB_PART* aRootPart ) :
75  EDA_ITEM( aAlias ),
76  shared( aRootPart )
77 {
78  name = aAlias.name;
79 
80  description = aAlias.description;
81  keyWords = aAlias.keyWords;
82  docFileName = aAlias.docFileName;
83 }
84 
85 
87 {
88  wxASSERT_MSG( shared, wxT( "~LIB_ALIAS() without a LIB_PART" ) );
89 
90  wxLogTrace( traceSchLibMem,
91  wxT( "%s: destroying alias:'%s' of part:'%s'." ),
92  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( name ),
93  GetChars( shared->GetName() ) );
94 
95  if( shared )
96  shared->RemoveAlias( this );
97 }
98 
99 
101 {
102  wxASSERT_MSG( shared, wxT( "LIB_ALIAS without a LIB_PART" ) );
103 
104  if( shared )
105  return shared->GetLibraryName();
106 
107  return wxString( _( "none" ) );
108 }
109 
110 
111 bool LIB_ALIAS::IsRoot() const
112 {
113  return name == shared->GetName();
114 }
115 
116 
118 {
119  return shared->GetLib();
120 }
121 
122 
124 {
125  if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
126  return true;
127 
128  try
129  {
130  aFormatter.Print( 0, "#\n$CMP %s\n", TO_UTF8( name ) );
131 
132  if( !description.IsEmpty() )
133  aFormatter.Print( 0, "D %s\n", TO_UTF8( description ) );
134 
135  if( !keyWords.IsEmpty() )
136  aFormatter.Print( 0, "K %s\n", TO_UTF8( keyWords ) );
137 
138  if( !docFileName.IsEmpty() )
139  aFormatter.Print( 0, "F %s\n", TO_UTF8( docFileName ) );
140 
141  aFormatter.Print( 0, "$ENDCMP\n" );
142  }
143  catch( const IO_ERROR& )
144  {
145  return false;
146  }
147 
148  return true;
149 }
150 
151 
152 bool LIB_ALIAS::operator==( const wxChar* aName ) const
153 {
154  return name == aName;
155 }
156 
157 
158 bool operator<( const LIB_ALIAS& aItem1, const LIB_ALIAS& aItem2 )
159 {
160  return aItem1.GetName() < aItem2.GetName();
161 }
162 
163 
164 int LibraryEntryCompare( const LIB_ALIAS* aItem1, const LIB_ALIAS* aItem2 )
165 {
166  return aItem1->GetName().Cmp( aItem2->GetName() );
167 }
168 
169 
172 {
173  void operator()(void const *) const
174  {
175  }
176 };
177 
178 
179 LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
180  EDA_ITEM( LIB_PART_T ),
181  m_me( this, null_deleter() )
182 {
183  m_name = aName;
184  m_library = aLibrary;
185  m_dateModified = 0;
186  m_unitCount = 1;
187  m_pinNameOffset = 40;
189  m_unitsLocked = false;
190  m_showPinNumbers = true;
191  m_showPinNames = true;
192 
193  // Create the default alias if the name parameter is not empty.
194  if( !aName.IsEmpty() )
195  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
196 
197  // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present
198  // when the field editors are invoked.
199  LIB_FIELD* value = new LIB_FIELD( this, VALUE );
200  value->SetText( aName );
201  drawings.push_back( value );
202 
203  drawings.push_back( new LIB_FIELD( this, REFERENCE ) );
204  drawings.push_back( new LIB_FIELD( this, FOOTPRINT ) );
205  drawings.push_back( new LIB_FIELD( this, DATASHEET ) );
206 }
207 
208 
209 LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
210  EDA_ITEM( aPart ),
211  m_me( this, null_deleter() )
212 {
213  LIB_ITEM* newItem;
214 
215  m_library = aLibrary;
216  m_name = aPart.m_name;
218  m_unitCount = aPart.m_unitCount;
224  m_options = aPart.m_options;
225 
226  for( LIB_ITEM& oldItem : aPart.GetDrawItemList() )
227  {
228  if( oldItem.IsNew() )
229  continue;
230 
231  newItem = (LIB_ITEM*) oldItem.Clone();
232  newItem->SetParent( this );
233  drawings.push_back( newItem );
234  }
235 
236  for( size_t i = 0; i < aPart.m_aliases.size(); i++ )
237  {
238  LIB_ALIAS* alias = new LIB_ALIAS( *aPart.m_aliases[i], this );
239  m_aliases.push_back( alias );
240  }
241 }
242 
243 
245 {
246  wxLogTrace( traceSchLibMem,
247  wxT( "%s: destroying part '%s' with alias list count of %llu." ),
248  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( GetName() ),
249  (long long unsigned) m_aliases.size() );
250 
251  // If the part is being deleted directly rather than through the library,
252  // delete all of the aliases.
253  while( m_aliases.size() )
254  {
255  LIB_ALIAS* alias = m_aliases.back();
256  m_aliases.pop_back();
257  delete alias;
258  }
259 }
260 
261 
262 const wxString LIB_PART::GetLibraryName()
263 {
264  if( m_library )
265  return m_library->GetName();
266 
267  return wxString( _( "none" ) );
268 }
269 
270 
271 wxString LIB_PART::SubReference( int aUnit, bool aAddSeparator )
272 {
273  wxString subRef;
274 
275  if( m_subpartIdSeparator != 0 && aAddSeparator )
276  subRef << wxChar( m_subpartIdSeparator );
277 
278  if( m_subpartFirstId >= '0' && m_subpartFirstId <= '9' )
279  subRef << aUnit;
280  else
281  {
282  // use letters as notation. To allow more than 26 units, the sub ref
283  // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
284  // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
285  int u;
286  aUnit -= 1; // Unit number starts to 1. now to 0.
287 
288  while( aUnit >= 26 ) // more than one letter are needed
289  {
290  u = aUnit / 26;
291  subRef << wxChar( m_subpartFirstId + u -1 );
292  aUnit %= 26;
293  }
294 
295  u = m_subpartFirstId + aUnit;
296  subRef << wxChar( u );
297  }
298 
299  return subRef;
300 }
301 
302 
303 void LIB_PART::SetName( const wxString& aName )
304 {
305  m_name = aName;
306  GetValueField().SetText( aName );
307 
308  // The LIB_ALIAS that is the LIB_PART name has to be created so create it.
309  if( m_aliases.size() == 0 )
310  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
311  else
312  m_aliases[0]->SetName( aName );
313 }
314 
315 
316 void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
317  int aMulti, int aConvert, const PART_DRAW_OPTIONS& aOpts )
318 {
319  BASE_SCREEN* screen = aPanel ? aPanel->GetScreen() : NULL;
320 
321  GRSetDrawMode( aDc, aOpts.draw_mode );
322 
323  /* draw background for filled items using background option
324  * Solid lines will be drawn after the background
325  * Note also, background is not drawn when:
326  * printing in black and white
327  * If the color is not the default color (aColor != -1 )
328  */
329  if( ! ( screen && screen->m_IsPrinting && GetGRForceBlackPenState() )
330  && ( aOpts.color == COLOR4D::UNSPECIFIED ) )
331  {
332  for( LIB_ITEM& drawItem : drawings )
333  {
334  if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
335  continue;
336 
337  if( aOpts.only_selected && !drawItem.IsSelected() )
338  continue;
339 
340  // Do not draw an item while moving (the cursor handler does that)
341  if( drawItem.m_Flags & IS_MOVED )
342  continue;
343 
344  // Do not draw items not attached to the current part
345  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
346  continue;
347 
348  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
349  continue;
350 
351  if( drawItem.Type() == LIB_FIELD_T )
352  continue;
353 
354  if( drawItem.Type() == LIB_FIELD_T )
355  {
356  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
357  aOpts.draw_mode, (void*) NULL, aOpts.transform );
358  }
359 
360  // Now, draw only the background for items with
361  // m_Fill == FILLED_WITH_BG_BODYCOLOR:
362  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
363  aOpts.draw_mode, (void*) false, aOpts.transform );
364  }
365  }
366 
367  // Track the index into the dangling pins list
368  size_t pin_index = 0;
369 
370  for( LIB_ITEM& drawItem : drawings )
371  {
372  if( aOpts.only_selected && !drawItem.IsSelected() )
373  continue;
374 
375  // Do not draw an item while moving (the cursor handler does that)
376  if( drawItem.m_Flags & IS_MOVED )
377  continue;
378 
379  // Do not draw items not attached to the current part
380  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
381  continue;
382 
383  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
384  continue;
385 
386  if( drawItem.Type() == LIB_FIELD_T )
387  {
388  LIB_FIELD& field = dynamic_cast<LIB_FIELD&>( drawItem );
389 
390  if( field.IsVisible() && !aOpts.draw_visible_fields )
391  continue;
392 
393  if( !field.IsVisible() && !aOpts.draw_hidden_fields )
394  continue;
395  }
396 
397  if( drawItem.Type() == LIB_PIN_T )
398  {
399  LIB_PIN& pin = dynamic_cast<LIB_PIN&>( drawItem );
400 
401  uintptr_t flags = 0;
402  if( aOpts.show_pin_text )
403  flags |= PIN_DRAW_TEXTS;
404 
405  if( aOpts.show_elec_type )
407 
408  if( aOpts.PinIsDangling( pin_index ) )
409  flags |= PIN_DRAW_DANGLING;
410 
411  if( pin.IsPowerConnection() && IsPower() )
412  flags |= PIN_DANGLING_HIDDEN;
413 
414  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
415  aOpts.draw_mode, (void*) flags, aOpts.transform );
416 
417  ++pin_index;
418  }
419  else if( drawItem.Type() == LIB_FIELD_T )
420  {
421  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
422  aOpts.draw_mode, (void*) NULL, aOpts.transform );
423  }
424  else
425  {
426  bool forceNoFill = drawItem.m_Fill == FILLED_WITH_BG_BODYCOLOR;
427  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
428  aOpts.draw_mode, (void*) forceNoFill,
429  aOpts.transform );
430  }
431 
432  }
433 
434  // Enable this to draw the anchor of the component.
435 #if 0
436  int len = aDc->DeviceToLogicalXRel( 3 );
437  EDA_RECT* const clipbox = aPanel ? aPanel->GetClipBox() : NULL;
438 
439  GRLine( clipbox, aDc, aOffset.x, aOffset.y - len, aOffset.x,
440  aOffset.y + len, 0, aOpts.color );
441  GRLine( clipbox, aDc, aOffset.x - len, aOffset.y, aOffset.x + len,
442  aOffset.y, 0, aOpts.color );
443 #endif
444 
445  /* Enable this to draw the bounding box around the component to validate
446  * the bounding box calculations. */
447 #if 0
448  EDA_RECT bBox = GetUnitBoundingBox( aMulti, aConvert );
449  bBox.RevertYAxis();
450  bBox = aOpts.transform.TransformCoordinate( bBox );
451  bBox.Move( aOffset );
452  GRRect( aPanel ? aPanel->GetClipBox() : NULL, aDc, bBox, 0, LIGHTMAGENTA );
453 #endif
454 }
455 
456 
457 void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
458  const wxPoint& aOffset, const TRANSFORM& aTransform )
459 {
460  wxASSERT( aPlotter != NULL );
461 
462  aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) );
463  bool fill = aPlotter->GetColorMode();
464 
465  // draw background for filled items using background option
466  // Solid lines will be drawn after the background
467  for( LIB_ITEM& item : drawings )
468  {
469  // Lib Fields are not plotted here, because this plot function
470  // is used to plot schematic items, which have they own fields
471  if( item.Type() == LIB_FIELD_T )
472  continue;
473 
474  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
475  continue;
476 
477  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
478  continue;
479 
480  if( item.m_Fill == FILLED_WITH_BG_BODYCOLOR )
481  item.Plot( aPlotter, aOffset, fill, aTransform );
482  }
483 
484  // Not filled items and filled shapes are now plotted
485  // (plot only items which are not already plotted)
486  for( LIB_ITEM& item : drawings )
487  {
488  if( item.Type() == LIB_FIELD_T )
489  continue;
490 
491  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
492  continue;
493 
494  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
495  continue;
496 
497  if( item.m_Fill != FILLED_WITH_BG_BODYCOLOR )
498  item.Plot( aPlotter, aOffset, fill, aTransform );
499  }
500 }
501 
502 void LIB_PART::PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
503  const wxPoint& aOffset, const TRANSFORM& aTransform )
504 {
505  wxASSERT( aPlotter != NULL );
506 
507  aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
508  bool fill = aPlotter->GetColorMode();
509 
510  for( LIB_ITEM& item : drawings )
511  {
512  if( item.Type() != LIB_FIELD_T )
513  continue;
514 
515  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
516  continue;
517 
518  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
519  continue;
520 
521  // The reference is a special case: we should change the basic text
522  // to add '?' and the part id
523  LIB_FIELD& field = (LIB_FIELD&) item;
524  wxString tmp = field.GetShownText();
525  if( field.GetId() == REFERENCE )
526  {
527  wxString text = field.GetFullText( aUnit );
528  field.SetText( text );
529  }
530  item.Plot( aPlotter, aOffset, fill, aTransform );
531  field.SetText( tmp );
532  }
533 }
534 
535 
536 void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aDc )
537 {
538  wxASSERT( aItem != NULL );
539 
540  // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
541  // omitted when saving to disk.
542  if( aItem->Type() == LIB_FIELD_T )
543  {
544  LIB_FIELD* field = (LIB_FIELD*) aItem;
545 
546  if( field->GetId() < MANDATORY_FIELDS )
547  {
548  wxLogWarning( _(
549  "An attempt was made to remove the %s field from component %s in library %s." ),
550  GetChars( field->GetName() ), GetChars( GetName() ),
551  GetChars( GetLibraryName() ) );
552  return;
553  }
554  }
555 
556  LIB_ITEMS::iterator i;
557 
558  for( i = drawings.begin(); i != drawings.end(); i++ )
559  {
560  if( *i == aItem )
561  {
562  if( aDc != NULL )
563  aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), COLOR4D::UNSPECIFIED,
564  g_XorMode, NULL, DefaultTransform );
565 
566  drawings.erase( i );
567  SetModified();
568  break;
569  }
570  }
571 }
572 
573 
575 {
576  wxASSERT( aItem != NULL );
577 
578  drawings.push_back( aItem );
579  drawings.sort();
580 }
581 
582 
584 {
585  /* Return the next draw object pointer.
586  * If item is NULL return the first item of type in the list.
587  */
588  if( drawings.empty() )
589  return NULL;
590 
591  if( aItem == NULL && aType == TYPE_NOT_INIT ) // type is unspecified
592  return &drawings[0];
593 
594  // Search for last item
595  size_t idx = 0;
596 
597  if( aItem )
598  {
599  for( ; idx < drawings.size(); idx++ )
600  {
601  if( aItem == &drawings[idx] )
602  {
603  idx++; // Prepare the next item search
604  break;
605  }
606  }
607  }
608 
609  // Search the next item
610  for( ; idx < drawings.size(); idx++ )
611  {
612  if( aType == TYPE_NOT_INIT || drawings[ idx ].Type() == aType )
613  return &drawings[ idx ];
614  }
615 
616  return NULL;
617 }
618 
619 
620 void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
621 {
622  /* Notes:
623  * when aUnit == 0: no unit filtering
624  * when aConvert == 0: no convert (shape selection) filtering
625  * when .m_Unit == 0, the body item is common to units
626  * when .m_Convert == 0, the body item is common to shapes
627  */
628  for( LIB_ITEM& item : drawings )
629  {
630  if( item.Type() != LIB_PIN_T ) // we search pins only
631  continue;
632 
633  // Unit filtering:
634  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
635  continue;
636 
637  // Shape filtering:
638  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
639  continue;
640 
641  aList.push_back( (LIB_PIN*) &item );
642  }
643 }
644 
645 
646 LIB_PIN* LIB_PART::GetPin( const wxString& aNumber, int aUnit, int aConvert )
647 {
648  wxString pNumber;
649  LIB_PINS pinList;
650 
651  GetPins( pinList, aUnit, aConvert );
652 
653  for( size_t i = 0; i < pinList.size(); i++ )
654  {
655  wxASSERT( pinList[i]->Type() == LIB_PIN_T );
656 
657  pinList[i]->PinStringNum( pNumber );
658 
659  if( aNumber == pNumber )
660  return pinList[i];
661  }
662 
663  return NULL;
664 }
665 
666 
667 bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames,
668  bool aTestType, bool aTestOrientation, bool aTestLength )
669 {
670  LIB_PINS thisPinList;
671  GetPins( thisPinList, /* aUnit */ 0, /* aConvert */ 0 );
672 
673  for( LIB_PIN* eachThisPin : thisPinList )
674  {
675  wxASSERT( eachThisPin );
676  LIB_PINS otherPinList;
677  aOtherPart.GetPins( otherPinList, /* aUnit */ 0, /* aConvert */ 0 );
678  bool foundMatch = false;
679 
680  for( LIB_PIN* eachOtherPin : otherPinList )
681  {
682  wxASSERT( eachOtherPin );
683  // Same position?
684  if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
685  continue;
686 
687  // Same number?
688  wxString eachThisPinNumber, eachOtherPinNumber;
689  eachThisPin->PinStringNum( eachThisPinNumber );
690  eachOtherPin->PinStringNum( eachOtherPinNumber );
691  if( aTestNums && ( eachThisPinNumber != eachOtherPinNumber ))
692  continue;
693 
694  // Same name?
695  if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() ))
696  continue;
697 
698  // Same electrical type?
699  if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() ))
700  continue;
701 
702  // Same orientation?
703  if( aTestOrientation && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() ))
704  continue;
705 
706  // Same length?
707  if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() ))
708  continue;
709 
710  foundMatch = true;
711  }
712 
713  if( !foundMatch )
714  {
715  // This means there was not an identical (according to the arguments)
716  // pin at the same position in the other component.
717  return true;
718  }
719  }
720 
721  // The loop never gave up, so no conflicts were found.
722  return false;
723 }
724 
725 
726 bool LIB_PART::Save( OUTPUTFORMATTER& aFormatter )
727 {
728  LIB_FIELD& value = GetValueField();
729 
730  // First line: it s a comment (component name for readers)
731  aFormatter.Print( 0, "#\n# %s\n#\n", TO_UTF8( value.GetText() ) );
732 
733  // Save data
734  aFormatter.Print( 0, "DEF" );
735 
736  if( value.IsVisible() )
737  {
738  aFormatter.Print( 0, " %s", TO_UTF8( value.GetText() ) );
739  }
740  else
741  {
742  aFormatter.Print( 0, " ~%s", TO_UTF8( value.GetText() ) );
743  }
744 
745  LIB_FIELD& reference = GetReferenceField();
746 
747  if( !reference.GetText().IsEmpty() )
748  {
749  aFormatter.Print( 0, " %s", TO_UTF8( reference.GetText() ) );
750  }
751  else
752  {
753  aFormatter.Print( 0, " ~" );
754  }
755 
756  aFormatter.Print( 0, " %d %d %c %c %d %c %c\n",
757  0, m_pinNameOffset,
758  m_showPinNumbers ? 'Y' : 'N',
759  m_showPinNames ? 'Y' : 'N',
760  m_unitCount, m_unitsLocked ? 'L' : 'F',
761  m_options == ENTRY_POWER ? 'P' : 'N' );
762 
763  if( !SaveDateAndTime( aFormatter ) )
764  return false;
765 
766  LIB_FIELDS fields;
767  GetFields( fields );
768 
769  // Mandatory fields:
770  // may have their own save policy so there is a separate loop for them.
771  // Empty fields are saved, because the user may have set visibility,
772  // size and orientation
773  for( int i = 0; i < MANDATORY_FIELDS; ++i )
774  {
775  if( !fields[i].Save( aFormatter ) )
776  return false;
777  }
778 
779  // User defined fields:
780  // may have their own save policy so there is a separate loop for them.
781 
782  int fieldId = MANDATORY_FIELDS; // really wish this would go away.
783 
784  for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
785  {
786  // There is no need to save empty fields, i.e. no reason to preserve field
787  // names now that fields names come in dynamically through the template
788  // fieldnames.
789  if( !fields[i].GetText().IsEmpty() )
790  {
791  fields[i].SetId( fieldId++ );
792 
793  if( !fields[i].Save( aFormatter ) )
794  return false;
795  }
796  }
797 
798  // Save the alias list: a line starting by "ALIAS". The first alias is the root
799  // and has the same name as the component. In the old library file format this
800  // alias does not get added to the alias list.
801  if( m_aliases.size() > 1 )
802  {
803  aFormatter.Print( 0, "ALIAS" );
804 
805  for( unsigned i = 1; i < m_aliases.size(); i++ )
806  {
807  aFormatter.Print( 0, " %s", TO_UTF8( m_aliases[i]->GetName() ) );
808  }
809 
810  aFormatter.Print( 0, "\n" );
811  }
812 
813  // Write the footprint filter list
814  if( m_FootprintList.GetCount() != 0 )
815  {
816  aFormatter.Print( 0, "$FPLIST\n" );
817 
818  for( unsigned i = 0; i < m_FootprintList.GetCount(); i++ )
819  {
820  aFormatter.Print( 0, " %s\n", TO_UTF8( m_FootprintList[i] ) );
821  }
822 
823  aFormatter.Print( 0, "$ENDFPLIST\n" );
824  }
825 
826  // Save graphics items (including pins)
827  if( !drawings.empty() )
828  {
829  /* we sort the draw items, in order to have an edition more easy,
830  * when a file editing "by hand" is made */
831  drawings.sort();
832 
833  aFormatter.Print( 0, "DRAW\n" );
834 
835  for( LIB_ITEM& item : drawings )
836  {
837  if( item.Type() == LIB_FIELD_T )
838  continue;
839 
840  if( !item.Save( aFormatter ) )
841  return false;
842  }
843 
844  aFormatter.Print( 0, "ENDDRAW\n" );
845  }
846 
847  aFormatter.Print( 0, "ENDDEF\n" );
848 
849  return true;
850 }
851 
852 
853 bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg )
854 {
855  int unused;
856  char* p;
857  char* componentName;
858  char* prefix = NULL;
859  char* line;
860 
861  bool result;
862  wxString Msg;
863 
864  line = aLineReader.Line();
865 
866  p = strtok( line, " \t\r\n" );
867 
868  if( strcmp( p, "DEF" ) != 0 )
869  {
870  aErrorMsg.Printf( wxT( "DEF command expected in line %d, aborted." ),
871  aLineReader.LineNumber() );
872  return false;
873  }
874 
875  // Read DEF line:
876  char drawnum = 0;
877  char drawname = 0;
878 
879  if( ( componentName = strtok( NULL, " \t\n" ) ) == NULL // Part name:
880  || ( prefix = strtok( NULL, " \t\n" ) ) == NULL // Prefix name:
881  || ( p = strtok( NULL, " \t\n" ) ) == NULL // NumOfPins:
882  || sscanf( p, "%d", &unused ) != 1
883  || ( p = strtok( NULL, " \t\n" ) ) == NULL // TextInside:
884  || sscanf( p, "%d", &m_pinNameOffset ) != 1
885  || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums:
886  || sscanf( p, "%c", &drawnum ) != 1
887  || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums:
888  || sscanf( p, "%c", &drawname ) != 1
889  || ( p = strtok( NULL, " \t\n" ) ) == NULL // m_unitCount:
890  || sscanf( p, "%d", &m_unitCount ) != 1 )
891  {
892  aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ),
893  aLineReader.LineNumber() );
894 
895  while( (line = aLineReader.ReadLine()) != NULL )
896  {
897  p = strtok( line, " \t\n" );
898 
899  if( p && strcasecmp( p, "ENDDEF" ) == 0 )
900  break;
901  }
902 
903  return false;
904  }
905 
906  // Ensure m_unitCount is >= 1 (could be read as 0 in old libraries)
907  if( m_unitCount < 1 )
908  m_unitCount = 1;
909 
910  m_showPinNumbers = ( drawnum == 'N' ) ? false : true;
911  m_showPinNames = ( drawname == 'N' ) ? false : true;
912 
913  // Copy part name and prefix.
914  LIB_FIELD& value = GetValueField();
915 
916  if( componentName[0] != '~' )
917  {
918  m_name = FROM_UTF8( componentName );
919  value.SetText( m_name );
920  }
921  else
922  {
923  m_name = FROM_UTF8( &componentName[1] );
924  value.SetText( m_name );
925  value.SetVisible( false );
926  }
927 
928  // Add the root alias to the alias list.
929  m_aliases.push_back( new LIB_ALIAS( m_name, this ) );
930 
931  LIB_FIELD& reference = GetReferenceField();
932 
933  if( strcmp( prefix, "~" ) == 0 )
934  {
935  reference.Empty();
936  reference.SetVisible( false );
937  }
938  else
939  {
940  reference.SetText( FROM_UTF8( prefix ) );
941  }
942 
943  // Copy optional infos
944  if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'L' )
945  m_unitsLocked = true;
946 
947  if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'P' )
949 
950  // Read next lines, until "ENDDEF" is found
951  while( ( line = aLineReader.ReadLine() ) != NULL )
952  {
953  p = strtok( line, " \t\r\n" );
954 
955  // This is the error flag ( if an error occurs, result = false)
956  result = true;
957 
958  if( *line == '#' ) // a comment
959  continue;
960 
961  if( p == NULL ) // empty line
962  continue;
963 
964  if( line[0] == 'T' && line[1] == 'i' )
965  result = LoadDateAndTime( aLineReader );
966  else if( *line == 'F' )
967  result = LoadField( aLineReader, Msg );
968  else if( strcmp( p, "ENDDEF" ) == 0 ) // End of component description
969  goto ok;
970  else if( strcmp( p, "DRAW" ) == 0 )
971  result = LoadDrawEntries( aLineReader, Msg );
972  else if( strncmp( p, "ALIAS", 5 ) == 0 )
973  {
974  p = strtok( NULL, "\r\n" );
975  result = LoadAliases( p, aErrorMsg );
976  }
977  else if( strncmp( p, "$FPLIST", 5 ) == 0 )
978  result = LoadFootprints( aLineReader, Msg );
979 
980  // End line or block analysis: test for an error
981  if( !result )
982  {
983  if( Msg.IsEmpty() )
984  aErrorMsg.Printf( wxT( "error occurred at line %d " ), aLineReader.LineNumber() );
985  else
986  aErrorMsg.Printf( wxT( "error <%s> occurred at line %d " ),
987  GetChars( Msg ), aLineReader.LineNumber() );
988 
989  return false;
990  }
991  }
992 
993  return false;
994 
995 ok:
996  // If we are here, this part is O.k. - put it in:
997  drawings.sort();
998 
999  return true;
1000 }
1001 
1002 
1003 bool LIB_PART::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorMsg )
1004 {
1005  char* line;
1006  LIB_ITEM* newEntry = NULL;
1007 
1008  while( true )
1009  {
1010  if( !( line = aLineReader.ReadLine() ) )
1011  {
1012  aErrorMsg = wxT( "file ended prematurely loading component draw element" );
1013  return false;
1014  }
1015 
1016  if( strncmp( line, "ENDDRAW", 7 ) == 0 )
1017  break;
1018 
1019  newEntry = NULL;
1020 
1021  switch( line[0] )
1022  {
1023  case 'A': // Arc
1024  newEntry = ( LIB_ITEM* ) new LIB_ARC( this );
1025  break;
1026 
1027  case 'C': // Circle
1028  newEntry = ( LIB_ITEM* ) new LIB_CIRCLE( this );
1029  break;
1030 
1031  case 'T': // Text
1032  newEntry = ( LIB_ITEM* ) new LIB_TEXT( this );
1033  break;
1034 
1035  case 'S': // Square
1036  newEntry = ( LIB_ITEM* ) new LIB_RECTANGLE( this );
1037  break;
1038 
1039  case 'X': // Pin Description
1040  newEntry = ( LIB_ITEM* ) new LIB_PIN( this );
1041  break;
1042 
1043  case 'P': // Polyline
1044  newEntry = ( LIB_ITEM* ) new LIB_POLYLINE( this );
1045  break;
1046 
1047  case 'B': // Bezier Curves
1048  newEntry = ( LIB_ITEM* ) new LIB_BEZIER( this );
1049  break;
1050 
1051  case '#': // Comment
1052  continue;
1053 
1054  case '\n':
1055  case '\r':
1056  case 0: // empty line
1057  continue;
1058 
1059  default:
1060  aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), line[0] );
1061  return false;
1062  }
1063 
1064  if( !newEntry->Load( aLineReader, aErrorMsg ) )
1065  {
1066  aErrorMsg.Printf( wxT( "error '%s' in DRAW command %c" ),
1067  GetChars( aErrorMsg ), line[0] );
1068  delete newEntry;
1069 
1070  // Flush till end of draw section
1071  do
1072  {
1073  if( !aLineReader.ReadLine() )
1074  {
1075  aErrorMsg = wxT( "file ended prematurely while attempting "
1076  "to flush to end of drawing section." );
1077  return false;
1078  }
1079  } while( strncmp( line, "ENDDRAW", 7 ) != 0 );
1080 
1081  return false;
1082  }
1083  else
1084  {
1085  drawings.push_back( newEntry );
1086  }
1087  }
1088 
1089  return true;
1090 }
1091 
1092 
1093 bool LIB_PART::LoadAliases( char* aLine, wxString& aErrorMsg )
1094 {
1095  char* text = strtok( aLine, " \t\r\n" );
1096 
1097  while( text )
1098  {
1099  m_aliases.push_back( new LIB_ALIAS( FROM_UTF8( text ), this ) );
1100  text = strtok( NULL, " \t\r\n" );
1101  }
1102 
1103  return true;
1104 }
1105 
1106 
1107 bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg )
1108 {
1109  LIB_FIELD* field = new LIB_FIELD( this );
1110 
1111  if( !field->Load( aLineReader, aErrorMsg ) )
1112  {
1113  delete field;
1114  return false;
1115  }
1116 
1117  if( field->GetId() < MANDATORY_FIELDS )
1118  {
1119  LIB_FIELD* fixedField = GetField( field->GetId() );
1120 
1121  // this will fire only if somebody broke a constructor or editor.
1122  // MANDATORY_FIELDS are always present in ram resident components, no
1123  // exceptions, and they always have their names set, even fixed fields.
1124  wxASSERT( fixedField );
1125 
1126  *fixedField = *field;
1127 
1128  if( field->GetId() == VALUE )
1129  m_name = field->GetText();
1130 
1131  delete field;
1132  }
1133  else
1134  {
1135  drawings.push_back( field );
1136  }
1137 
1138  return true;
1139 }
1140 
1141 
1142 bool LIB_PART::LoadFootprints( LINE_READER& aLineReader, wxString& aErrorMsg )
1143 {
1144  char* line;
1145  char* p;
1146 
1147  while( true )
1148  {
1149  if( !( line = aLineReader.ReadLine() ) )
1150  {
1151  aErrorMsg = wxT( "file ended prematurely while loading footprints" );
1152  return false;
1153  }
1154 
1155  p = strtok( line, " \t\r\n" );
1156 
1157  if( strcasecmp( p, "$ENDFPLIST" ) == 0 )
1158  break;
1159 
1160  m_FootprintList.Add( FROM_UTF8( p ) );
1161  }
1162 
1163  return true;
1164 }
1165 
1166 
1167 const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const
1168 {
1169  EDA_RECT bBox;
1170  bool initialized = false;
1171 
1172  for( unsigned ii = 0; ii < drawings.size(); ii++ )
1173  {
1174  const LIB_ITEM& item = drawings[ii];
1175 
1176  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
1177  && ( aUnit != item.m_Unit ) ) )
1178  continue;
1179 
1180  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
1181  continue;
1182 
1183  if ( ( item.Type() == LIB_FIELD_T ) && !( ( LIB_FIELD& ) item ).IsVisible() )
1184  continue;
1185 
1186  if( initialized )
1187  bBox.Merge( item.GetBoundingBox() );
1188  else
1189  {
1190  bBox = item.GetBoundingBox();
1191  initialized = true;
1192  }
1193  }
1194 
1195  return bBox;
1196 }
1197 
1198 
1199 const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
1200 {
1201  EDA_RECT bBox;
1202  bool initialized = false;
1203 
1204  for( unsigned ii = 0; ii < drawings.size(); ii++ )
1205  {
1206  const LIB_ITEM& item = drawings[ii];
1207 
1208  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
1209  && ( aUnit != item.m_Unit ) ) )
1210  continue;
1211 
1212  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
1213  continue;
1214 
1215  if( item.Type() == LIB_FIELD_T )
1216  continue;
1217 
1218  if( initialized )
1219  bBox.Merge( item.GetBoundingBox() );
1220  else
1221  {
1222  bBox = item.GetBoundingBox();
1223  initialized = true;
1224  }
1225  }
1226 
1227  return bBox;
1228 }
1229 
1230 
1232 {
1233  LIB_ITEMS::iterator it;
1234 
1235  for( it = drawings.begin(); it != drawings.end(); /* deleting */ )
1236  {
1237  if( it->Type() != LIB_FIELD_T )
1238  {
1239  ++it;
1240  continue;
1241  }
1242 
1243  // 'it' is not advanced, but should point to next in list after erase()
1244  it = drawings.erase( it );
1245  }
1246 }
1247 
1248 
1249 void LIB_PART::SetFields( const std::vector <LIB_FIELD>& aFields )
1250 {
1251  deleteAllFields();
1252 
1253  for( unsigned i=0; i<aFields.size(); ++i )
1254  {
1255  // drawings is a ptr_vector, new and copy an object on the heap.
1256  LIB_FIELD* field = new LIB_FIELD( aFields[i] );
1257 
1258  field->SetParent( this );
1259  drawings.push_back( field );
1260  }
1261 
1262  // Reorder drawings: transparent polygons first, pins and text last.
1263  // so texts have priority on screen.
1264  drawings.sort();
1265 }
1266 
1267 
1269 {
1270  LIB_FIELD* field;
1271 
1272  // The only caller of this function is the library field editor, so it
1273  // establishes policy here.
1274 
1275  // Grab the MANDATORY_FIELDS first, in expected order given by
1276  // enum NumFieldType
1277  for( int id=0; id<MANDATORY_FIELDS; ++id )
1278  {
1279  field = GetField( id );
1280 
1281  // the MANDATORY_FIELDS are exactly that in RAM.
1282  wxASSERT( field );
1283 
1284  aList.push_back( *field );
1285  }
1286 
1287  // Now grab all the rest of fields.
1288  for( LIB_ITEM& item : drawings )
1289  {
1290  if( item.Type() != LIB_FIELD_T )
1291  continue;
1292 
1293  field = ( LIB_FIELD* ) &item;
1294 
1295  if( (unsigned) field->GetId() < MANDATORY_FIELDS )
1296  continue; // was added above
1297 
1298  aList.push_back( *field );
1299  }
1300 }
1301 
1302 
1304 {
1305  for( LIB_ITEM& item : drawings )
1306  {
1307  if( item.Type() != LIB_FIELD_T )
1308  continue;
1309 
1310  LIB_FIELD* field = ( LIB_FIELD* ) &item;
1311 
1312  if( field->GetId() == aId )
1313  return field;
1314  }
1315 
1316  return NULL;
1317 }
1318 
1319 
1320 LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
1321 {
1322  for( LIB_ITEM& item : drawings )
1323  {
1324  if( item.Type() != LIB_FIELD_T )
1325  continue;
1326 
1327  LIB_FIELD* field = ( LIB_FIELD* ) &item;
1328 
1329  if( field->GetName() == aFieldName )
1330  return field;
1331  }
1332 
1333  return NULL;
1334 }
1335 
1336 
1338 {
1339  LIB_FIELD* field = GetField( VALUE );
1340  wxASSERT( field != NULL );
1341  return *field;
1342 }
1343 
1344 
1346 {
1347  LIB_FIELD* field = GetField( REFERENCE );
1348  wxASSERT( field != NULL );
1349  return *field;
1350 }
1351 
1352 
1354 {
1355  int year, mon, day, hour, min, sec;
1356 
1357  if( m_dateModified == 0 )
1358  return true;
1359 
1360  sec = m_dateModified & 63;
1361  min = ( m_dateModified >> 6 ) & 63;
1362  hour = ( m_dateModified >> 12 ) & 31;
1363  day = ( m_dateModified >> 17 ) & 31;
1364  mon = ( m_dateModified >> 22 ) & 15;
1365  year = ( m_dateModified >> 26 ) + 1990;
1366 
1367  aFormatter.Print( 0, "Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
1368 
1369  return true;
1370 }
1371 
1372 
1373 bool LIB_PART::LoadDateAndTime( char* aLine )
1374 {
1375  int year, mon, day, hour, min, sec;
1376 
1377  year = mon = day = hour = min = sec = 0;
1378  strtok( aLine, " \r\t\n" );
1379  strtok( NULL, " \r\t\n" );
1380 
1381  if( sscanf( aLine, "%d/%d/%d %d:%d:%d", &year, &mon, &day, &hour, &min, &sec ) != 6 )
1382  return false;
1383 
1384  m_dateModified = ( sec & 63 ) + ( ( min & 63 ) << 6 ) +
1385  ( ( hour & 31 ) << 12 ) + ( ( day & 31 ) << 17 ) +
1386  ( ( mon & 15 ) << 22 ) + ( ( year - 1990 ) << 26 );
1387 
1388  return true;
1389 }
1390 
1391 
1392 void LIB_PART::SetOffset( const wxPoint& aOffset )
1393 {
1394  for( LIB_ITEM& item : drawings )
1395  {
1396  item.SetOffset( aOffset );
1397  }
1398 }
1399 
1400 
1402 {
1403  drawings.unique();
1404 }
1405 
1406 
1408 {
1409  for( unsigned ii = 0; ii < drawings.size(); ii++ )
1410  {
1411  const LIB_ITEM& item = drawings[ii];
1412  if( item.m_Convert > 1 )
1413  return true;
1414  }
1415 
1416  return false;
1417 }
1418 
1419 
1421 {
1422  for( LIB_ITEM& item : drawings )
1423  {
1424  item.m_Flags = 0;
1425  }
1426 }
1427 
1428 
1429 int LIB_PART::SelectItems( EDA_RECT& aRect, int aUnit, int aConvert, bool aEditPinByPin )
1430 {
1431  int itemCount = 0;
1432 
1433  for( LIB_ITEM& item : drawings )
1434  {
1435  item.ClearFlags( SELECTED );
1436 
1437  if( ( item.m_Unit && item.m_Unit != aUnit )
1438  || ( item.m_Convert && item.m_Convert != aConvert ) )
1439  {
1440  if( item.Type() != LIB_PIN_T )
1441  continue;
1442 
1443  // Specific rules for pins.
1444  if( aEditPinByPin || m_unitsLocked
1445  || ( item.m_Convert && item.m_Convert != aConvert ) )
1446  continue;
1447  }
1448 
1449  if( item.Inside( aRect ) )
1450  {
1451  item.SetFlags( SELECTED );
1452  itemCount++;
1453  }
1454  }
1455 
1456  return itemCount;
1457 }
1458 
1459 
1460 void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
1461 {
1462  for( LIB_ITEM& item : drawings )
1463  {
1464  if( !item.IsSelected() )
1465  continue;
1466 
1467  item.SetOffset( aOffset );
1468  item.m_Flags = 0;
1469  }
1470 
1471  drawings.sort();
1472 }
1473 
1474 
1476 {
1477  for( LIB_ITEM& item : drawings )
1478  {
1479  item.m_Flags = 0;
1480  }
1481 }
1482 
1483 
1485 {
1486  LIB_ITEMS::iterator item = drawings.begin();
1487 
1488  // We *do not* remove the 2 mandatory fields: reference and value
1489  // so skip them (do not remove) if they are flagged selected.
1490  // Skip also not visible items.
1491  // But I think fields must not be deleted by a block delete command or other global command
1492  // because they are not really graphic items
1493  while( item != drawings.end() )
1494  {
1495  if( item->Type() == LIB_FIELD_T )
1496  {
1497 #if 0 // Set to 1 to allows fields deletion on block delete or other global command
1498  LIB_FIELD& field = ( LIB_FIELD& ) *item;
1499 
1500  if( (field.GetId() == REFERENCE) || (field.m_FieldId == VALUE) ||
1501  (field.m_Attributs & TEXT_NO_VISIBLE) )
1502 #endif
1503  item->ClearFlags( SELECTED );
1504  }
1505 
1506  if( !item->IsSelected() )
1507  item++;
1508  else
1509  item = drawings.erase( item );
1510  }
1511 }
1512 
1513 
1514 void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
1515 {
1516  /* *do not* use iterators here, because new items
1517  * are added to drawings that is a boost::ptr_vector.
1518  * When push_back elements in buffer,
1519  * a memory reallocation can happen and will break pointers
1520  */
1521  unsigned icnt = drawings.size();
1522 
1523  for( unsigned ii = 0; ii < icnt; ii++ )
1524  {
1525  LIB_ITEM& item = drawings[ii];
1526 
1527  // We *do not* copy fields because they are unique for the whole component
1528  // so skip them (do not duplicate) if they are flagged selected.
1529  if( item.Type() == LIB_FIELD_T )
1530  item.ClearFlags( SELECTED );
1531 
1532  if( !item.IsSelected() )
1533  continue;
1534 
1535  item.ClearFlags( SELECTED );
1536  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1537  newItem->SetFlags( SELECTED );
1538  drawings.push_back( newItem );
1539  }
1540 
1541  MoveSelectedItems( aOffset );
1542  drawings.sort();
1543 }
1544 
1545 
1546 
1548 {
1549  for( LIB_ITEM& item : drawings )
1550  {
1551  if( !item.IsSelected() )
1552  continue;
1553 
1554  item.MirrorHorizontal( aCenter );
1555  item.m_Flags = 0;
1556  }
1557 
1558  drawings.sort();
1559 }
1560 
1562 {
1563  for( LIB_ITEM& item : drawings )
1564  {
1565  if( !item.IsSelected() )
1566  continue;
1567 
1568  item.MirrorVertical( aCenter );
1569  item.m_Flags = 0;
1570  }
1571 
1572  drawings.sort();
1573 }
1574 
1576 {
1577  for( LIB_ITEM& item : drawings )
1578  {
1579  if( !item.IsSelected() )
1580  continue;
1581 
1582  item.Rotate( aCenter );
1583  item.m_Flags = 0;
1584  }
1585 
1586  drawings.sort();
1587 }
1588 
1589 
1590 
1591 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
1592  KICAD_T aType, const wxPoint& aPoint )
1593 {
1594  for( LIB_ITEM& item : drawings )
1595  {
1596  if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
1597  || ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
1598  || ( ( item.Type() != aType ) && ( aType != TYPE_NOT_INIT ) ) )
1599  continue;
1600 
1601  if( item.HitTest( aPoint ) )
1602  return &item;
1603  }
1604 
1605  return NULL;
1606 }
1607 
1608 
1609 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
1610  const wxPoint& aPoint, const TRANSFORM& aTransform )
1611 {
1612  /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1613  * wxPoint& pt ) to search items.
1614  * because this function uses DefaultTransform as orient/mirror matrix
1615  * we temporary copy aTransform in DefaultTransform
1616  */
1617  LIB_ITEM* item;
1618  TRANSFORM transform = DefaultTransform;
1619  DefaultTransform = aTransform;
1620 
1621  item = LocateDrawItem( aUnit, aConvert, aType, aPoint );
1622 
1623  // Restore matrix
1624  DefaultTransform = transform;
1625 
1626  return item;
1627 }
1628 
1629 
1630 void LIB_PART::SetUnitCount( int aCount )
1631 {
1632  if( m_unitCount == aCount )
1633  return;
1634 
1635  if( aCount < m_unitCount )
1636  {
1637  LIB_ITEMS::iterator i;
1638  i = drawings.begin();
1639 
1640  while( i != drawings.end() )
1641  {
1642  if( i->m_Unit > aCount )
1643  i = drawings.erase( i );
1644  else
1645  i++;
1646  }
1647  }
1648  else
1649  {
1650  int prevCount = m_unitCount;
1651 
1652  // We cannot use an iterator here, because when adding items in vector
1653  // the buffer can be reallocated, that change the previous value of
1654  // .begin() and .end() iterators and invalidate others iterators
1655  unsigned imax = drawings.size();
1656 
1657  for( unsigned ii = 0; ii < imax; ii++ )
1658  {
1659  if( drawings[ii].m_Unit != 1 )
1660  continue;
1661 
1662  for( int j = prevCount + 1; j <= aCount; j++ )
1663  {
1664  LIB_ITEM* newItem = (LIB_ITEM*) drawings[ii].Clone();
1665  newItem->m_Unit = j;
1666  drawings.push_back( newItem );
1667  }
1668  }
1669 
1670  drawings.sort();
1671  }
1672 
1673  m_unitCount = aCount;
1674 }
1675 
1676 
1677 void LIB_PART::SetConversion( bool aSetConvert )
1678 {
1679  if( aSetConvert == HasConversion() )
1680  return;
1681 
1682  // Duplicate items to create the converted shape
1683  if( aSetConvert )
1684  {
1685  std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
1686 
1687  for( LIB_ITEM& item : drawings )
1688  {
1689  // Only pins are duplicated.
1690  if( item.Type() != LIB_PIN_T )
1691  continue;
1692 
1693  if( item.m_Convert == 1 )
1694  {
1695  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1696  newItem->m_Convert = 2;
1697  tmp.push_back( newItem );
1698  }
1699  }
1700 
1701  // Transfer the new pins to the LIB_PART.
1702  for( unsigned i = 0; i < tmp.size(); i++ )
1703  drawings.push_back( tmp[i] );
1704  }
1705  else
1706  {
1707  // Delete converted shape items because the converted shape does
1708  // not exist
1709  LIB_ITEMS::iterator i = drawings.begin();
1710 
1711  while( i != drawings.end() )
1712  {
1713  if( i->m_Convert > 1 )
1714  i = drawings.erase( i );
1715  else
1716  i++;
1717  }
1718  }
1719 }
1720 
1721 
1722 wxArrayString LIB_PART::GetAliasNames( bool aIncludeRoot ) const
1723 {
1724  wxArrayString names;
1725 
1726  LIB_ALIASES::const_iterator it;
1727 
1728  for( it=m_aliases.begin(); it != m_aliases.end(); ++it )
1729  {
1730  if( !aIncludeRoot && (*it)->IsRoot() )
1731  continue;
1732 
1733  names.Add( (*it)->GetName() );
1734  }
1735 
1736  return names;
1737 }
1738 
1739 
1740 bool LIB_PART::HasAlias( const wxString& aName ) const
1741 {
1742  wxCHECK2_MSG( !aName.IsEmpty(), return false,
1743  wxT( "Cannot get alias with an empty name, bad programmer." ) );
1744 
1745  for( size_t i = 0; i < m_aliases.size(); i++ )
1746  {
1747  if( aName == m_aliases[i]->GetName() )
1748  return true;
1749  }
1750 
1751  return false;
1752 }
1753 
1754 
1755 void LIB_PART::SetAliases( const wxArrayString& aAliasList )
1756 {
1757  wxCHECK_RET( !m_library,
1758  wxT( "Part aliases cannot be changed when they are owned by a library." ) );
1759 
1760  if( aAliasList == GetAliasNames() )
1761  return;
1762 
1763  // Add names not existing in the current component alias list.
1764  for( size_t i = 0; i < aAliasList.GetCount(); i++ )
1765  {
1766  if( HasAlias( aAliasList[ i ] ) )
1767  continue;
1768 
1769  m_aliases.push_back( new LIB_ALIAS( aAliasList[ i ], this ) );
1770  }
1771 
1772  // Remove names in the current component that are not in the new alias list.
1773  LIB_ALIASES::iterator it = m_aliases.begin();
1774 
1775  while( it != m_aliases.end() )
1776  {
1777  int index = aAliasList.Index( (*it)->GetName(), false );
1778 
1779  if( index != wxNOT_FOUND || (*it)->IsRoot() )
1780  ++it;
1781  else
1782  it = m_aliases.erase( it );
1783  }
1784 }
1785 
1786 
1787 #if 0 // this version looked suspect to me, it did not rename a deleted root
1788 
1789 void LIB_PART::RemoveAlias( const wxString& aName )
1790 {
1791  wxCHECK_RET( m_library == NULL,
1792  wxT( "Part aliases cannot be changed when they are owned by a library." ) );
1793  wxCHECK_RET( !aName.IsEmpty(), wxT( "Cannot get alias with an empty name." ) );
1794 
1795  LIB_ALIASES::iterator it;
1796 
1797  for( it = m_aliases.begin(); it != m_aliases.end(); it++ )
1798  {
1799  if( aName == (*it)->GetName() )
1800  {
1801  m_aliases.erase( it );
1802  break;
1803  }
1804  }
1805 }
1806 
1807 #else
1808 void LIB_PART::RemoveAlias( const wxString& aName )
1809 {
1810  LIB_ALIAS* a = GetAlias( aName );
1811 
1812  if( a )
1813  RemoveAlias( a );
1814 }
1815 #endif
1816 
1817 
1819 {
1820  wxCHECK_MSG( aAlias, NULL, wxT( "Cannot remove alias by NULL pointer." ) );
1821 
1822  LIB_ALIAS* nextAlias = NULL;
1823 
1824  LIB_ALIASES::iterator it = find( m_aliases.begin(), m_aliases.end(), aAlias );
1825 
1826  if( it != m_aliases.end() )
1827  {
1828  bool rename = aAlias->IsRoot();
1829 
1830  wxLogTrace( traceSchLibMem,
1831  wxT( "%s: part:'%s', alias:'%s', alias count %llu, reference count %ld." ),
1832  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ),
1833  GetChars( m_name ),
1834  GetChars( aAlias->GetName() ),
1835  (long long unsigned) m_aliases.size(),
1836  m_me.use_count() );
1837 
1838  it = m_aliases.erase( it );
1839 
1840  if( !m_aliases.empty() )
1841  {
1842  if( it == m_aliases.end() )
1843  it = m_aliases.begin();
1844 
1845  nextAlias = *it;
1846 
1847  if( rename )
1848  SetName( nextAlias->GetName() );
1849  }
1850  }
1851 
1852  return nextAlias;
1853 }
1854 
1855 
1857 {
1858  // Remove all of the aliases except the root alias.
1859  while( m_aliases.size() > 1 )
1860  m_aliases.pop_back();
1861 }
1862 
1863 
1864 LIB_ALIAS* LIB_PART::GetAlias( const wxString& aName )
1865 {
1866  wxCHECK2_MSG( !aName.IsEmpty(), return NULL,
1867  wxT( "Cannot get alias with an empty name. Bad programmer!" ) );
1868 
1869  for( size_t i = 0; i < m_aliases.size(); i++ )
1870  {
1871  if( aName == m_aliases[i]->GetName() )
1872  return m_aliases[i];
1873  }
1874 
1875  return NULL;
1876 }
1877 
1878 
1880 {
1881  wxCHECK2_MSG( aIndex < m_aliases.size(), return NULL,
1882  wxT( "Illegal alias list index, bad programmer." ) );
1883 
1884  return m_aliases[aIndex];
1885 }
1886 
1887 
1888 void LIB_PART::AddAlias( const wxString& aName )
1889 {
1890  wxCHECK_RET( !HasAlias( aName ),
1891  wxT( "Part <" ) + GetName() + wxT( "> already has an alias <" ) +
1892  aName + wxT( ">. Bad programmer." ) );
1893 
1894  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
1895 }
1896 
1897 
1898 void LIB_PART::SetSubpartIdNotation( int aSep, int aFirstId )
1899 {
1900  m_subpartFirstId = 'A';
1902 
1903  if( aSep == '.' || aSep == '-' || aSep == '_' )
1904  m_subpartIdSeparator = aSep;
1905 
1906  if( aFirstId == '1' && aSep != 0 )
1907  m_subpartFirstId = aFirstId;
1908 }
LIB_ALIASES m_aliases
List of alias object pointers associated with the part.
PART_LIB * GetLib()
virtual ~LIB_ALIAS()
GR_DRAWMODE g_XorMode
Definition: gr_basic.cpp:51
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
LIB_FIELD * GetField(int aId)
Return pointer to the requested field.
bool PinsConflictWith(LIB_PART &aOtherPart, bool aTestNums, bool aTestNames, bool aTestType, bool aTestOrientation, bool aTestLength)
Function PinsConflictWith returns true if this part's pins do not match another part's pins...
void SetModified()
static int m_subpartIdSeparator
the separator char between the subpart id and the reference like U1A ( m_subpartIdSeparator = 0 ) or ...
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
const EDA_RECT GetUnitBoundingBox(int aUnit, int aConvert) const
Function GetBoundingBox.
Part library alias object definition.
bool PinIsDangling(size_t aPin) const
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
void SetConversion(bool aSetConvert)
Set or clear the alternate body style (DeMorgan) for the part.
virtual ~LIB_PART()
name of datasheet
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
bool LoadFootprints(LINE_READER &aReader, wxString &aErrorMsg)
bool Load(LINE_READER &aLineReader, wxString &errorMsg) override
Definition: lib_field.cpp:157
LIB_ITEMS & GetDrawItemList()
Return a reference to the draw item list.
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
bool Load(LINE_READER &aReader, wxString &aErrorMsg)
Load part definition from aReader.
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
bool m_showPinNumbers
Determines if part pin numbers are visible.
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:290
wxString description
documentation for info
int LibraryEntryCompare(const LIB_ALIAS *aItem1, const LIB_ALIAS *aItem2)
bool IsPower() const
LIB_ALIAS * GetAlias(size_t aIndex)
Class LIB_TEXT defines a component library graphical text item.
Definition: lib_text.h:45
virtual void SetColor(COLOR4D color)=0
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:352
int m_unitCount
Number of units (parts) per package.
const wxString GetLibraryName()
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...
Class LIB_FIELD is used in symbol libraries.
Definition: lib_field.h:60
static int m_subpartFirstId
the ascii char value to calculate the subpart symbol id from the part number: only 'A'...
const EDA_RECT GetBodyBoundingBox(int aUnit, int aConvert) const
Function GetBodyBoundingBox.
bool HasAlias(const wxString &aName) const
Test if alias aName is in part alias list.
void SetVisible(bool aVisible)
Definition: eda_text.h:175
bool LoadDrawEntries(LINE_READER &aReader, wxString &aErrorMsg)
bool IsSelected() const
Definition: base_struct.h:221
LIB_FIELD & GetValueField()
Return reference to the value field.
int m_Unit
Unit identification for multiple parts per package.
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
LIB_ALIAS(const wxString &aName, LIB_PART *aRootComponent)
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: lib_field.cpp:533
void ClearSelectedItems()
Clears all the draw items marked by a block select.
void AddAlias(const wxString &aName)
Function AddAlias.
LIBRENTRYOPTIONS m_options
Special part features such as POWER or NORMAL.)
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Definition: eeschema.cpp:166
PART_LIB * GetLib()
void RevertYAxis()
Function RevertYAxis Mirror the rectangle from the X axis (negate Y pos and size) ...
void operator()(void const *) const
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:90
bool m_unitsLocked
True if part has multiple units and changing one unit does not automatically change another unit...
Class LIB_ITEM is the base class for drawable items used by schematic library components.
Definition: lib_draw_item.h:77
const wxChar traceSchLibMem[]
WXTRACE value to enable schematic library memory deletion debug output.
void MirrorSelectedItemsH(const wxPoint &aCenter)
Horizontally (X axis) mirror selected draw items about a point.
This file contains miscellaneous commonly used macros and functions.
wxString name
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.
void MirrorSelectedItemsV(const wxPoint &aCenter)
Vertically (Y axis) mirror selected draw items about a point.
bool LoadDateAndTime(char *aLine)
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:135
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.
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
#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 deleteAllFields()
#define SELECTED
Definition: base_struct.h:120
bool IsRoot() const
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1077
bool LoadField(LINE_READER &aReader, wxString &aErrorMsg)
Class for tranforming 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.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:253
LIB_FIELD * FindField(const wxString &aFieldName)
Function FindField finds a field within this part matching aFieldName and returns it or NULL if not f...
wxString m_name
void SetText(const wxString &aText) override
Sets the field text to aText.
Definition: lib_field.cpp:679
bool Save(OUTPUTFORMATTER &aFormatter)
Function Save writes the data structures out to aFormatter in the part library "*.lib" format.
void SetUnitCount(int count)
Set the units per part count.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:213
int GetId() const
Definition: lib_field.h:136
wxString docFileName
Associate doc file name.
void CopySelectedItems(const wxPoint &aOffset)
Make a copy of the selected draw items marked by a block select.
Definitions for the Eeschema program SCH_SCREEN class.
const wxString & GetName() const
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
LIB_PART * shared
Actual LIB_PART referenced by [multiple] aliases.
void RotateSelectedItems(const wxPoint &aCenter)
Rotate CCW selected draw items about a point.
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
Class LIB_ITEM definition.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
const wxString GetName() const
Return the file name without path or extension.
void Empty()
Definition: eda_text.h:231
bool operator==(const wxChar *aName) const
KEEPCASE sensitive comparison of the part entry name.
Class LIB_PART defines a library part object.
EDA_RECT * GetClipBox()
Common plot library Plot settings, and plotting engines (Postscript, Gerber, HPGL and DXF) ...
wxString GetText(GRAPHIC_PINSHAPE shape)
Definition: pin_shape.cpp:33
void RemoveDuplicateDrawItems()
Remove duplicate draw items from list.
bool operator<(const LIB_ALIAS &aItem1, const LIB_ALIAS &aItem2)
wxArrayString m_FootprintList
List of suitable footprint names for the part (wild card names accepted).
bool GetColorMode() const
Definition: plot_common.h:121
LIB_PART(const wxString &aName, PART_LIB *aLibrary=NULL)
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:609
const wxString GetLibraryName()
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared ...
Field Value of part, i.e. "3.3K".
virtual const EDA_RECT GetBoundingBox() const override
Base plotter engine class.
Definition: plot_common.h:86
void SetAliases(const wxArrayString &aAliasList)
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_draw_item.h:70
bool LoadAliases(char *aLine, wxString &aErrorMsg)
bool SaveDoc(OUTPUTFORMATTER &aFormatter)
Function SaveDocs write the entry document information to aFormatter in "*.dcm" format.
void ClearStatus()
Clears the status flag all draw objects in this part.
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter...
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
TRANSFORM DefaultTransform
Definition: eeschema.cpp:57
GR_DRAWMODE draw_mode
Device context drawing mode, see wxDC.
int SelectItems(EDA_RECT &aRect, int aUnit, int aConvert, bool aEditPinByPin)
Checks all draw objects of part to see if they are with block.
COLOR4D color
Color to draw part in.
void RemoveAlias(const wxString &aName)
LIB_ITEMS drawings
How to draw this part.
void RemoveAllAliases()
virtual void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void *aData, const TRANSFORM &aTransform)
Draw an item.
const wxString & GetName() const
virtual bool Load(LINE_READER &aLine, wxString &aErrorMsg)=0
bool IsVisible() const
Function IsVisible.
Definition: lib_field.h:168
static void SetSubpartIdNotation(int aSep, int aFirstId)
Set the separator char between the subpart id and the reference 0 (no separator) or '...
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:261
wxArrayString GetAliasNames(bool aIncludeRoot=true) const
Class EDA_RECT handles the component boundary box.
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Function SubReference.
bool show_pin_text
Whether to show pin texts.
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:188
void RemoveDrawItem(LIB_ITEM *aItem, EDA_DRAW_PANEL *aPanel=NULL, wxDC *aDc=NULL)
Remove draw aItem from list.
friend class LIB_ALIAS
bool only_selected
Draws only the body items that are selected, for block moves.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
bool show_elec_type
Whether to show the pin electrical type.
int m_Convert
Shape identification for alternate body styles.
long m_dateModified
Date the part was last modified.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:254
void MoveSelectedItems(const wxPoint &aOffset)
Move the selected draw items marked by a block select.
bool IsPowerConnection() const
Return whether this pin forms an implicit power connection: i.e., is hidden and of type POWER_IN...
Definition: lib_pin.h:378
LIB_ITEM * LocateDrawItem(int aUnit, int aConvert, KICAD_T aType, const wxPoint &aPoint)
Locate a draw object.
virtual void SetName(const wxString &aName)
Definition for part library class.
bool draw_visible_fields
Whether to draw "visible" fields.
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
Definition: gr_basic.cpp:281
void DeleteSelectedItems()
Deletes the select draw items marked by a block select.
bool m_showPinNames
Determines if part pin names are visible.
void SetFields(const std::vector< LIB_FIELD > &aFieldsList)
Function SetFields overwrites all the existing in this part with fields supplied in aFieldsList...
Class PART_LIB is used to load, save, search, and otherwise manipulate part library files...
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
TRANSFORM transform
Coordinate adjustment settings.
wxString keyWords
keyword list (used for search for parts by keyword)
void GetFields(LIB_FIELDS &aList)
Function GetFields returns a list of fields withing this part.
LIB_PIN * GetPin(const wxString &aNumber, int aUnit=0, int aConvert=0)
Return pin object with the requested pin aNumber.
#define min(a, b)
Definition: auxiliary.h:85
bool SaveDateAndTime(OUTPUTFORMATTER &aFormatter)
Function SaveDateAndTime write the date and time of part to aFile in the format: "Ti yy/mm/jj hh:mm:s...
Class LIB_BEZIER defines bezier curve graphic body item.
Definition: lib_bezier.h:39
#define IS_MOVED
Item being moved.
Definition: base_struct.h:112
PART_SPTR m_me
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared ...