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 
30 #include <fctsys.h>
31 #include <macros.h>
32 #include <kicad_string.h>
33 #include <sch_draw_panel.h>
34 #include <plotter.h>
35 #include <gr_basic.h>
36 #include <sch_screen.h>
37 #include <richio.h>
38 #include <kicad_string.h>
39 #include <trace_helpers.h>
40 
41 #include <general.h>
42 #include <template_fieldnames.h>
43 #include <transform.h>
44 #include <class_library.h>
45 #include <class_libentry.h>
46 #include <lib_pin.h>
47 #include <lib_arc.h>
48 #include <lib_bezier.h>
49 #include <lib_circle.h>
50 #include <lib_polyline.h>
51 #include <lib_rectangle.h>
52 #include <lib_text.h>
53 
54 
55 // the separator char between the subpart id and the reference
56 // 0 (no separator) or '.' or some other character
58 
59 // the ascii char value to calculate the subpart symbol id from the part number:
60 // 'A' or '1' usually. (to print U1.A or U1.1)
61 // if this a a digit, a number is used as id symbol
63 
64 
65 LIB_ALIAS::LIB_ALIAS( const wxString& aName, LIB_PART* aRootPart ) :
67  shared( aRootPart ),
68  tmpUnit( 0 ),
69  tmpConversion( 0 )
70 {
71  SetName( aName );
72 }
73 
74 
75 LIB_ALIAS::LIB_ALIAS( const LIB_ALIAS& aAlias, LIB_PART* aRootPart ) :
76  EDA_ITEM( aAlias ),
77  shared( aRootPart ),
78  tmpUnit( 0 ),
79  tmpConversion( 0 )
80 {
81  name = aAlias.name;
82 
83  description = aAlias.description;
84  keyWords = aAlias.keyWords;
85  docFileName = aAlias.docFileName;
86 }
87 
88 
90 {
91  wxLogTrace( traceSchLibMem, wxT( "%s: destroying alias:'%s'" ),
92  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( GetName() ) );
93 
94  wxCHECK_RET( shared, wxT( "~LIB_ALIAS() without a LIB_PART" ) );
95 
96  if( shared )
97  shared->RemoveAlias( this );
98 }
99 
100 
102 {
103  wxASSERT_MSG( shared, wxT( "LIB_ALIAS without a LIB_PART" ) );
104 
105  if( shared )
106  return shared->GetLibraryName();
107 
108  return wxEmptyString;
109 }
110 
111 
112 bool LIB_ALIAS::IsRoot() const
113 {
114  return name == shared->GetName();
115 }
116 
117 
119 {
120  LIB_ID id = shared->GetLibId();
121  id.SetLibItemName( name );
122  return id;
123 }
124 
125 
127 {
128  return shared->GetLib();
129 }
130 
131 
132 void LIB_ALIAS::SetName( const wxString& aName )
133 {
135 }
136 
137 
139 {
140  return shared->GetUnitCount();
141 }
142 
143 
144 wxString LIB_ALIAS::GetUnitReference( int aUnit )
145 {
146  return LIB_PART::SubReference( aUnit, false );
147 }
148 
149 
151 {
152  // a LIB_ALIAS does not really have a bounding box.
153  // return a 0 size rect.
154  EDA_RECT dummy;
155 
156  return dummy;
157 };
158 
159 
161 {
162  // LIB_ALIAS may be displayed in preview windows, so ensure that it is always
163  // selected for drawing.
164  BOX2I bbox;
165  bbox.SetMaximum();
166  return bbox;
167 }
168 
169 
171 {
172  // Matches are scored by offset from front of string, so inclusion of this spacer
173  // discounts matches found after it.
174  static const wxString discount( wxT( " " ) );
175 
176  wxString text = GetKeyWords() + discount + GetDescription();
177 
178  // If a footprint is defined for the part, add it to the serach string
179  if( shared )
180  {
181  wxString footprint = shared->GetFootprintField().GetText();
182 
183  if( !footprint.IsEmpty() )
184  text += discount + footprint;
185  }
186 
187  return text;
188 }
189 
190 
191 bool LIB_ALIAS::operator==( const wxChar* aName ) const
192 {
193  return name == aName;
194 }
195 
196 
197 bool operator<( const LIB_ALIAS& aItem1, const LIB_ALIAS& aItem2 )
198 {
199  return aItem1.GetName() < aItem2.GetName();
200 }
201 
202 
203 void LIB_ALIAS::ViewGetLayers( int aLayers[], int& aCount ) const
204 {
205  // An alias's fields don't know how to fetch their parent's values so we don't let
206  // them draw themselves. This means the alias always has to draw them, which means
207  // it has to "own" their layers as well.
208  aCount = 5;
209  aLayers[0] = LAYER_DEVICE;
210  aLayers[1] = LAYER_DEVICE_BACKGROUND;
211  aLayers[2] = LAYER_REFERENCEPART;
212  aLayers[3] = LAYER_VALUEPART;
213  aLayers[4] = LAYER_FIELDS;
214 }
215 
216 
219 {
220  void operator()(void const *) const
221  {
222  }
223 };
224 
225 
226 LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
227  EDA_ITEM( LIB_PART_T ),
228  m_me( this, null_deleter() )
229 {
230  m_dateLastEdition = 0;
231  m_unitCount = 1;
232  m_pinNameOffset = 40;
234  m_unitsLocked = false;
235  m_showPinNumbers = true;
236  m_showPinNames = true;
237 
238  // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present
239  // when the field editors are invoked.
240  m_drawings[LIB_FIELD_T].reserve( 4 );
245 
246  SetLib( aLibrary );
247  SetName( aName );
248 }
249 
250 
251 LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
252  EDA_ITEM( aPart ),
253  m_me( this, null_deleter() )
254 {
255  LIB_ITEM* newItem;
256 
257  m_library = aLibrary;
259  m_unitCount = aPart.m_unitCount;
265  m_options = aPart.m_options;
266  m_libId = aPart.m_libId;
267 
268  for( LIB_ITEM& oldItem : aPart.m_drawings )
269  {
270  if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
271  continue;
272 
273  newItem = (LIB_ITEM*) oldItem.Clone();
274  newItem->SetParent( this );
275  m_drawings.push_back( newItem );
276  }
277 
278  for( size_t i = 0; i < aPart.m_aliases.size(); i++ )
279  {
280  LIB_ALIAS* alias = new LIB_ALIAS( *aPart.m_aliases[i], this );
281  m_aliases.push_back( alias );
282  }
283 }
284 
285 
287 {
288  wxLogTrace( traceSchLibMem,
289  wxT( "%s: destroying symbol with alias list count of %llu" ),
290  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ),
291  (long long unsigned) m_aliases.size() );
292 
293  // If the part is being deleted directly rather than through the library,
294  // delete all of the aliases.
295  while( m_aliases.size() )
296  {
297  LIB_ALIAS* alias = m_aliases.back();
298  m_aliases.pop_back();
299  delete alias;
300  }
301 }
302 
303 
304 const wxString LIB_PART::GetLibraryName()
305 {
306  if( m_library )
307  return m_library->GetName();
308 
309  return m_libId.GetLibNickname();
310 }
311 
312 
313 wxString LIB_PART::SubReference( int aUnit, bool aAddSeparator )
314 {
315  wxString subRef;
316 
317  if( m_subpartIdSeparator != 0 && aAddSeparator )
318  subRef << wxChar( m_subpartIdSeparator );
319 
320  if( m_subpartFirstId >= '0' && m_subpartFirstId <= '9' )
321  subRef << aUnit;
322  else
323  {
324  // use letters as notation. To allow more than 26 units, the sub ref
325  // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
326  // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
327  int u;
328  aUnit -= 1; // Unit number starts to 1. now to 0.
329 
330  while( aUnit >= 26 ) // more than one letter are needed
331  {
332  u = aUnit / 26;
333  subRef << wxChar( m_subpartFirstId + u -1 );
334  aUnit %= 26;
335  }
336 
337  u = m_subpartFirstId + aUnit;
338  subRef << wxChar( u );
339  }
340 
341  return subRef;
342 }
343 
344 
345 const wxString& LIB_PART::GetName() const
346 {
347  static wxString dummy;
348 
349  wxCHECK_MSG( m_aliases.size(), dummy, "no aliases defined for symbol" );
350 
351  return m_aliases[0]->GetName();
352 }
353 
354 
355 void LIB_PART::SetName( const wxString& aName )
356 {
357  // The LIB_ALIAS that is the LIB_PART name has to be created so create it.
358  if( m_aliases.empty() )
359  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
360  else
361  m_aliases[0]->SetName( aName );
362 
363  wxString validatedName = LIB_ID::FixIllegalChars( aName, LIB_ID::ID_SCH );
364  m_libId.SetLibItemName( validatedName, false );
365 
366  GetValueField().SetText( validatedName );
367 }
368 
369 
370 void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
371  int aMulti, int aConvert, const PART_DRAW_OPTIONS& aOpts )
372 {
373  /* draw background for filled items using background option
374  * Solid lines will be drawn after the background
375  * Note also, background is not drawn when printing in black and white
376  */
377  if( ! GetGRForceBlackPenState() )
378  {
379  for( LIB_ITEM& drawItem : m_drawings )
380  {
381  if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
382  continue;
383 
384  // Do not draw items not attached to the current part
385  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
386  continue;
387 
388  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
389  continue;
390 
391  if( drawItem.Type() == LIB_FIELD_T )
392  continue;
393 
394  // Now, draw only the background for items with
395  // m_Fill == FILLED_WITH_BG_BODYCOLOR:
396  drawItem.Draw( aPanel, aDc, aOffset, (void*) false, aOpts.transform );
397  }
398  }
399 
400  for( LIB_ITEM& drawItem : m_drawings )
401  {
402  // Do not draw items not attached to the current part
403  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
404  continue;
405 
406  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
407  continue;
408 
409  if( drawItem.Type() == LIB_FIELD_T )
410  {
411  LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem );
412 
413  if( field.IsVisible() && !aOpts.draw_visible_fields )
414  continue;
415 
416  if( !field.IsVisible() && !aOpts.draw_hidden_fields )
417  continue;
418  }
419 
420  if( drawItem.Type() == LIB_PIN_T )
421  {
422  drawItem.Draw( aPanel, aDc, aOffset, (void*) aOpts.show_elec_type, aOpts.transform );
423  }
424  else if( drawItem.Type() == LIB_FIELD_T )
425  {
426  drawItem.Draw( aPanel, aDc, aOffset, (void*) NULL, aOpts.transform );
427  }
428  else
429  {
430  bool forceNoFill = drawItem.m_Fill == FILLED_WITH_BG_BODYCOLOR;
431  drawItem.Draw( aPanel, aDc, aOffset, (void*) forceNoFill, aOpts.transform );
432  }
433  }
434 }
435 
436 
437 void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
438  const wxPoint& aOffset, const TRANSFORM& aTransform )
439 {
440  wxASSERT( aPlotter != NULL );
441 
442  aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) );
443  bool fill = aPlotter->GetColorMode();
444 
445  // draw background for filled items using background option
446  // Solid lines will be drawn after the background
447  for( LIB_ITEM& item : m_drawings )
448  {
449  // Lib Fields are not plotted here, because this plot function
450  // is used to plot schematic items, which have they own fields
451  if( item.Type() == LIB_FIELD_T )
452  continue;
453 
454  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
455  continue;
456 
457  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
458  continue;
459 
460  if( item.m_Fill == FILLED_WITH_BG_BODYCOLOR )
461  item.Plot( aPlotter, aOffset, fill, aTransform );
462  }
463 
464  // Not filled items and filled shapes are now plotted
465  // (plot only items which are not already plotted)
466  for( LIB_ITEM& item : m_drawings )
467  {
468  if( item.Type() == LIB_FIELD_T )
469  continue;
470 
471  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
472  continue;
473 
474  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
475  continue;
476 
477  if( item.m_Fill != FILLED_WITH_BG_BODYCOLOR )
478  item.Plot( aPlotter, aOffset, fill, aTransform );
479  }
480 }
481 
482 
483 void LIB_PART::PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
484  const wxPoint& aOffset, const TRANSFORM& aTransform )
485 {
486  wxASSERT( aPlotter != NULL );
487 
488  aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
489  bool fill = aPlotter->GetColorMode();
490 
491  for( LIB_ITEM& item : m_drawings )
492  {
493  if( item.Type() != LIB_FIELD_T )
494  continue;
495 
496  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
497  continue;
498 
499  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
500  continue;
501 
502  // The reference is a special case: we should change the basic text
503  // to add '?' and the part id
504  LIB_FIELD& field = (LIB_FIELD&) item;
505  wxString tmp = field.GetShownText();
506  if( field.GetId() == REFERENCE )
507  {
508  wxString text = field.GetFullText( aUnit );
509  field.SetText( text );
510  }
511  item.Plot( aPlotter, aOffset, fill, aTransform );
512  field.SetText( tmp );
513  }
514 }
515 
516 
517 void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aDc )
518 {
519  wxASSERT( aItem != NULL );
520 
521  // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
522  // omitted when saving to disk.
523  if( aItem->Type() == LIB_FIELD_T )
524  {
525  LIB_FIELD* field = (LIB_FIELD*) aItem;
526 
527  if( field->GetId() < MANDATORY_FIELDS )
528  {
529  wxLogWarning( _(
530  "An attempt was made to remove the %s field from component %s in library %s." ),
531  GetChars( field->GetName() ), GetChars( GetName() ),
532  GetChars( GetLibraryName() ) );
533  return;
534  }
535  }
536 
537  LIB_ITEMS& items = m_drawings[ aItem->Type() ];
538 
539  for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
540  {
541  if( *i == aItem )
542  {
543  items.erase( i );
544  SetModified();
545  break;
546  }
547  }
548 }
549 
550 
552 {
553  wxASSERT( aItem != NULL );
554 
555  m_drawings.push_back( aItem );
556 }
557 
558 
560 {
561  if( m_drawings.empty( aType ) )
562  return NULL;
563 
564  if( aItem == NULL )
565  return &( *( m_drawings.begin( aType ) ) );
566 
567  // Search for the last item, assume aItem is of type aType
568  wxASSERT( ( aType == TYPE_NOT_INIT ) || ( aType == aItem->Type() ) );
570 
571  while( ( it != m_drawings.end( aType ) ) && ( aItem != &( *it ) ) )
572  ++it;
573 
574  // Search the next item
575  if( it != m_drawings.end( aType ) )
576  {
577  ++it;
578 
579  if( it != m_drawings.end( aType ) )
580  return &( *it );
581  }
582 
583  return NULL;
584 }
585 
586 
587 void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
588 {
589  if( m_drawings.empty( LIB_PIN_T ) )
590  return;
591 
592  /* Notes:
593  * when aUnit == 0: no unit filtering
594  * when aConvert == 0: no convert (shape selection) filtering
595  * when .m_Unit == 0, the body item is common to units
596  * when .m_Convert == 0, the body item is common to shapes
597  */
598  for( LIB_ITEM& item : m_drawings[ LIB_PIN_T ] )
599  {
600  // Unit filtering:
601  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
602  continue;
603 
604  // Shape filtering:
605  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
606  continue;
607 
608  aList.push_back( (LIB_PIN*) &item );
609  }
610 }
611 
612 
613 LIB_PIN* LIB_PART::GetPin( const wxString& aNumber, int aUnit, int aConvert )
614 {
615  LIB_PINS pinList;
616 
617  GetPins( pinList, aUnit, aConvert );
618 
619  for( size_t i = 0; i < pinList.size(); i++ )
620  {
621  wxASSERT( pinList[i]->Type() == LIB_PIN_T );
622 
623  if( aNumber == pinList[i]->GetNumber() )
624  return pinList[i];
625  }
626 
627  return NULL;
628 }
629 
630 
631 bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames,
632  bool aTestType, bool aTestOrientation, bool aTestLength )
633 {
634  LIB_PINS thisPinList;
635  GetPins( thisPinList, /* aUnit */ 0, /* aConvert */ 0 );
636 
637  for( LIB_PIN* eachThisPin : thisPinList )
638  {
639  wxASSERT( eachThisPin );
640  LIB_PINS otherPinList;
641  aOtherPart.GetPins( otherPinList, /* aUnit */ 0, /* aConvert */ 0 );
642  bool foundMatch = false;
643 
644  for( LIB_PIN* eachOtherPin : otherPinList )
645  {
646  wxASSERT( eachOtherPin );
647  // Same position?
648  if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
649  continue;
650 
651  // Same number?
652  if( aTestNums && ( eachThisPin->GetNumber() != eachOtherPin->GetNumber() ))
653  continue;
654 
655  // Same name?
656  if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() ))
657  continue;
658 
659  // Same electrical type?
660  if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() ))
661  continue;
662 
663  // Same orientation?
664  if( aTestOrientation && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() ))
665  continue;
666 
667  // Same length?
668  if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() ))
669  continue;
670 
671  foundMatch = true;
672  }
673 
674  if( !foundMatch )
675  {
676  // This means there was not an identical (according to the arguments)
677  // pin at the same position in the other component.
678  return true;
679  }
680  }
681 
682  // The loop never gave up, so no conflicts were found.
683  return false;
684 }
685 
686 
687 const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const
688 {
689  EDA_RECT bBox;
690  bool initialized = false;
691 
692  for( const LIB_ITEM& item : m_drawings )
693  {
694  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
695  && ( aUnit != item.m_Unit ) ) )
696  continue;
697 
698  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
699  continue;
700 
701  if ( ( item.Type() == LIB_FIELD_T ) && !( ( LIB_FIELD& ) item ).IsVisible() )
702  continue;
703 
704  if( initialized )
705  bBox.Merge( item.GetBoundingBox() );
706  else
707  {
708  bBox = item.GetBoundingBox();
709  initialized = true;
710  }
711  }
712 
713  return bBox;
714 }
715 
716 
717 void LIB_PART::ViewGetLayers( int aLayers[], int& aCount ) const
718 {
719  aCount = 2;
720  aLayers[0] = LAYER_DEVICE;
721  aLayers[1] = LAYER_DEVICE_BACKGROUND;
722 }
723 
724 
725 const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
726 {
727  EDA_RECT bBox;
728  bool initialized = false;
729 
730  for( const LIB_ITEM& item : m_drawings )
731  {
732  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
733  && ( aUnit != item.m_Unit ) ) )
734  continue;
735 
736  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
737  continue;
738 
739  if( item.Type() == LIB_FIELD_T )
740  continue;
741 
742  if( initialized )
743  bBox.Merge( item.GetBoundingBox() );
744  else
745  {
746  bBox = item.GetBoundingBox();
747  initialized = true;
748  }
749  }
750 
751  return bBox;
752 }
753 
754 
756 {
757  m_drawings[ LIB_FIELD_T ].clear();
758 }
759 
760 
761 void LIB_PART::SetFields( const std::vector <LIB_FIELD>& aFields )
762 {
763  deleteAllFields();
764 
765  for( unsigned i=0; i<aFields.size(); ++i )
766  {
767  // drawings is a ptr_vector, new and copy an object on the heap.
768  LIB_FIELD* field = new LIB_FIELD( aFields[i] );
769 
770  field->SetParent( this );
771  m_drawings.push_back( field );
772  }
773 }
774 
775 
777 {
778  LIB_FIELD* field;
779 
780  // Grab the MANDATORY_FIELDS first, in expected order given by
781  // enum NumFieldType
782  for( int id=0; id<MANDATORY_FIELDS; ++id )
783  {
784  field = GetField( id );
785 
786  // the MANDATORY_FIELDS are exactly that in RAM.
787  wxASSERT( field );
788 
789  aList.push_back( *field );
790  }
791 
792  // Now grab all the rest of fields.
793  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
794  {
795  field = ( LIB_FIELD* ) &item;
796 
797  if( (unsigned) field->GetId() < MANDATORY_FIELDS )
798  continue; // was added above
799 
800  aList.push_back( *field );
801  }
802 }
803 
804 
806 {
807  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
808  {
809  LIB_FIELD* field = ( LIB_FIELD* ) &item;
810 
811  if( field->GetId() == aId )
812  return field;
813  }
814 
815  return NULL;
816 }
817 
818 
819 LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
820 {
821  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
822  {
823  LIB_FIELD* field = ( LIB_FIELD* ) &item;
824 
825  if( field->GetName() == aFieldName )
826  return field;
827  }
828 
829  return NULL;
830 }
831 
832 
834 {
835  LIB_FIELD* field = GetField( VALUE );
836  wxASSERT( field != NULL );
837  return *field;
838 }
839 
840 
842 {
843  LIB_FIELD* field = GetField( REFERENCE );
844  wxASSERT( field != NULL );
845  return *field;
846 }
847 
848 
850 {
851  LIB_FIELD* field = GetField( FOOTPRINT );
852  wxASSERT( field != NULL );
853  return *field;
854 }
855 
856 
858 {
859  int year, mon, day, hour, min, sec;
860 
861  if( m_dateLastEdition == 0 )
862  return true;
863 
864  sec = m_dateLastEdition & 63;
865  min = ( m_dateLastEdition >> 6 ) & 63;
866  hour = ( m_dateLastEdition >> 12 ) & 31;
867  day = ( m_dateLastEdition >> 17 ) & 31;
868  mon = ( m_dateLastEdition >> 22 ) & 15;
869  year = ( m_dateLastEdition >> 26 ) + 1990;
870 
871  aFormatter.Print( 0, "Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
872 
873  return true;
874 }
875 
876 
877 bool LIB_PART::LoadDateAndTime( char* aLine )
878 {
879  int year, mon, day, hour, min, sec;
880 
881  year = mon = day = hour = min = sec = 0;
882  strtok( aLine, " \r\t\n" );
883  strtok( NULL, " \r\t\n" );
884 
885  if( sscanf( aLine, "%d/%d/%d %d:%d:%d", &year, &mon, &day, &hour, &min, &sec ) != 6 )
886  return false;
887 
888  m_dateLastEdition = ( sec & 63 ) + ( ( min & 63 ) << 6 ) +
889  ( ( hour & 31 ) << 12 ) + ( ( day & 31 ) << 17 ) +
890  ( ( mon & 15 ) << 22 ) + ( ( year - 1990 ) << 26 );
891 
892  return true;
893 }
894 
895 
896 void LIB_PART::SetOffset( const wxPoint& aOffset )
897 {
898  for( LIB_ITEM& item : m_drawings )
899  item.Offset( aOffset );
900 }
901 
902 
904 {
905  m_drawings.unique();
906 }
907 
908 
910 {
911  for( const LIB_ITEM& item : m_drawings )
912  {
913  if( item.m_Convert > LIB_ITEM::LIB_CONVERT::BASE )
914  return true;
915  }
916 
917  return false;
918 }
919 
921 {
922  for( LIB_ITEM& item : m_drawings )
923  item.ClearTempFlags();
924 }
925 
927 {
928  for( LIB_ITEM& item : m_drawings )
929  item.ClearEditFlags();
930 }
931 
932 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
933  KICAD_T aType, const wxPoint& aPoint )
934 {
935  for( LIB_ITEM& item : m_drawings )
936  {
937  if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
938  || ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
939  || ( ( item.Type() != aType ) && ( aType != TYPE_NOT_INIT ) ) )
940  continue;
941 
942  if( item.HitTest( aPoint ) )
943  return &item;
944  }
945 
946  return NULL;
947 }
948 
949 
950 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
951  const wxPoint& aPoint, const TRANSFORM& aTransform )
952 {
953  /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
954  * wxPoint& pt ) to search items.
955  * because this function uses DefaultTransform as orient/mirror matrix
956  * we temporary copy aTransform in DefaultTransform
957  */
958  LIB_ITEM* item;
959  TRANSFORM transform = DefaultTransform;
960  DefaultTransform = aTransform;
961 
962  item = LocateDrawItem( aUnit, aConvert, aType, aPoint );
963 
964  // Restore matrix
965  DefaultTransform = transform;
966 
967  return item;
968 }
969 
970 
971 SEARCH_RESULT LIB_PART::Visit( INSPECTOR aInspector, void* aTestData, const KICAD_T aFilterTypes[] )
972 {
973  // The part itself is never inspected, only its children
974  for( LIB_ITEM& item : m_drawings )
975  {
976  if( item.IsType( aFilterTypes ) )
977  {
978  if( aInspector( &item, aTestData ) == SEARCH_QUIT )
979  return SEARCH_QUIT;
980  }
981  }
982 
983  return SEARCH_CONTINUE;
984 }
985 
986 
987 void LIB_PART::SetUnitCount( int aCount )
988 {
989  if( m_unitCount == aCount )
990  return;
991 
992  if( aCount < m_unitCount )
993  {
995 
996  while( i != m_drawings.end() )
997  {
998  if( i->m_Unit > aCount )
999  i = m_drawings.erase( i );
1000  else
1001  ++i;
1002  }
1003  }
1004  else
1005  {
1006  int prevCount = m_unitCount;
1007 
1008  // Temporary storage for new items, as adding new items directly to
1009  // m_drawings may cause the buffer reallocation which invalidates the
1010  // iterators
1011  std::vector< LIB_ITEM* > tmp;
1012 
1013  for( LIB_ITEM& item : m_drawings )
1014  {
1015  if( item.m_Unit != 1 )
1016  continue;
1017 
1018  for( int j = prevCount + 1; j <= aCount; j++ )
1019  {
1020  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1021  newItem->m_Unit = j;
1022  tmp.push_back( newItem );
1023  }
1024  }
1025 
1026  for( auto item : tmp )
1027  m_drawings.push_back( item );
1028  }
1029 
1030  m_unitCount = aCount;
1031 }
1032 
1033 
1034 void LIB_PART::SetConversion( bool aSetConvert )
1035 {
1036  if( aSetConvert == HasConversion() )
1037  return;
1038 
1039  // Duplicate items to create the converted shape
1040  if( aSetConvert )
1041  {
1042  std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
1043 
1044  for( LIB_ITEM& item : m_drawings )
1045  {
1046  // Only pins are duplicated.
1047  if( item.Type() != LIB_PIN_T )
1048  continue;
1049 
1050  if( item.m_Convert == 1 )
1051  {
1052  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1053  newItem->m_Convert = 2;
1054  tmp.push_back( newItem );
1055  }
1056  }
1057 
1058  // Transfer the new pins to the LIB_PART.
1059  for( unsigned i = 0; i < tmp.size(); i++ )
1060  m_drawings.push_back( tmp[i] );
1061  }
1062  else
1063  {
1064  // Delete converted shape items because the converted shape does
1065  // not exist
1067 
1068  while( i != m_drawings.end() )
1069  {
1070  if( i->m_Convert > 1 )
1071  i = m_drawings.erase( i );
1072  else
1073  ++i;
1074  }
1075  }
1076 }
1077 
1078 
1079 wxArrayString LIB_PART::GetAliasNames( bool aIncludeRoot ) const
1080 {
1081  wxArrayString names;
1082 
1083  LIB_ALIASES::const_iterator it;
1084 
1085  for( it=m_aliases.begin(); it != m_aliases.end(); ++it )
1086  {
1087  if( !aIncludeRoot && (*it)->IsRoot() )
1088  continue;
1089 
1090  names.Add( (*it)->GetName() );
1091  }
1092 
1093  return names;
1094 }
1095 
1096 
1097 bool LIB_PART::HasAlias( const wxString& aName ) const
1098 {
1099  wxCHECK2_MSG( !aName.IsEmpty(), return false,
1100  wxT( "Cannot get alias with an empty name, bad programmer." ) );
1101 
1102  for( size_t i = 0; i < m_aliases.size(); i++ )
1103  {
1104  if( aName == m_aliases[i]->GetName() )
1105  return true;
1106  }
1107 
1108  return false;
1109 }
1110 
1111 
1112 void LIB_PART::RemoveAlias( const wxString& aName )
1113 {
1114  LIB_ALIAS* a = GetAlias( aName );
1115 
1116  if( a )
1117  RemoveAlias( a );
1118 }
1119 
1120 
1122 {
1123  wxCHECK_MSG( aAlias, NULL, wxT( "Cannot remove alias by NULL pointer." ) );
1124 
1125  LIB_ALIAS* nextAlias = NULL;
1126 
1127  LIB_ALIASES::iterator it = find( m_aliases.begin(), m_aliases.end(), aAlias );
1128 
1129  if( it != m_aliases.end() )
1130  {
1131  bool rename = aAlias->IsRoot();
1132 
1133  wxLogTrace( traceSchLibMem,
1134  wxT( "%s: symbol:'%s', alias:'%s', alias count %llu, reference count %ld." ),
1135  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ),
1136  GetChars( GetName() ),
1137  GetChars( aAlias->GetName() ),
1138  (long long unsigned) m_aliases.size(),
1139  m_me.use_count() );
1140 
1141  it = m_aliases.erase( it );
1142 
1143  if( !m_aliases.empty() )
1144  {
1145  if( it == m_aliases.end() )
1146  it = m_aliases.begin();
1147 
1148  nextAlias = *it;
1149 
1150  if( rename )
1151  SetName( nextAlias->GetName() );
1152  }
1153  }
1154 
1155  return nextAlias;
1156 }
1157 
1158 
1160 {
1161  // Remove all of the aliases except the root alias.
1162  while( m_aliases.size() > 1 )
1163  m_aliases.pop_back();
1164 }
1165 
1166 
1167 LIB_ALIAS* LIB_PART::GetAlias( const wxString& aName )
1168 {
1169  wxCHECK2_MSG( !aName.IsEmpty(), return NULL,
1170  wxT( "Cannot get alias with an empty name. Bad programmer!" ) );
1171 
1172  for( size_t i = 0; i < m_aliases.size(); i++ )
1173  {
1174  if( aName == m_aliases[i]->GetName() )
1175  return m_aliases[i];
1176  }
1177 
1178  return NULL;
1179 }
1180 
1181 
1183 {
1184  wxCHECK2_MSG( aIndex < m_aliases.size(), return NULL,
1185  wxT( "Illegal alias list index, bad programmer." ) );
1186 
1187  return m_aliases[aIndex];
1188 }
1189 
1190 
1191 void LIB_PART::AddAlias( const wxString& aName )
1192 {
1193  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
1194 }
1195 
1196 
1198 {
1199  m_aliases.push_back( aAlias );
1200 }
1201 
1202 
1203 void LIB_PART::SetSubpartIdNotation( int aSep, int aFirstId )
1204 {
1205  m_subpartFirstId = 'A';
1207 
1208  if( aSep == '.' || aSep == '-' || aSep == '_' )
1209  m_subpartIdSeparator = aSep;
1210 
1211  if( aFirstId == '1' && aSep != 0 )
1212  m_subpartFirstId = aFirstId;
1213 }
timestamp_t m_dateLastEdition
Date of the last modification.
LIB_ALIASES m_aliases
List of alias object pointers associated with the part.
void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
PART_LIB * GetLib()
virtual ~LIB_ALIAS()
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:408
void SetLib(PART_LIB *aLibrary)
int GetUnitCount() const
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)
Return 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 ...
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
Part library alias object definition.
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 description
documentation for info
int GetUnitCount() override
For symbols with units, return the number of units.
LIB_ALIAS * GetAlias(size_t aIndex)
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
virtual void SetColor(COLOR4D color)=0
LIB_ID GetLibId() const override
wxString GetSearchText() override
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.
bool empty(int aType=UNDEFINED_TYPE)
Definition: multivector.h:224
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',...
wxString GetUnitReference(int aUnit) override
For symbols with units, return an identifier for unit x.
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 m_Unit
Unit identification for multiple parts per package.
Definition: lib_draw_item.h:89
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
virtual const wxString GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:147
LIB_ALIAS(const wxString &aName, LIB_PART *aRootComponent)
int GetId() const
Definition: lib_field.h:139
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
void AddAlias(const wxString &aName)
Add an alias aName to the part.
LIBRENTRYOPTIONS m_options
Special part features such as POWER or NORMAL.)
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Definition: eeschema.cpp:174
PART_LIB * GetLib()
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_draw_item.h:67
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
wxString GetLibNickname() const override
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.
bool IsVisible() const
Definition: lib_field.h:165
bool LoadDateAndTime(char *aLine)
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:114
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:102
void deleteAllFields()
wxArrayString GetAliasNames(bool aIncludeRoot=true) const
bool IsRoot() const override
For symbols having aliases, IsRoot() indicates the principal item.
void SetName(const wxString &aName)
#define VALUE
void operator()(void const *) const
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.
LIB_FIELD * FindField(const wxString &aFieldName)
Findd a field within this part matching aFieldName and returns it or NULL if not found.
void SetText(const wxString &aText) override
Sets the field text to aText.
Definition: lib_field.cpp:453
void SetUnitCount(int count)
Set the units per part count.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:219
wxString docFileName
Associate doc file name.
LIB_PART * shared
Actual LIB_PART referenced by [multiple] aliases.
void push_back(T *aItem)
Definition: multivector.h:169
Class LIB_ITEM definition.
const wxString & GetKeyWords() const
void SetMaximum()
Definition: box2.h:71
const LIB_ID & GetLibId() const
Define a library symbol object.
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:123
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
wxLogTrace helper definitions.
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).
LIB_PART(const wxString &aName, PART_LIB *aLibrary=NULL)
LIB_ID m_libId
const wxChar *const traceSchLibMem
Flag to enable schematic library memory deletion debug output.
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
const wxString GetLibraryName()
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
const wxString & GetDescription() override
Definitions for the Eeschema program SCH_SCREEN class.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Base plotter engine class.
Definition: plotter.h:97
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_draw_item.h:61
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:100
TRANSFORM DefaultTransform
Definition: eeschema.cpp:59
const wxString & GetName() const override
void RemoveAlias(const wxString &aName)
void RemoveAllAliases()
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
const wxString & GetName() const
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:250
size_t i
Definition: json11.cpp:597
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:331
static wxString SubReference(int aUnit, bool aAddSeparator=true)
void RemoveDrawItem(LIB_ITEM *aItem, EDA_DRAW_PANEL *aPanel=NULL, wxDC *aDc=NULL)
Remove draw aItem from list.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:157
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
bool show_elec_type
Whether to show the pin electrical type.
int m_Convert
Shape identification for alternate body styles.
Definition: lib_draw_item.h:96
LIB_ITEM * LocateDrawItem(int aUnit, int aConvert, KICAD_T aType, const wxPoint &aPoint)
Locate a draw object.
virtual void SetName(const wxString &aName)
bool operator==(const wxChar *aName) const
KEEPCASE sensitive comparison of the part entry name.
virtual const BOX2I ViewBBox() const override
Returns a default bounding box for the alias.
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:152
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:404
SEARCH_RESULT
Definition: base_struct.h:66
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
Definition: gr_basic.cpp:214
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:261
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.
Object used to load, save, search, and otherwise manipulate symbol library files.
TRANSFORM transform
Coordinate adjustment settings.
wxString keyWords
keyword list (used for search for parts by keyword)
void GetFields(LIB_FIELDS &aList)
Return a list of fields within this part.
bool HasAlias(const wxString &aName) const
Test if alias aName is in part alias list.
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:204
#define min(a, b)
Definition: auxiliary.h:85
bool SaveDateAndTime(OUTPUTFORMATTER &aFormatter)
Write the date and time of part to aFile in the format: "Ti yy/mm/jj hh:mm:ss".
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