KiCad PCB EDA Suite
Loading...
Searching...
No Matches
lib_symbol.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 <[email protected]>
6 * Copyright (C) 2022 CERN
7 * Copyright (C) 2004-2024 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <sch_draw_panel.h>
28#include <plotters/plotter.h>
29#include <sch_screen.h>
30#include <template_fieldnames.h>
31#include <transform.h>
32#include <symbol_library.h>
34#include <sch_pin.h>
35#include <sch_shape.h>
36
37#include <memory>
38
39std::vector<SEARCH_TERM> LIB_SYMBOL::GetSearchTerms()
40{
41 std::vector<SEARCH_TERM> terms;
42
43 terms.emplace_back( SEARCH_TERM( GetName(), 8 ) );
44
45 wxStringTokenizer keywordTokenizer( GetKeyWords(), wxS( " " ), wxTOKEN_STRTOK );
46
47 while( keywordTokenizer.HasMoreTokens() )
48 terms.emplace_back( SEARCH_TERM( keywordTokenizer.GetNextToken(), 4 ) );
49
50 // TODO(JE) rework this later so we can highlight matches in their column
51 std::map<wxString, wxString> fields;
52 GetChooserFields( fields );
53
54 for( const auto& [ name, text ] : fields )
55 terms.emplace_back( SEARCH_TERM( text, 4 ) );
56
57 // Also include keywords as one long string, just in case
58 terms.emplace_back( SEARCH_TERM( GetKeyWords(), 1 ) );
59 terms.emplace_back( SEARCH_TERM( GetDescription(), 1 ) );
60
61 wxString footprint = GetFootprintField().GetText();
62
63 if( !footprint.IsEmpty() )
64 terms.emplace_back( SEARCH_TERM( GetFootprintField().GetText(), 1 ) );
65
66 return terms;
67}
68
69
70void LIB_SYMBOL::GetChooserFields( std::map<wxString, wxString>& aColumnMap )
71{
72 for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
73 {
74 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
75
76 if( field->ShowInChooser() )
77 aColumnMap[field->GetName()] = field->EDA_TEXT::GetShownText( false );
78 }
79}
80
81
82bool operator<( const LIB_SYMBOL& aItem1, const LIB_SYMBOL& aItem2 )
83{
84 return aItem1.GetName() < aItem2.GetName();
85}
86
87
90{
91 void operator()(void const *) const
92 {
93 }
94};
95
96
97LIB_SYMBOL::LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent, SYMBOL_LIB* aLibrary ) :
99 m_me( this, null_deleter() )
100{
101 m_lastModDate = 0;
102 m_unitCount = 1;
105 m_unitsLocked = false;
106
107 // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present
108 // when the field editors are invoked.
110
111 for( int i = 0; i < MANDATORY_FIELDS; i++ )
112 m_drawings[SCH_FIELD_T].push_back( new SCH_FIELD( this, i ) );
113
114 // Ensure reference and value fields are visible when creating a lib symbol
115 // whatever the SCH_FIELD Ctor default value is.
117 GetValueField().SetVisible( true );
118
119 // Set visibilty to false for these other mandatory fields (at lest for now)
120 // whatever the SCH_FIELD Ctor default value is.
121 GetFootprintField().SetVisible( false );
122 GetDatasheetField().SetVisible( false );
124
125 SetName( aName );
126
127 if( aParent )
128 SetParent( aParent );
129
130 SetLib( aLibrary );
131}
132
133
134LIB_SYMBOL::LIB_SYMBOL( const LIB_SYMBOL& aSymbol, SYMBOL_LIB* aLibrary ) :
135 SYMBOL( aSymbol ),
136 m_me( this, null_deleter() )
137{
138 m_library = aLibrary;
139 m_name = aSymbol.m_name;
140 m_fpFilters = wxArrayString( aSymbol.m_fpFilters );
141 m_unitCount = aSymbol.m_unitCount;
144 m_options = aSymbol.m_options;
145 m_libId = aSymbol.m_libId;
146 m_keyWords = aSymbol.m_keyWords;
147
149
151
152 for( const SCH_ITEM& oldItem : aSymbol.m_drawings )
153 {
154 if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
155 continue;
156
157 try
158 {
159 SCH_ITEM* newItem = (SCH_ITEM*) oldItem.Clone();
160 newItem->ClearSelected();
161 newItem->SetParent( this );
162 m_drawings.push_back( newItem );
163 }
164 catch( ... )
165 {
166 wxFAIL_MSG( "Failed to clone SCH_ITEM." );
167 return;
168 }
169 }
170
171 LIB_SYMBOL_SPTR parent = aSymbol.m_parent.lock();
172
173 if( parent )
174 SetParent( parent.get() );
175}
176
177
179{
180 if( &aSymbol == this )
181 return aSymbol;
182
183 SYMBOL::operator=( aSymbol );
184
185 m_library = aSymbol.m_library;
186 m_name = aSymbol.m_name;
187 m_fpFilters = wxArrayString( aSymbol.m_fpFilters );
188 m_unitCount = aSymbol.m_unitCount;
191 m_options = aSymbol.m_options;
192 m_libId = aSymbol.m_libId;
193 m_keyWords = aSymbol.m_keyWords;
194
195 m_unitDisplayNames.clear();
197
199
200 for( const SCH_ITEM& oldItem : aSymbol.m_drawings )
201 {
202 if( ( oldItem.GetFlags() & ( IS_NEW | STRUCT_DELETED ) ) != 0 )
203 continue;
204
205 SCH_ITEM* newItem = (SCH_ITEM*) oldItem.Clone();
206 newItem->SetParent( this );
207 m_drawings.push_back( newItem );
208 }
209
211
212 LIB_SYMBOL_SPTR parent = aSymbol.m_parent.lock();
213
214 if( parent )
215 SetParent( parent.get() );
216
217 return *this;
218}
219
220
222{
223 unsigned depth = 0;
224
225 LIB_SYMBOL_SPTR parent = GetParent().lock();
226
227 while( parent )
228 {
229 depth += 1;
230 parent = parent->GetParent().lock();
231 }
232
233 return depth;
234}
235
236
237#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); }
238#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider )
239
240int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
241{
242 UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MILLIMETRES );
243
244 if( m_me == aRhs.m_me )
245 return 0;
246
247 if( !aReporter && ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
248 {
249 if( int tmp = m_name.Cmp( aRhs.m_name ) )
250 return tmp;
251
252 if( int tmp = m_libId.compare( aRhs.m_libId ) )
253 return tmp;
254
255 if( m_parent.lock() < aRhs.m_parent.lock() )
256 return -1;
257
258 if( m_parent.lock() > aRhs.m_parent.lock() )
259 return 1;
260 }
261
262 int retv = 0;
263
264 if( m_options != aRhs.m_options )
265 {
266 retv = ( m_options == ENTRY_NORMAL ) ? -1 : 1;
267 REPORT( _( "Power flag differs." ) );
268
269 if( !aReporter )
270 return retv;
271 }
272
273 if( int tmp = m_unitCount - aRhs.m_unitCount )
274 {
275 retv = tmp;
276 REPORT( _( "Unit count differs." ) );
277
278 if( !aReporter )
279 return retv;
280 }
281
282 // Make sure shapes and pins are sorted. No need with fields as those are
283 // matched by id/name.
284
285 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
286 std::set<const SCH_ITEM*> aFields;
287 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aPins;
288
289 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
290 {
291 if( it->Type() == SCH_SHAPE_T )
292 aShapes.insert( &(*it) );
293 else if( it->Type() == SCH_FIELD_T )
294 aFields.insert( &(*it) );
295 else if( it->Type() == SCH_PIN_T )
296 aPins.insert( &(*it) );
297 }
298
299 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
300 std::set<const SCH_ITEM*> bFields;
301 std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bPins;
302
303 for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
304 {
305 if( it->Type() == SCH_SHAPE_T )
306 bShapes.insert( &(*it) );
307 else if( it->Type() == SCH_FIELD_T )
308 bFields.insert( &(*it) );
309 else if( it->Type() == SCH_PIN_T )
310 bPins.insert( &(*it) );
311 }
312
313 if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
314 {
315 retv = tmp;
316 REPORT( _( "Graphic item count differs." ) );
317
318 if( !aReporter )
319 return retv;
320 }
321 else
322 {
323 for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
324 {
325 if( int tmp2 = (*aIt)->compare( *(*bIt), aCompareFlags ) )
326 {
327 retv = tmp2;
328 REPORT( wxString::Format( _( "%s differs." ), ITEM_DESC( *aIt ) ) );
329
330 if( !aReporter )
331 return retv;
332 }
333 }
334 }
335
336 if( int tmp = static_cast<int>( aPins.size() - bPins.size() ) )
337 {
338 retv = tmp;
339 REPORT( _( "Pin count differs." ) );
340
341 if( !aReporter )
342 return retv;
343 }
344 else
345 {
346 for( const SCH_ITEM* aPinItem : aPins )
347 {
348 const SCH_PIN* aPin = static_cast<const SCH_PIN*>( aPinItem );
349 const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(),
350 aPin->GetBodyStyle() );
351
352 if( !bPin )
353 {
354 retv = 1;
355 REPORT( wxString::Format( _( "Pin %s not found." ), aPin->GetNumber() ) );
356
357 if( !aReporter )
358 return retv;
359 }
360 else if( int tmp2 = aPinItem->compare( *bPin, aCompareFlags ) )
361 {
362 retv = tmp2;
363 REPORT( wxString::Format( _( "Pin %s differs." ), aPin->GetNumber() ) );
364
365 if( !aReporter )
366 return retv;
367 }
368 }
369 }
370
371 for( const SCH_ITEM* aFieldItem : aFields )
372 {
373 const SCH_FIELD* aField = static_cast<const SCH_FIELD*>( aFieldItem );
374 const SCH_FIELD* bField = nullptr;
375 int tmp = 0;
376
377 if( aField->IsMandatory() )
378 bField = aRhs.GetFieldById( aField->GetId() );
379 else
380 bField = aRhs.FindField( aField->GetName() );
381
382 if( !bField )
383 tmp = 1;
384 else
385 tmp = aFieldItem->compare( *bField, aCompareFlags );
386
387 if( tmp )
388 {
389 retv = tmp;
390 REPORT( wxString::Format( _( "%s field differs." ), aField->GetName( false ) ) );
391
392 if( !aReporter )
393 return retv;
394 }
395 }
396
397 if( int tmp = static_cast<int>( aFields.size() - bFields.size() ) )
398 {
399 retv = tmp;
400 REPORT( _( "Field count differs." ) );
401
402 if( !aReporter )
403 return retv;
404 }
405
406 if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
407 {
408 retv = tmp;
409 REPORT( _( "Footprint filters differs." ) );
410
411 if( !aReporter )
412 return retv;
413 }
414 else
415 {
416 for( size_t i = 0; i < m_fpFilters.GetCount(); i++ )
417 {
418 if( int tmp2 = m_fpFilters[i].Cmp( aRhs.m_fpFilters[i] ) )
419 {
420 retv = tmp2;
421 REPORT( _( "Footprint filters differ." ) );
422
423 if( !aReporter )
424 return retv;
425 }
426 }
427 }
428
429 if( int tmp = m_keyWords.Cmp( aRhs.m_keyWords ) )
430 {
431 retv = tmp;
432 REPORT( _( "Symbol keywords differ." ) );
433
434 if( !aReporter )
435 return retv;
436 }
437
438 if( int tmp = m_pinNameOffset - aRhs.m_pinNameOffset )
439 {
440 retv = tmp;
441 REPORT( _( "Symbol pin name offsets differ." ) );
442
443 if( !aReporter )
444 return retv;
445 }
446
447 if( ( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::ERC ) == 0 )
448 {
449 if( m_showPinNames != aRhs.m_showPinNames )
450 {
451 retv = ( m_showPinNames ) ? 1 : -1;
452 REPORT( _( "Show pin names settings differ." ) );
453
454 if( !aReporter )
455 return retv;
456 }
457
459 {
460 retv = ( m_showPinNumbers ) ? 1 : -1;
461 REPORT( _( "Show pin numbers settings differ." ) );
462
463 if( !aReporter )
464 return retv;
465 }
466
468 {
469 retv = ( m_excludedFromSim ) ? -1 : 1;
470 REPORT( _( "Exclude from simulation settings differ." ) );
471
472 if( !aReporter )
473 return retv;
474 }
475
477 {
478 retv = ( m_excludedFromBOM ) ? -1 : 1;
479 REPORT( _( "Exclude from bill of materials settings differ." ) );
480
481 if( !aReporter )
482 return retv;
483 }
484
486 {
487 retv = ( m_excludedFromBoard ) ? -1 : 1;
488 REPORT( _( "Exclude from board settings differ." ) );
489
490 if( !aReporter )
491 return retv;
492 }
493 }
494
495 if( !aReporter )
496 {
497 if( m_unitsLocked != aRhs.m_unitsLocked )
498 return ( m_unitsLocked ) ? 1 : -1;
499
500 // Compare unit display names
502 return -1;
503 else if( m_unitDisplayNames > aRhs.m_unitDisplayNames )
504 return 1;
505 }
506
507 return retv;
508}
509
510
512{
513 const LIB_SYMBOL_SPTR sp = m_parent.lock();
514
515 // Recurse until the parent symbol is empty.
516 if( sp )
517 return sp->GetRootSymbol();
518
519 return m_me;
520}
521
522
523wxString LIB_SYMBOL::GetUnitReference( int aUnit )
524{
525 return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
526}
527
528
530{
531 return ( m_unitDisplayNames.count( aUnit ) == 1 );
532}
533
534
536{
537 if( HasUnitDisplayName( aUnit ) )
538 return m_unitDisplayNames[aUnit];
539 else
540 return wxString::Format( _( "Unit %s" ), GetUnitReference( aUnit ) );
541}
542
543
544void LIB_SYMBOL::CopyUnitDisplayNames( std::map<int, wxString>& aTarget ) const
545{
546 for( const auto& it : m_unitDisplayNames )
547 aTarget[it.first] = it.second;
548}
549
550
551void LIB_SYMBOL::SetUnitDisplayName( int aUnit, const wxString& aName )
552{
553 if( aUnit <= GetUnitCount() )
554 {
555 if( aName.Length() > 0 )
556 m_unitDisplayNames[aUnit] = aName;
557 else
558 m_unitDisplayNames.erase( aUnit );
559 }
560}
561
562
563void LIB_SYMBOL::SetName( const wxString& aName )
564{
565 m_name = aName;
566 m_libId.SetLibItemName( aName );
567}
568
569
571{
572 if( aParent )
573 m_parent = aParent->SharedPtr();
574 else
575 m_parent.reset();
576}
577
578
579std::unique_ptr< LIB_SYMBOL > LIB_SYMBOL::Flatten() const
580{
581 std::unique_ptr< LIB_SYMBOL > retv;
582
583 if( IsAlias() )
584 {
585 LIB_SYMBOL_SPTR parent = m_parent.lock();
586
587 wxCHECK_MSG( parent, retv,
588 wxString::Format( "Parent of derived symbol '%s' undefined", m_name ) );
589
590 // Copy the parent.
591 if( parent->IsAlias() )
592 retv = parent->Flatten();
593 else
594 retv = std::make_unique<LIB_SYMBOL>( *parent.get() );
595
596 retv->m_name = m_name;
597 retv->SetLibId( m_libId );
598
599 // Now add the inherited part mandatory field (this) information.
600 for( int i = 0; i < MANDATORY_FIELDS; i++ )
601 {
602 wxString tmp = GetFieldById( i )->GetText();
603
604 // If the field isn't defined then inherit the parent field value.
605 if( tmp.IsEmpty() )
606 retv->GetFieldById( i )->SetText( retv->GetFieldById( i )->GetText() );
607 else
608 *retv->GetFieldById( i ) = *GetFieldById( i );
609 }
610
611 // Grab all the rest of derived symbol fields.
612 for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
613 {
614 const SCH_FIELD* aliasField = static_cast<const SCH_FIELD*>( &item );
615
616 // Mandatory fields were already resolved.
617 if( aliasField->IsMandatory() )
618 continue;
619
620 SCH_FIELD* newField = new SCH_FIELD( *aliasField );
621 newField->SetParent( retv.get() );
622
623 SCH_FIELD* parentField = retv->FindField( aliasField->GetName() );
624
625 if( !parentField ) // Derived symbol field does not exist in parent symbol.
626 {
627 retv->AddDrawItem( newField );
628 }
629 else // Derived symbol field overrides the parent symbol field.
630 {
631 retv->RemoveDrawItem( parentField );
632 retv->AddDrawItem( newField );
633 }
634 }
635
636 retv->SetKeyWords( m_keyWords.IsEmpty() ? parent->GetKeyWords() : m_keyWords );
637 retv->SetFPFilters( m_fpFilters.IsEmpty() ? parent->GetFPFilters() : m_fpFilters );
638
639 retv->SetExcludedFromSim( parent->GetExcludedFromSim() );
640 retv->SetExcludedFromBOM( parent->GetExcludedFromBOM() );
641 retv->SetExcludedFromBoard( parent->GetExcludedFromBoard() );
642
643 retv->UpdateFieldOrdinals();
644 }
645 else
646 {
647 retv = std::make_unique<LIB_SYMBOL>( *this );
648 }
649
650 return retv;
651}
652
653
654const wxString LIB_SYMBOL::GetLibraryName() const
655{
656 if( m_library )
657 return m_library->GetName();
658
659 return m_libId.GetLibNickname();
660}
661
662
664{
665 std::shared_ptr<LIB_SYMBOL> parent;
666
667 if( !m_parent.expired() && ( parent = m_parent.lock() ) )
668 {
669 if( parent->IsRoot() )
670 return parent->m_options == ENTRY_POWER;
671 else
672 return parent->IsPower();
673 }
674
675 return m_options == ENTRY_POWER;
676}
677
678
680{
681 if( LIB_SYMBOL_SPTR parent = m_parent.lock() )
682 {
683 if( parent->IsRoot() )
684 parent->m_options = ENTRY_POWER;
685 else
686 parent->SetPower();
687 }
688
690}
691
692
694{
695 if( LIB_SYMBOL_SPTR parent = m_parent.lock() )
696 {
697 if( parent->IsRoot() )
698 return parent->m_options == ENTRY_NORMAL;
699 else
700 return parent->IsNormal();
701 }
702
703 return m_options == ENTRY_NORMAL;
704}
705
706
708{
709 if( LIB_SYMBOL_SPTR parent = m_parent.lock() )
710 {
711 if( parent->IsRoot() )
712 parent->m_options = ENTRY_NORMAL;
713 else
714 parent->SetNormal();
715 }
716
718}
719
720
721wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
722{
723 // use letters as notation. To allow more than 26 units, the sub ref
724 // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
725 // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
726 int u;
727 wxString suffix;
728
729 do
730 {
731 u = ( aUnit - 1 ) % 26;
732 suffix = wxChar( aFirstId + u ) + suffix;
733 aUnit = ( aUnit - u ) / 26;
734 } while( aUnit > 0 );
735
736 return suffix;
737}
738
739
740void LIB_SYMBOL::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle,
741 const VECTOR2I& aOffset, bool aForceNoFill, bool aDimmed )
742{
743 for( SCH_ITEM& item : m_drawings )
744 {
745 // Do not print private items
746 if( item.IsPrivate() )
747 continue;
748
749 // Do not draw items not attached to the current part
750 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
751 continue;
752
753 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
754 continue;
755
756 if( item.Type() == SCH_PIN_T )
757 {
758 item.Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
759 }
760 else if( item.Type() == SCH_FIELD_T )
761 {
762 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
763
764 if( ( field.IsVisible() && aSettings->m_ShowVisibleFields )
765 || ( !field.IsVisible() && aSettings->m_ShowHiddenFields ) )
766 {
767 item.Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
768 }
769 }
770 else if( item.Type() == SCH_SHAPE_T )
771 {
772 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
773
774 if( shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
775 aForceNoFill = true;
776
777 shape.Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
778 }
779 else
780 {
781 item.Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
782 }
783 }
784}
785
786
787void LIB_SYMBOL::PrintBackground( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle,
788 const VECTOR2I& aOffset, bool aDimmed )
789{
790 /* draw background for filled items using background option
791 * Solid lines will be drawn after the background
792 * Note also, background is not drawn when printing in black and white
793 */
795 {
796 for( SCH_ITEM& item : m_drawings )
797 {
798 // Do not print private items
799 if( item.IsPrivate() )
800 continue;
801
802 if( item.Type() == SCH_SHAPE_T )
803 {
804 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
805
806 // Do not draw items not attached to the current part
807 if( aUnit && shape.m_unit && ( shape.m_unit != aUnit ) )
808 continue;
809
810 if( aBodyStyle && shape.m_bodyStyle && ( shape.m_bodyStyle != aBodyStyle ) )
811 continue;
812
813 if( shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
814 shape.Print( aSettings, aUnit, aBodyStyle, aOffset, false, aDimmed );
815 }
816 }
817 }
818}
819
820
821void LIB_SYMBOL::Plot( PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
822 int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed )
823{
824 wxASSERT( aPlotter != nullptr );
825
826 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
827 COLOR4D color = renderSettings->GetLayerColor( LAYER_DEVICE );
828 COLOR4D bg = renderSettings->GetBackgroundColor();
829
830 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
831 bg = COLOR4D::WHITE;
832
833 if( aDimmed )
834 {
835 color.Desaturate( );
836 color = color.Mix( bg, 0.5f );
837 }
838
839 aPlotter->SetColor( color );
840
841 for( SCH_ITEM& item : m_drawings )
842 {
843 // Do not plot private items
844 if( item.IsPrivate() )
845 continue;
846
847 // LIB_FIELDs are not plotted here, because this plot function is used to plot schematic
848 // items which have their own SCH_FIELDs
849 if( item.Type() == SCH_FIELD_T )
850 continue;
851
852 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
853 continue;
854
855 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
856 continue;
857
858 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
859 }
860}
861
862
863void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
864 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
865{
866 wxASSERT( aPlotter != nullptr );
867
868 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
869 COLOR4D color = renderSettings->GetLayerColor( LAYER_FIELDS );
870 COLOR4D bg = renderSettings->GetBackgroundColor();
871
872 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
873 bg = COLOR4D::WHITE;
874
875 if( aDimmed )
876 {
877 color.Desaturate( );
878 color = color.Mix( bg, 0.5f );
879 }
880
881 aPlotter->SetColor( color );
882
883 for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
884 {
885 SCH_FIELD& field = static_cast<SCH_FIELD&>( item );
886
887 if( !renderSettings->m_ShowHiddenFields && !field.IsVisible() )
888 continue;
889
890 // The reference is a special case: we should change the basic text
891 // to add '?' and the part id
892 wxString tmp = field.GetText();
893
894 field.SetText( field.GetFullText( aUnit ) );
895 item.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
896
897 field.SetText( tmp );
898 }
899}
900
901
903{
904 std::vector<SCH_SHAPE*> potential_top_items;
905 std::vector<SCH_ITEM*> bottom_items;
906
907 for( SCH_ITEM& item : m_drawings )
908 {
909 if( item.Type() == SCH_SHAPE_T )
910 {
911 SCH_SHAPE& shape = static_cast<SCH_SHAPE&>( item );
912
913 if( shape.GetFillMode() == FILL_T::FILLED_WITH_COLOR )
914 potential_top_items.push_back( &shape );
915 else
916 bottom_items.push_back( &item );
917 }
918 else
919 {
920 bottom_items.push_back( &item );
921 }
922 }
923
924 std::sort( potential_top_items.begin(), potential_top_items.end(),
925 []( SCH_ITEM* a, SCH_ITEM* b )
926 {
927 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
928 } );
929
930 for( SCH_SHAPE* item : potential_top_items )
931 {
932 for( SCH_ITEM* bottom_item : bottom_items )
933 {
934 if( item->GetBoundingBox().Contains( bottom_item->GetBoundingBox() ) )
935 {
936 item->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
937 break;
938 }
939 }
940 }
941}
942
943
945{
946 wxASSERT( aItem != nullptr );
947
948 // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
949 // omitted when saving to disk.
950 if( aItem->Type() == SCH_FIELD_T )
951 {
952 if( static_cast<SCH_FIELD*>( aItem )->IsMandatory() )
953 return;
954 }
955
956 LIB_ITEMS& items = m_drawings[ aItem->Type() ];
957
958 for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
959 {
960 if( &*i == aItem )
961 {
962 items.erase( i );
963 break;
964 }
965 }
966}
967
968
969void LIB_SYMBOL::AddDrawItem( SCH_ITEM* aItem, bool aSort )
970{
971 wxCHECK( aItem, /* void */ );
972
973 aItem->SetParent( this );
974
975 m_drawings.push_back( aItem );
976
977 if( aSort )
979}
980
981
982std::vector<SCH_PIN*> LIB_SYMBOL::GetPins( int aUnit, int aBodyStyle ) const
983{
984 std::vector<SCH_PIN*> pins;
985
986 /* Notes:
987 * when aUnit == 0: no unit filtering
988 * when aBodyStyle == 0: no body style filtering
989 * when m_unit == 0, the item is common to all units
990 * when m_bodyStyle == 0, the item is common to all body styles
991 */
992
993 LIB_SYMBOL_SPTR parent = m_parent.lock();
994 const LIB_ITEMS_CONTAINER& drawItems = parent ? parent->m_drawings : m_drawings;
995
996 for( const SCH_ITEM& item : drawItems[SCH_PIN_T] )
997 {
998 // Unit filtering:
999 if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
1000 continue;
1001
1002 // De Morgan variant filtering:
1003 if( aBodyStyle && item.m_bodyStyle && ( item.m_bodyStyle != aBodyStyle ) )
1004 continue;
1005
1006 // TODO: get rid of const_cast. (It used to be a C-style cast so was less noticeable.)
1007 pins.push_back( const_cast<SCH_PIN*>( static_cast<const SCH_PIN*>( &item ) ) );
1008 }
1009
1010 return pins;
1011}
1012
1013
1014std::vector<SCH_PIN*> LIB_SYMBOL::GetAllLibPins() const
1015{
1016 return GetPins( 0, 0 );
1017}
1018
1019
1021{
1022 return (int) GetPins( 0 /* all units */, 1 /* single body style */ ).size();
1023}
1024
1025
1026SCH_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aBodyStyle ) const
1027{
1028 for( SCH_PIN* pin : GetPins( aUnit, aBodyStyle ) )
1029 {
1030 if( aNumber == pin->GetNumber() )
1031 return pin;
1032 }
1033
1034 return nullptr;
1035}
1036
1037
1038bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames,
1039 bool aTestType, bool aTestOrientation, bool aTestLength ) const
1040{
1041 std::vector<SCH_PIN*> thisPinList = GetAllLibPins();
1042
1043 for( const SCH_PIN* eachThisPin : thisPinList )
1044 {
1045 wxASSERT( eachThisPin );
1046 std::vector<SCH_PIN*> otherPinList = aOtherPart.GetAllLibPins();
1047 bool foundMatch = false;
1048
1049 for( const SCH_PIN* eachOtherPin : otherPinList )
1050 {
1051 wxASSERT( eachOtherPin );
1052
1053 // Same unit?
1054 if( eachThisPin->GetUnit() != eachOtherPin->GetUnit() )
1055 continue;
1056
1057 // Same body stype?
1058 if( eachThisPin->GetBodyStyle() != eachOtherPin->GetBodyStyle() )
1059 continue;
1060
1061 // Same position?
1062 if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
1063 continue;
1064
1065 // Same number?
1066 if( aTestNums && ( eachThisPin->GetNumber() != eachOtherPin->GetNumber() ) )
1067 continue;
1068
1069 // Same name?
1070 if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() ) )
1071 continue;
1072
1073 // Same electrical type?
1074 if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() ) )
1075 continue;
1076
1077 // Same orientation?
1078 if( aTestOrientation
1079 && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() ) )
1080 continue;
1081
1082 // Same length?
1083 if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() ) )
1084 continue;
1085
1086 foundMatch = true;
1087 break; // Match found so search is complete.
1088 }
1089
1090 if( !foundMatch )
1091 {
1092 // This means there was not an identical (according to the arguments)
1093 // pin at the same position in the other symbol.
1094 return true;
1095 }
1096 }
1097
1098 // The loop never gave up, so no conflicts were found.
1099 return false;
1100}
1101
1102
1103const BOX2I LIB_SYMBOL::GetUnitBoundingBox( int aUnit, int aBodyStyle,
1104 bool aIgnoreHiddenFields ) const
1105{
1106 BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works
1107
1108 for( const SCH_ITEM& item : m_drawings )
1109 {
1110 if( item.m_unit > 0 && m_unitCount > 1 && aUnit > 0 && aUnit != item.m_unit )
1111 continue;
1112
1113 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1114 continue;
1115
1116 if( aIgnoreHiddenFields && item.Type() == SCH_FIELD_T )
1117 {
1118 if( !static_cast<const SCH_FIELD&>( item ).IsVisible() )
1119 continue;
1120 }
1121
1122 bBox.Merge( item.GetBoundingBox() );
1123 }
1124
1125 return bBox;
1126}
1127
1128
1129const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aIncludePins,
1130 bool aIncludePrivateItems ) const
1131{
1132 BOX2I bbox;
1133
1134 for( const SCH_ITEM& item : m_drawings )
1135 {
1136 if( item.m_unit > 0 && aUnit > 0 && aUnit != item.m_unit )
1137 continue;
1138
1139 if( item.m_bodyStyle > 0 && aBodyStyle > 0 && aBodyStyle != item.m_bodyStyle )
1140 continue;
1141
1142 if( item.IsPrivate() && !aIncludePrivateItems )
1143 continue;
1144
1145 if( item.Type() == SCH_FIELD_T )
1146 continue;
1147
1148 if( item.Type() == SCH_PIN_T )
1149 {
1150 const SCH_PIN& pin = static_cast<const SCH_PIN&>( item );
1151
1152 if( pin.IsVisible() )
1153 {
1154 // Note: the roots of the pins are always included for symbols that don't have
1155 // a well-defined body.
1156
1157 if( aIncludePins )
1158 bbox.Merge( pin.GetBoundingBox( false, false, false ) );
1159 else
1160 bbox.Merge( pin.GetPinRoot() );
1161 }
1162 }
1163 else
1164 {
1165 bbox.Merge( item.GetBoundingBox() );
1166 }
1167 }
1168
1169 return bbox;
1170}
1171
1172
1174{
1176}
1177
1178
1180{
1181 AddDrawItem( aField );
1182}
1183
1184
1185void LIB_SYMBOL::SetFields( const std::vector<SCH_FIELD>& aFieldsList )
1186{
1188
1189 for( const SCH_FIELD& src : aFieldsList )
1190 {
1191 // drawings is a ptr_vector, new and copy an object on the heap.
1192 SCH_FIELD* field = new SCH_FIELD( src );
1193
1194 field->SetParent( this );
1195 m_drawings.push_back( field );
1196 }
1197
1198 m_drawings.sort();
1199}
1200
1201
1202void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD*>& aList )
1203{
1204 // Grab the MANDATORY_FIELDS first, in expected order given by enum MANDATORY_FIELD_T
1205 for( int id = 0; id < MANDATORY_FIELDS; ++id )
1206 aList.push_back( GetFieldById( id ) );
1207
1208 // Now grab all the rest of fields.
1209 for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
1210 {
1211 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1212
1213 if( !field->IsMandatory() )
1214 aList.push_back( field );
1215 }
1216}
1217
1218
1219void LIB_SYMBOL::GetFields( std::vector<SCH_FIELD>& aList )
1220{
1221 // Grab the MANDATORY_FIELDS first, in expected order given by enum MANDATORY_FIELD_T
1222 for( int id = 0; id < MANDATORY_FIELDS; ++id )
1223 aList.push_back( *GetFieldById( id ) );
1224
1225 // Now grab all the rest of fields.
1226 for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
1227 {
1228 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1229
1230 if( !field->IsMandatory() )
1231 aList.push_back( *field );
1232 }
1233}
1234
1235
1237{
1238 for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
1239 {
1240 SCH_FIELD* field = ( SCH_FIELD* ) &item;
1241
1242 if( field->GetId() == aId )
1243 return field;
1244 }
1245
1246 return nullptr;
1247}
1248
1249
1250SCH_FIELD* LIB_SYMBOL::FindField( const wxString& aFieldName, bool aCaseInsensitive )
1251{
1252 for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
1253 {
1254 if( aCaseInsensitive )
1255 {
1256 if( static_cast<SCH_FIELD*>( &item )->GetCanonicalName().Upper() == aFieldName.Upper() )
1257 return static_cast<SCH_FIELD*>( &item );
1258 }
1259 else
1260 {
1261 if( static_cast<SCH_FIELD*>( &item )->GetCanonicalName() == aFieldName )
1262 return static_cast<SCH_FIELD*>( &item );
1263 }
1264 }
1265
1266 return nullptr;
1267}
1268
1269
1270const SCH_FIELD* LIB_SYMBOL::FindField( const wxString& aFieldName,
1271 bool aCaseInsensitive ) const
1272{
1273 for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
1274 {
1275 const SCH_FIELD& field = static_cast<const SCH_FIELD&>( item );
1276
1277 if( aCaseInsensitive )
1278 {
1279 if( field.GetCanonicalName().Upper() == aFieldName.Upper() )
1280 return &field;
1281 }
1282 else
1283 {
1284 if( field.GetCanonicalName() == aFieldName )
1285 return &field;
1286 }
1287 }
1288
1289 return nullptr;
1290}
1291
1292
1294{
1296 wxASSERT( field != nullptr );
1297 return *field;
1298}
1299
1300
1302{
1304 wxASSERT( field != nullptr );
1305 return *field;
1306}
1307
1308
1310{
1312 wxASSERT( field != nullptr );
1313 return *field;
1314}
1315
1316
1318{
1320 wxASSERT( field != nullptr );
1321 return *field;
1322}
1323
1324
1326{
1328 wxASSERT( field != nullptr );
1329 return *field;
1330}
1331
1332
1334{
1335 wxString refDesignator = GetFieldById( REFERENCE_FIELD )->GetText();
1336
1337 refDesignator.Replace( wxS( "~" ), wxS( " " ) );
1338
1339 wxString prefix = refDesignator;
1340
1341 while( prefix.Length() )
1342 {
1343 wxUniCharRef last = prefix.Last();
1344
1345 if( ( last >= '0' && last <= '9' ) || last == '?' || last == '*' )
1346 prefix.RemoveLast();
1347 else
1348 break;
1349 }
1350
1351 // Avoid a prefix containing trailing/leading spaces
1352 prefix.Trim( true );
1353 prefix.Trim( false );
1354
1355 return prefix;
1356}
1357
1358
1359void LIB_SYMBOL::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
1360{
1361 for( SCH_ITEM& item : m_drawings )
1362 aFunction( &item );
1363}
1364
1365
1367{
1368 int retv = 0;
1369 int lastOrdinal = MANDATORY_FIELDS;
1370
1371 for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] )
1372 {
1373 SCH_FIELD* field = static_cast<SCH_FIELD*>( &item );
1374
1375 // Mandatory fields were already resolved always have the same ordinal values.
1376 if( field->IsMandatory() )
1377 continue;
1378
1379 if( field->GetId() != lastOrdinal )
1380 {
1381 field->SetId( lastOrdinal );
1382 retv += 1;
1383 }
1384
1385 lastOrdinal += 1;
1386 }
1387
1388 return retv;
1389}
1390
1391
1393{
1394 int retv = MANDATORY_FIELDS;
1395
1396 while( GetFieldById( retv ) )
1397 retv += 1;
1398
1399 return retv;
1400}
1401
1402
1403void LIB_SYMBOL::Move( const VECTOR2I& aOffset )
1404{
1405 for( SCH_ITEM& item : m_drawings )
1406 item.Move( aOffset );
1407}
1408
1409
1411{
1412 for( const SCH_ITEM& item : m_drawings )
1413 {
1414 if( item.m_bodyStyle > BODY_STYLE::BASE )
1415 return true;
1416 }
1417
1418 if( LIB_SYMBOL_SPTR parent = m_parent.lock() )
1419 {
1420 for( const SCH_ITEM& item : parent->GetDrawItems() )
1421 {
1422 if( item.m_bodyStyle > BODY_STYLE::BASE )
1423 return true;
1424 }
1425 }
1426
1427 return false;
1428}
1429
1430
1432{
1433 int maxPinNumber = 0;
1434 LIB_SYMBOL_SPTR parent = m_parent.lock();
1435 const LIB_ITEMS_CONTAINER& drawItems = parent ? parent->m_drawings : m_drawings;
1436
1437 for( const SCH_ITEM& item : drawItems[SCH_PIN_T] )
1438 {
1439 const SCH_PIN* pin = static_cast<const SCH_PIN*>( &item );
1440 long currentPinNumber = 0;
1441
1442 if( pin->GetNumber().ToLong( &currentPinNumber ) )
1443 maxPinNumber = std::max( maxPinNumber, (int) currentPinNumber );
1444 }
1445
1446 return maxPinNumber;
1447}
1448
1449
1451{
1453
1454 for( SCH_ITEM& item : m_drawings )
1455 item.ClearTempFlags();
1456}
1457
1458
1460{
1462
1463 for( SCH_ITEM& item : m_drawings )
1464 item.ClearEditFlags();
1465}
1466
1467
1468SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType,
1469 const VECTOR2I& aPoint )
1470{
1471 for( SCH_ITEM& item : m_drawings )
1472 {
1473 if( ( aUnit && item.m_unit && aUnit != item.m_unit )
1474 || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle )
1475 || ( item.Type() != aType && aType != TYPE_NOT_INIT ) )
1476 {
1477 continue;
1478 }
1479
1480 if( item.HitTest( aPoint ) )
1481 return &item;
1482 }
1483
1484 return nullptr;
1485}
1486
1487
1488SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType,
1489 const VECTOR2I& aPoint, const TRANSFORM& aTransform )
1490{
1491 /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1492 * VECTOR2I& pt ) to search items.
1493 * because this function uses DefaultTransform as orient/mirror matrix
1494 * we temporary copy aTransform in DefaultTransform
1495 */
1496 TRANSFORM transform = DefaultTransform;
1497 DefaultTransform = aTransform;
1498
1499 SCH_ITEM* item = LocateDrawItem( aUnit, aBodyStyle, aType, aPoint );
1500
1501 // Restore matrix
1502 DefaultTransform = transform;
1503
1504 return item;
1505}
1506
1507
1508INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData,
1509 const std::vector<KICAD_T>& aScanTypes )
1510{
1511 // The part itself is never inspected, only its children
1512 for( SCH_ITEM& item : m_drawings )
1513 {
1514 if( item.IsType( aScanTypes ) )
1515 {
1516 if( aInspector( &item, aTestData ) == INSPECT_RESULT::QUIT )
1517 return INSPECT_RESULT::QUIT;
1518 }
1519 }
1520
1521 return INSPECT_RESULT::CONTINUE;
1522}
1523
1524
1525void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
1526{
1527 if( m_unitCount == aCount )
1528 return;
1529
1530 if( aCount < m_unitCount )
1531 {
1533
1534 while( i != m_drawings.end() )
1535 {
1536 if( i->m_unit > aCount )
1537 i = m_drawings.erase( i );
1538 else
1539 ++i;
1540 }
1541 }
1542 else if( aDuplicateDrawItems )
1543 {
1544 int prevCount = m_unitCount;
1545
1546 // Temporary storage for new items, as adding new items directly to
1547 // m_drawings may cause the buffer reallocation which invalidates the
1548 // iterators
1549 std::vector<SCH_ITEM*> tmp;
1550
1551 for( SCH_ITEM& item : m_drawings )
1552 {
1553 if( item.m_unit != 1 )
1554 continue;
1555
1556 for( int j = prevCount + 1; j <= aCount; j++ )
1557 {
1558 SCH_ITEM* newItem = item.Duplicate();
1559 newItem->m_unit = j;
1560 tmp.push_back( newItem );
1561 }
1562 }
1563
1564 for( SCH_ITEM* item : tmp )
1565 m_drawings.push_back( item );
1566 }
1567
1568 m_drawings.sort();
1569 m_unitCount = aCount;
1570}
1571
1572
1574{
1575 if( LIB_SYMBOL_SPTR parent = m_parent.lock() )
1576 return parent->GetUnitCount();
1577
1578 return m_unitCount;
1579}
1580
1581
1582void LIB_SYMBOL::SetHasAlternateBodyStyle( bool aHasAlternate, bool aDuplicatePins )
1583{
1584 if( aHasAlternate == HasAlternateBodyStyle() )
1585 return;
1586
1587 // Duplicate items to create the converted shape
1588 if( aHasAlternate )
1589 {
1590 if( aDuplicatePins )
1591 {
1592 std::vector<SCH_ITEM*> tmp; // Temporarily store the duplicated pins here.
1593
1594 for( SCH_ITEM& item : m_drawings[ SCH_PIN_T ] )
1595 {
1596 if( item.m_bodyStyle == 1 )
1597 {
1598 SCH_ITEM* newItem = item.Duplicate();
1599 newItem->m_bodyStyle = 2;
1600 tmp.push_back( newItem );
1601 }
1602 }
1603
1604 // Transfer the new pins to the LIB_SYMBOL.
1605 for( SCH_ITEM* item : tmp )
1606 m_drawings.push_back( item );
1607 }
1608 }
1609 else
1610 {
1611 // Delete converted shape items because the converted shape does not exist
1613
1614 while( i != m_drawings.end() )
1615 {
1616 if( i->m_bodyStyle > 1 )
1617 i = m_drawings.erase( i );
1618 else
1619 ++i;
1620 }
1621 }
1622
1623 m_drawings.sort();
1624}
1625
1626
1627std::vector<SCH_ITEM*> LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle )
1628{
1629 std::vector<SCH_ITEM*> unitItems;
1630
1631 for( SCH_ITEM& item : m_drawings )
1632 {
1633 if( item.Type() == SCH_FIELD_T )
1634 continue;
1635
1636 if( ( aBodyStyle == -1 && item.GetUnit() == aUnit )
1637 || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle )
1638 || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) )
1639 {
1640 unitItems.push_back( &item );
1641 }
1642 }
1643
1644 return unitItems;
1645}
1646
1647
1648std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
1649{
1650 std::vector<LIB_SYMBOL_UNIT> units;
1651
1652 for( SCH_ITEM& item : m_drawings )
1653 {
1654 if( item.Type() == SCH_FIELD_T )
1655 continue;
1656
1657 int unit = item.GetUnit();
1658 int bodyStyle = item.GetBodyStyle();
1659
1660 auto it = std::find_if( units.begin(), units.end(),
1661 [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a )
1662 {
1663 return a.m_unit == unit && a.m_bodyStyle == bodyStyle;
1664 } );
1665
1666 if( it == units.end() )
1667 {
1668 LIB_SYMBOL_UNIT newUnit;
1669 newUnit.m_unit = item.GetUnit();
1670 newUnit.m_bodyStyle = item.GetBodyStyle();
1671 newUnit.m_items.push_back( &item );
1672 units.emplace_back( newUnit );
1673 }
1674 else
1675 {
1676 it->m_items.push_back( &item );
1677 }
1678 }
1679
1680 return units;
1681}
1682
1683
1684bool LIB_SYMBOL::operator==( const LIB_SYMBOL& aOther ) const
1685{
1686 if( m_libId != aOther.m_libId )
1687 return false;
1688
1690 return false;
1691
1692 if( m_excludedFromBOM != aOther.m_excludedFromBOM )
1693 return false;
1694
1695 if( m_excludedFromSim != aOther.m_excludedFromSim )
1696 return false;
1697
1698 if( m_flags != aOther.m_flags )
1699 return false;
1700
1701 if( m_unitCount != aOther.m_unitCount )
1702 return false;
1703
1704 if( m_pinNameOffset != aOther.m_pinNameOffset )
1705 return false;
1706
1707 if( m_showPinNames != aOther.m_showPinNames )
1708 return false;
1709
1710 if( m_showPinNumbers != aOther.m_showPinNumbers )
1711 return false;
1712
1713 if( m_drawings.size() != aOther.m_drawings.size() )
1714 return false;
1715
1716 for( auto it1 = m_drawings.begin(), it2 = aOther.m_drawings.begin();
1717 it1 != m_drawings.end(); ++it1, ++it2 )
1718 {
1719 if( !( *it1 == *it2 ) )
1720 return false;
1721 }
1722
1723 const std::vector<SCH_PIN*> thisPinList = GetAllLibPins();
1724 const std::vector<SCH_PIN*> otherPinList = aOther.GetAllLibPins();
1725
1726 if( thisPinList.size() != otherPinList.size() )
1727 return false;
1728
1729 for( auto it1 = thisPinList.begin(), it2 = otherPinList.begin();
1730 it1 != thisPinList.end(); ++it1, ++it2 )
1731 {
1732 if( !( **it1 == **it2 ) )
1733 return false;
1734 }
1735 for( size_t ii = 0; ii < thisPinList.size(); ++ii )
1736 {
1737 if( !( *thisPinList[ii] == *otherPinList[ii] ) )
1738 return false;
1739 }
1740
1741 return true;
1742}
1743
1744
1745double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
1746{
1747 wxCHECK( aOther.Type() == LIB_SYMBOL_T, 0.0 );
1748
1749 const LIB_SYMBOL& other = static_cast<const LIB_SYMBOL&>( aOther );
1750 double similarity = 0.0;
1751 int totalItems = 0;
1752
1753 if( m_Uuid == aOther.m_Uuid )
1754 return 1.0;
1755
1756 for( const SCH_ITEM& item : m_drawings )
1757 {
1758 totalItems += 1;
1759 double max_similarity = 0.0;
1760
1761 for( const SCH_ITEM& otherItem : other.m_drawings )
1762 {
1763 double temp_similarity = item.Similarity( otherItem );
1764 max_similarity = std::max( max_similarity, temp_similarity );
1765
1766 if( max_similarity == 1.0 )
1767 break;
1768 }
1769
1770 similarity += max_similarity;
1771 }
1772
1773 for( const SCH_PIN* pin : GetAllLibPins() )
1774 {
1775 totalItems += 1;
1776 double max_similarity = 0.0;
1777
1778 for( const SCH_PIN* otherPin : other.GetAllLibPins() )
1779 {
1780 double temp_similarity = pin->Similarity( *otherPin );
1781 max_similarity = std::max( max_similarity, temp_similarity );
1782
1783 if( max_similarity == 1.0 )
1784 break;
1785 }
1786
1787 similarity += max_similarity;
1788 }
1789
1790 if( totalItems == 0 )
1791 similarity = 0.0;
1792 else
1793 similarity /= totalItems;
1794
1796 similarity *= 0.9;
1797
1799 similarity *= 0.9;
1800
1802 similarity *= 0.9;
1803
1804 if( m_flags != other.m_flags )
1805 similarity *= 0.9;
1806
1807 if( m_unitCount != other.m_unitCount )
1808 similarity *= 0.5;
1809
1810 if( m_pinNameOffset != other.m_pinNameOffset )
1811 similarity *= 0.9;
1812
1813 if( m_showPinNames != other.m_showPinNames )
1814 similarity *= 0.9;
1815
1816 if( m_showPinNumbers != other.m_showPinNumbers )
1817 similarity *= 0.9;
1818
1819 return similarity;
1820}
int color
Definition: DXF_plotter.cpp:58
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:623
virtual void ClearEditFlags()
Definition: eda_item.h:140
const KIID m_Uuid
Definition: eda_item.h:485
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
void ClearSelected()
Definition: eda_item.h:121
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:490
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:103
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:82
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:129
virtual void ClearTempFlags()
Definition: eda_item.h:152
FILL_T GetFillMode() const
Definition: eda_shape.h:102
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
virtual bool IsVisible() const
Definition: eda_text.h:151
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:245
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition: lib_id.cpp:110
int compare(const LIB_ID &aLibId) const
Compare the contents of LIB_ID objects by performing a std::string comparison of the library nickname...
Definition: lib_id.cpp:160
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Define a library symbol object.
Definition: lib_symbol.h:77
LIB_ITEMS_CONTAINER m_drawings
Definition: lib_symbol.h:638
wxString GetDescription() const override
Definition: lib_symbol.h:157
wxString GetKeyWords() const override
Definition: lib_symbol.h:170
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction) override
LIBRENTRYOPTIONS m_options
Special symbol features such as POWER or NORMAL.)
Definition: lib_symbol.h:636
void Print(const SCH_RENDER_SETTINGS *aSettings, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aForceNoFill, bool aDimmed) override
Print an item.
Definition: lib_symbol.cpp:740
bool PinsConflictWith(const LIB_SYMBOL &aOtherSymbol, bool aTestNums, bool aTestNames, bool aTestType, bool aTestOrientation, bool aTestLength) const
Return true if this symbol's pins do not match another symbol's pins.
bool IsPower() const override
Definition: lib_symbol.cpp:663
wxString GetPrefix()
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
std::vector< SCH_PIN * > GetPins(int aUnit=0, int aBodyStyle=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:982
const BOX2I GetUnitBoundingBox(int aUnit, int aBodyStyle, bool aIgnoreHiddenFields=true) const
Get the bounding box for the symbol.
int GetNextAvailableFieldId() const
void GetFields(std::vector< SCH_FIELD * > &aList)
Return a list of fields within this symbol.
bool operator==(const LIB_SYMBOL *aSymbol) const
Definition: lib_symbol.h:570
std::vector< struct LIB_SYMBOL_UNIT > GetUnitDrawItems()
Return a list of SCH_ITEM objects separated by unit and convert number.
std::map< int, wxString > m_unitDisplayNames
Definition: lib_symbol.h:646
void ClearTempFlags() override
Clears the status flag all draw objects in this symbol.
SYMBOL_LIB * m_library
Definition: lib_symbol.h:640
wxString GetUnitDisplayName(int aUnit) override
Return the user-defined display name for aUnit for symbols with units.
Definition: lib_symbol.cpp:535
const wxString GetLibraryName() const
Definition: lib_symbol.cpp:654
void SetFields(const std::vector< SCH_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
SCH_FIELD & GetValueField() const
Return reference to the value field.
std::vector< SEARCH_TERM > GetSearchTerms() override
Definition: lib_symbol.cpp:39
bool IsAlias() const
Definition: lib_symbol.h:194
int GetMaxPinNumber() const
LIB_SYMBOL_SPTR m_me
Definition: lib_symbol.h:626
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
Definition: lib_symbol.cpp:821
int Compare(const LIB_SYMBOL &aRhs, int aCompareFlags=0, REPORTER *aReporter=nullptr) const
Comparison test that can be used for operators.
Definition: lib_symbol.cpp:240
void FixupDrawItems()
This function finds the filled draw items that are covering up smaller draw items and replaces their ...
Definition: lib_symbol.cpp:902
static wxString LetterSubReference(int aUnit, int aFirstId)
Definition: lib_symbol.cpp:721
SCH_PIN * GetPin(const wxString &aNumber, int aUnit=0, int aBodyStyle=0) const
Return pin object with the requested pin aNumber.
bool IsNormal() const override
Definition: lib_symbol.cpp:693
wxString m_name
Definition: lib_symbol.h:641
std::vector< SCH_PIN * > GetAllLibPins() const
Return a list of pin pointers for all units / converts.
void SetPower()
Definition: lib_symbol.cpp:679
bool HasAlternateBodyStyle() const override
Test if symbol has more than one body conversion type (DeMorgan).
SCH_FIELD * GetFieldById(int aId) const
Return pointer to the requested field.
wxString m_keyWords
Search keywords.
Definition: lib_symbol.h:642
SCH_ITEM * LocateDrawItem(int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I &aPoint)
Locate a draw object.
double Similarity(const SCH_ITEM &aSymbol) const override
Return a measure of similarity between this symbol and aSymbol.
void PlotFields(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed)
Plot symbol fields.
Definition: lib_symbol.cpp:863
SCH_FIELD & GetDatasheetField() const
Return reference to the datasheet field.
SCH_FIELD & GetFootprintField() const
Return reference to the footprint field.
void SetParent(LIB_SYMBOL *aParent=nullptr)
Definition: lib_symbol.cpp:570
wxString GetName() const override
Definition: lib_symbol.h:136
SCH_FIELD & GetReferenceField() const
Return reference to the reference designator field.
void PrintBackground(const SCH_RENDER_SETTINGS *aSettings, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Print just the background fills.
Definition: lib_symbol.cpp:787
void RemoveDrawItem(SCH_ITEM *aItem)
Remove draw aItem from list.
Definition: lib_symbol.cpp:944
void GetChooserFields(std::map< wxString, wxString > &aColumnMap) override
Retrieves a key/value map of the fields on this item that should be exposed to the library browser/ch...
Definition: lib_symbol.cpp:70
timestamp_t m_lastModDate
Definition: lib_symbol.h:630
LIB_ID m_libId
Definition: lib_symbol.h:628
void SetLib(SYMBOL_LIB *aLibrary)
Definition: lib_symbol.h:199
SCH_FIELD & GetDescriptionField() const
Return reference to the description field.
const LIB_SYMBOL & operator=(const LIB_SYMBOL &aSymbol)
Definition: lib_symbol.cpp:178
bool m_unitsLocked
True if symbol has multiple units and changing one unit does not automatically change another unit.
Definition: lib_symbol.h:633
wxArrayString m_fpFilters
List of suitable footprint names for the symbol (wild card names accepted).
Definition: lib_symbol.h:643
void Move(const VECTOR2I &aOffset) override
Move the symbol aOffset.
bool HasUnitDisplayName(int aUnit) override
Return true if the given unit aUnit has a display name defined.
Definition: lib_symbol.cpp:529
const BOX2I GetBodyBoundingBox(int aUnit, int aBodyStyle, bool aIncludePins, bool aIncludePrivateItems) const
Get the symbol bounding box excluding fields.
LIB_SYMBOL_SPTR SharedPtr() const
Definition: lib_symbol.h:88
SCH_FIELD * FindField(const wxString &aFieldName, bool aCaseInsensitive=false)
Find a field within this symbol matching aFieldName and returns it or NULL if not found.
int UpdateFieldOrdinals()
Order optional field indices.
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
wxString GetUnitReference(int aUnit) override
Return an identifier for aUnit for symbols with units.
Definition: lib_symbol.cpp:523
int m_unitCount
Number of units (parts) per package.
Definition: lib_symbol.h:632
void SetHasAlternateBodyStyle(bool aHasAlternate, bool aDuplicatePins=true)
Set or clear the alternate body style (DeMorgan) for the symbol.
unsigned GetInheritanceDepth() const
Get the number of parents for this symbol.
Definition: lib_symbol.cpp:221
int GetUnitCount() const override
LIB_SYMBOL_REF m_parent
Use for inherited symbols.
Definition: lib_symbol.h:627
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:579
int GetPinCount() override
void AddField(SCH_FIELD *aField)
Add a field.
void ClearEditFlags() override
void deleteAllFields()
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:105
LIB_SYMBOL_SPTR GetRootSymbol() const
Get the parent symbol that does not have another parent.
Definition: lib_symbol.cpp:511
void SetUnitDisplayName(int aUnit, const wxString &aName)
Set the user-defined display name for aUnit to aName for symbols with units.
Definition: lib_symbol.cpp:551
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:969
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:563
void SetNormal()
Definition: lib_symbol.cpp:707
void CopyUnitDisplayNames(std::map< int, wxString > &aTarget) const
Copy all unit display names into the given map aTarget.
Definition: lib_symbol.cpp:544
size_t size(int aType=UNDEFINED_TYPE) const
Definition: multivector.h:226
void sort()
Definition: multivector.h:248
void push_back(T *aItem)
Definition: multivector.h:175
ITERATOR_BASE< SCH_ITEM, MULTIVECTOR< SCH_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The const iterator.
Definition: multivector.h:165
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:195
void clear(int aType=UNDEFINED_TYPE)
Definition: multivector.h:213
ITERATOR erase(const ITERATOR &aIterator)
Definition: multivector.h:180
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:189
Base plotter engine class.
Definition: plotter.h:104
bool GetColorMode() const
Definition: plotter.h:132
virtual void SetColor(const COLOR4D &color)=0
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
int compare(const SCH_ITEM &aOther, int aCompareFlags=0) const override
Provide the draw object specific comparison called by the == and < operators.
Definition: sch_field.cpp:1541
bool IsMandatory() const
Definition: sch_field.cpp:1429
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: sch_field.cpp:305
void Print(const SCH_RENDER_SETTINGS *aSettings, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aForceNoFill, bool aDimmed) override
Print an item.
Definition: sch_field.cpp:397
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:1174
int GetId() const
Definition: sch_field.h:133
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1149
void SetId(int aId)
Definition: sch_field.cpp:154
bool ShowInChooser() const
Definition: sch_field.h:226
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1138
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:174
int m_unit
Definition: sch_item.h:732
int m_bodyStyle
Definition: sch_item.h:733
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition: sch_item.h:678
int GetBodyStyle() const
Definition: sch_item.h:240
friend class LIB_SYMBOL
Definition: sch_item.h:751
int GetUnit() const
Definition: sch_item.h:237
virtual void SetExcludedFromSim(bool aExclude)
Definition: sch_item.h:245
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:120
const wxString & GetNumber() const
Definition: sch_pin.h:111
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
void Print(const SCH_RENDER_SETTINGS *aSettings, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aForceNoFill, bool aDimmed) override
Print an item.
Definition: sch_shape.cpp:382
Object used to load, save, search, and otherwise manipulate symbol library files.
const wxString GetName() const
Return the file name without path or extension.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition: symbol.h:34
bool m_showPinNumbers
Definition: symbol.h:162
bool m_excludedFromSim
Definition: symbol.h:164
bool m_showPinNames
Definition: symbol.h:161
bool m_excludedFromBOM
Definition: symbol.h:165
bool m_excludedFromBoard
Definition: symbol.h:166
SYMBOL & operator=(const SYMBOL &aItem)
Definition: symbol.h:62
int m_pinNameOffset
The offset in mils to draw the pin name.
Definition: symbol.h:159
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:46
#define DEFAULT_PIN_NAME_OFFSET
The intersheets references prefix string.
#define _(s)
INSPECT_RESULT
Definition: eda_item.h:43
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:81
#define IS_NEW
New item, just created.
#define STRUCT_DELETED
flag indication structures to be erased
TRANSFORM DefaultTransform
Definition: transform.cpp:32
bool GetGRForceBlackPenState(void)
Definition: gr_basic.cpp:165
@ LAYER_DEVICE
Definition: layer_ids.h:370
@ LAYER_FIELDS
Definition: layer_ids.h:366
#define REPORT(msg)
Definition: lib_symbol.cpp:237
bool operator<(const LIB_SYMBOL &aItem1, const LIB_SYMBOL &aItem2)
Definition: lib_symbol.cpp:82
#define ITEM_DESC(item)
Definition: lib_symbol.cpp:238
@ ENTRY_NORMAL
Definition: lib_symbol.h:54
@ ENTRY_POWER
Definition: lib_symbol.h:55
std::shared_ptr< LIB_SYMBOL > LIB_SYMBOL_SPTR
shared pointer to LIB_SYMBOL
Definition: lib_symbol.h:45
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
Definition: lib_symbol.h:48
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
int m_bodyStyle
The alternate body style of the unit.
Definition: lib_symbol.h:65
std::vector< SCH_ITEM * > m_items
The items unique to this unit and alternate body style.
Definition: lib_symbol.h:66
int m_unit
The unit number.
Definition: lib_symbol.h:64
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared
Definition: lib_symbol.cpp:90
void operator()(void const *) const
Definition: lib_symbol.cpp:91
Definition for symbol library class.
@ DATASHEET_FIELD
name of datasheet
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ LIB_SYMBOL_T
Definition: typeinfo.h:148
@ TYPE_NOT_INIT
Definition: typeinfo.h:81
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_PIN_T
Definition: typeinfo.h:153