KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_sheet.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2023 CERN
6 * Copyright The 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <cstdlib>
23
24#include <bitmaps.h>
25#include <core/mirror.h>
26#include <core/kicad_algo.h>
27#include <sch_draw_panel.h>
28#include <trigo.h>
29#include <sch_edit_frame.h>
30#include <plotters/plotter.h>
31#include <sch_plotter.h>
32#include <string_utils.h>
33#include <widgets/msgpanel.h>
34#include <math/util.h> // for KiROUND
36#include <api/api_enums.h>
37#include <api/api_utils.h>
38#include <api/schematic/schematic_types.pb.h>
39#include <sch_sheet.h>
40#include <sch_sheet_path.h>
41#include <sch_sheet_pin.h>
42#include <sch_no_connect.h>
43#include <sch_symbol.h>
44#include <sch_painter.h>
45#include <schematic.h>
47#include <trace_helpers.h>
48#include <validators.h>
50#include <properties/property.h>
52#include <pgm_base.h>
53#include <wx/log.h>
54
55
57{
58public:
59 SCH_SHEET_FIELD_PROPERTY( const wxString& aName ) :
60 PROPERTY_BASE( aName ),
61 m_name( aName )
62 {
63 SetGroup( _HKI( "Fields" ) );
64 }
65
66 size_t OwnerHash() const override { return TYPE_HASH( SCH_SHEET ); }
67 size_t BaseHash() const override { return TYPE_HASH( SCH_SHEET ); }
68 size_t TypeHash() const override { return TYPE_HASH( wxString ); }
69
70 void setter( void* obj, wxAny& v ) override
71 {
72 wxString value;
73
74 if( !v.GetAs( &value ) )
75 return;
76
77 SCH_SHEET* sheet = reinterpret_cast<SCH_SHEET*>( obj );
78 SCH_FIELD* field = sheet->GetField( m_name );
79
80 wxString variantName;
81 const SCH_SHEET_PATH* sheetPath = nullptr;
82
83 if( sheet->Schematic() )
84 {
85 variantName = sheet->Schematic()->GetCurrentVariant();
86 sheetPath = &sheet->Schematic()->CurrentSheet();
87 }
88
89 if( !field )
90 {
91 SCH_FIELD newField( sheet, FIELD_T::USER, m_name );
92 newField.SetText( value, sheetPath, variantName );
93 sheet->AddField( newField );
94 }
95 else
96 {
97 field->SetText( value, sheetPath, variantName );
98 }
99 }
100
101 wxAny getter( const void* obj ) const override
102 {
103 const SCH_SHEET* sheet = reinterpret_cast<const SCH_SHEET*>( obj );
104 const SCH_FIELD* field = sheet->GetField( m_name );
105
106 if( !field )
107 return wxAny();
108
109 wxString variantName;
110 const SCH_SHEET_PATH* sheetPath = nullptr;
111
112 if( sheet->Schematic() )
113 {
114 variantName = sheet->Schematic()->GetCurrentVariant();
115 sheetPath = &sheet->Schematic()->CurrentSheet();
116 }
117
118 wxString text;
119
120 if( !variantName.IsEmpty() && sheetPath )
121 text = field->GetText( sheetPath, variantName );
122 else
123 text = field->GetText();
124
125 return wxAny( text );
126 }
127
128private:
129 wxString m_name;
130};
131
132
133SCH_SHEET::SCH_SHEET( EDA_ITEM* aParent, const VECTOR2I& aPos, VECTOR2I aSize ) :
134 SCH_ITEM( aParent, SCH_SHEET_T ),
135 m_excludedFromSim( false ),
136 m_excludedFromBOM( false ),
137 m_excludedFromBoard( false ),
138 m_DNP( false )
139{
141 m_pos = aPos;
142 m_size = aSize;
143 m_screen = nullptr;
144
145 m_borderWidth = 0;
149
150 m_fields.emplace_back( this, FIELD_T::SHEET_NAME,
152
153 m_fields.emplace_back( this, FIELD_T::SHEET_FILENAME,
155
157}
158
159
160void SCH_SHEET::Serialize( google::protobuf::Any& aContainer ) const
161{
162 using namespace kiapi::common;
163 using namespace kiapi::common::types;
164 using namespace kiapi::schematic::types;
165
166 SheetSymbol sheet;
167
168 sheet.mutable_id()->set_value( m_Uuid.AsStdString() );
169 PackVector2( *sheet.mutable_position(), GetPosition(), schIUScale );
170 PackVector2( *sheet.mutable_size(), GetSize(), schIUScale );
171 sheet.set_locked( IsLocked() ? LockedState::LS_LOCKED : LockedState::LS_UNLOCKED );
172 sheet.set_fields_autoplaced( GetFieldsAutoplaced() != AUTOPLACE_NONE );
173 sheet.set_exclude_from_sim( GetExcludedFromSim() );
174 sheet.set_exclude_from_bom( GetExcludedFromBOM() );
175 sheet.set_exclude_from_board( GetExcludedFromBoard() );
176 sheet.set_dnp( GetDNP() );
177
178 StrokeAttributes* borderStroke = sheet.mutable_border_stroke();
179 PackDistance( *borderStroke->mutable_width(), GetBorderWidth(), schIUScale );
181
183 PackColor( *borderStroke->mutable_color(), GetBorderColor() );
184
185 GraphicFillAttributes* fill = sheet.mutable_fill();
186 fill->set_fill_type( GetBackgroundColor() == COLOR4D::UNSPECIFIED ? GraphicFillType::GFT_UNFILLED
187 : GraphicFillType::GFT_FILLED_WITH_COLOR );
188
190 PackColor( *fill->mutable_color(), GetBackgroundColor() );
191
192 GetField( FIELD_T::SHEET_NAME )->Serialize( *sheet.mutable_name_field(), schIUScale );
193 GetField( FIELD_T::SHEET_FILENAME )->Serialize( *sheet.mutable_filename_field(), schIUScale );
194
195 for( const SCH_FIELD& field : GetFields() )
196 {
197 if( field.IsMandatory() )
198 continue;
199
200 field.Serialize( *sheet.add_user_fields(), schIUScale );
201 }
202
203 for( const SCH_SHEET_PIN* pin : GetPins() )
204 pin->Serialize( *sheet.add_pins(), schIUScale );
205
206 kiapi::common::PackCustomProperties( sheet.mutable_custom_properties(), *this );
207 aContainer.PackFrom( sheet );
208}
209
210
211bool SCH_SHEET::Deserialize( const google::protobuf::Any& aContainer )
212{
213 using namespace kiapi::common;
214 using namespace kiapi::common::types;
215 using namespace kiapi::schematic::types;
216
217 SheetSymbol sheet;
218
219 if( !aContainer.UnpackTo( &sheet ) )
220 return false;
221
222 const_cast<::KIID&>( m_Uuid ) = ::KIID( sheet.id().value() );
223 SetPosition( UnpackVector2( sheet.position(), schIUScale ) );
224 SetSize( UnpackVector2( sheet.size(), schIUScale ) );
225 SetLocked( sheet.locked() == LockedState::LS_LOCKED );
226 SetFieldsAutoplaced( sheet.fields_autoplaced() ? AUTOPLACE_AUTO : AUTOPLACE_NONE );
227 SetExcludedFromSim( sheet.exclude_from_sim() );
228 SetExcludedFromBOM( sheet.exclude_from_bom() );
229 SetExcludedFromBoard( sheet.exclude_from_board() );
230 SetDNP( sheet.dnp() );
231 kiapi::common::UnpackCustomProperties( sheet.custom_properties(), *this );
232
233 SetBorderWidth( UnpackDistance( sheet.border_stroke().width(), schIUScale ) );
234 SetBorderColor( sheet.border_stroke().has_color() ? UnpackColor( sheet.border_stroke().color() )
236
237 if( sheet.fill().fill_type() == GraphicFillType::GFT_UNFILLED || !sheet.fill().has_color() )
239 else
240 SetBackgroundColor( UnpackColor( sheet.fill().color() ) );
241
242 for( SCH_SHEET_PIN* pin : m_pins )
243 delete pin;
244
245 m_pins.clear();
246
247 m_fields.clear();
248 m_fields.emplace_back( this, FIELD_T::SHEET_NAME,
250 m_fields.emplace_back( this, FIELD_T::SHEET_FILENAME,
252
253 GetField( FIELD_T::SHEET_NAME )->Deserialize( sheet.name_field(), schIUScale );
254 GetField( FIELD_T::SHEET_FILENAME )->Deserialize( sheet.filename_field(), schIUScale );
255
256 for( const auto& field : sheet.user_fields() )
257 {
258 m_fields.emplace_back( this, FIELD_T::SHEET_USER );
259 m_fields.back().Deserialize( field, schIUScale );
260 }
261
262 for( const auto& pinProto : sheet.pins() )
263 {
264 auto pin = std::make_unique<SCH_SHEET_PIN>( this );
265
266 if( !pin->Deserialize( pinProto, schIUScale ) )
267 return false;
268
269 AddPin( pin.release() );
270 }
271
272 SetScreen( nullptr );
273
274 return true;
275}
276
277
279 SCH_ITEM( aSheet )
280{
281 m_pos = aSheet.m_pos;
282 m_size = aSheet.m_size;
283 m_layer = aSheet.m_layer;
284 const_cast<KIID&>( m_Uuid ) = aSheet.m_Uuid;
285 m_fields = aSheet.m_fields;
287 m_screen = aSheet.m_screen;
288
292 m_DNP = aSheet.m_DNP;
293
297 m_instances = aSheet.m_instances;
298
299 for( SCH_SHEET_PIN* pin : aSheet.m_pins )
300 {
301 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
302 m_pins.back()->SetParent( this );
303 }
304
305 for( SCH_FIELD& field : m_fields )
306 field.SetParent( this );
307
308 if( m_screen )
309 m_screen->IncRefCount();
310}
311
312
314{
315 // also, look at the associated sheet & its reference count
316 // perhaps it should be deleted also.
317 if( m_screen )
318 {
319 m_screen->DecRefCount();
320
321 if( m_screen->GetRefCount() == 0 )
322 delete m_screen;
323 }
324
325 // We own our pins; delete them
326 for( SCH_SHEET_PIN* pin : m_pins )
327 delete pin;
328}
329
330
331std::vector<PROPERTY_BASE*> SCH_SHEET::GetDynamicProperties() const
332{
333 std::vector<PROPERTY_BASE*> props;
334
335 auto getOrCreate = [&]( const wxString& aName )
336 {
337 auto it = m_dynamicPropertyCache.find( aName );
338
339 if( it == m_dynamicPropertyCache.end() )
340 {
341 auto prop = std::make_unique<SCH_SHEET_FIELD_PROPERTY>( aName );
342 it = m_dynamicPropertyCache.emplace( aName, std::move( prop ) ).first;
343 }
344
345 return it->second.get();
346 };
347
348
349 for( const SCH_FIELD& field : GetFields() )
350 {
351 if( field.IsMandatory() )
352 {
353 if( field.IsPrivate() )
354 continue;
355
356 const wxString& name = field.GetUntranslatedName();
357
358 if( PROPERTY_MANAGER::Instance().GetProperty( TYPE_HASH( SCH_SHEET ), name ) )
359 continue;
360
361 props.push_back( getOrCreate( name ) );
362 }
363 }
364
365 std::vector<const SCH_FIELD*> userFields;
366
367 for( const SCH_FIELD& field : GetFields() )
368 {
369 if( field.IsMandatory() )
370 continue;
371
372 if( field.IsPrivate() )
373 continue;
374
375 userFields.push_back( &field );
376 }
377
378 std::ranges::sort( userFields,
379 []( const SCH_FIELD* a, const SCH_FIELD* b )
380 {
381 return a->GetUntranslatedName().CmpNoCase( b->GetUntranslatedName() ) < 0;
382 } );
383
384 for( const SCH_FIELD* field : userFields )
385 {
386 const wxString& name = field->GetUntranslatedName();
387 props.push_back( getOrCreate( name ) );
388 }
389
391 props.push_back( prop );
392
393 return props;
394}
395
396
398{
399 return new SCH_SHEET( *this );
400}
401
402
404{
405 if( aScreen == m_screen )
406 return;
407
408 if( m_screen != nullptr )
409 {
410 m_screen->DecRefCount();
411
412 if( m_screen->GetRefCount() == 0 )
413 {
414 delete m_screen;
415 m_screen = nullptr;
416 }
417 }
418
419 m_screen = aScreen;
420
421 if( m_screen )
422 m_screen->IncRefCount();
423}
424
425
427{
428 wxCHECK_RET( m_screen, wxS( "Cannot sync a sheet UUID without a screen" ) );
429
430 const_cast<KIID&>( m_Uuid ) = m_screen->GetUuid();
431}
432
433
435{
436 if( m_screen == nullptr )
437 return 0;
438
439 return m_screen->GetRefCount();
440}
441
442
444{
445 wxCHECK_MSG( Schematic(), false, "Can't call IsVirtualRootSheet without setting a schematic" );
446
447 return m_Uuid == niluuid;
448}
449
450
452{
453 wxCHECK_MSG( Schematic(), false, "Can't call IsTopLevelSheet without setting a schematic" );
454
455 return Schematic()->IsTopLevelSheet( this );
456}
457
458
459void SCH_SHEET::GetContextualTextVars( wxArrayString* aVars ) const
460{
461 auto add =
462 [&]( const wxString& aVar )
463 {
464 if( !alg::contains( *aVars, aVar ) )
465 aVars->push_back( aVar );
466 };
467
468 for( const SCH_FIELD& field : m_fields )
469 {
470 if( field.IsMandatory() )
471 add( field.GetUntranslatedName().Upper() );
472 else
473 add( field.GetName() );
474 }
475
476 SCH_SHEET_PATH sheetPath = findSelf();
477
478 if( sheetPath.size() >= 2 )
479 {
480 sheetPath.pop_back();
481 sheetPath.Last()->GetContextualTextVars( aVars );
482 }
483 else if( Schematic() )
484 {
486 }
487
488 add( wxT( "#" ) );
489 add( wxT( "##" ) );
490 add( wxT( "SHEETPATH" ) );
491 add( wxT( "EXCLUDE_FROM_BOM" ) );
492 add( wxT( "EXCLUDE_FROM_BOARD" ) );
493 add( wxT( "EXCLUDE_FROM_SIM" ) );
494 add( wxT( "DNP" ) );
495 add( wxT( "ERC_ERROR <message_text>" ) );
496 add( wxT( "ERC_WARNING <message_text>" ) );
497
498 m_screen->GetTitleBlock().GetContextualTextVars( aVars );
499}
500
501
502bool SCH_SHEET::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
503{
504 wxCHECK( aPath, false );
505
507
508 if( !schematic )
509 return false;
510
511 if( token->Contains( ':' ) )
512 {
513 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
514 return true;
515 }
516
517 for( const SCH_FIELD& field : m_fields )
518 {
519 wxString fieldName = field.IsMandatory() ? field.GetUntranslatedName().Upper()
520 : field.GetName();
521
522 if( token->IsSameAs( fieldName ) )
523 {
524 *token = field.GetShownText( aPath, INTERNAL, wxEmptyString, aDepth + 1 );
525 return true;
526 }
527 }
528
529 PROJECT* project = &schematic->Project();
530 wxString variant = schematic->GetCurrentVariant();
531
532 // We cannot resolve text variables initially on load as we need to first load the screen and
533 // then parse the hierarchy. So skip the resolution if the screen isn't set yet
534 if( m_screen && m_screen->GetTitleBlock().TextVarResolver( token, project, INTERNAL ) )
535 return true;
536
537 if( token->IsSameAs( wxT( "#" ) ) )
538 {
539 *token = wxString::Format( "%s", aPath->GetPageNumber() );
540 return true;
541 }
542 else if( token->IsSameAs( wxT( "##" ) ) )
543 {
544 *token = wxString::Format( wxT( "%d" ), (int) schematic->Hierarchy().size() );
545 return true;
546 }
547 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
548 {
549 *token = aPath->PathHumanReadable();
550 return true;
551 }
552 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
553 {
554 *token = wxEmptyString;
555
556 if( aPath->GetExcludedFromBOM( variant ) || this->ResolveExcludedFromBOM( aPath, variant ) )
557 *token = wxS( "Excluded from BOM" );
558
559 return true;
560 }
561 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
562 {
563 *token = wxEmptyString;
564
565 if( aPath->GetExcludedFromBoard( variant ) || this->ResolveExcludedFromBoard( aPath, variant ) )
566 *token = wxS( "Excluded from board" );
567
568 return true;
569 }
570 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
571 {
572 *token = wxEmptyString;
573
574 if( aPath->GetExcludedFromSim( variant ) || this->ResolveExcludedFromSim( aPath, variant ) )
575 *token = wxS( "Excluded from simulation" );
576
577 return true;
578 }
579 else if( token->IsSameAs( wxT( "DNP" ) ) )
580 {
581 *token = wxEmptyString;
582
583 if( aPath->GetDNP( variant ) || this->ResolveDNP( aPath, variant ) )
584 *token = wxS( "DNP" );
585
586 return true;
587 }
588
589 // See if parent can resolve it (these will recurse to ancestors)
590
591 if( aPath->size() >= 2 )
592 {
593 SCH_SHEET_PATH path = *aPath;
594 path.pop_back();
595
596 if( path.Last()->ResolveTextVar( &path, token, aDepth + 1 ) )
597 return true;
598 }
599 else
600 {
601 if( schematic->ResolveTextVar( aPath, token, aDepth + 1 ) )
602 return true;
603 }
604
605 return false;
606}
607
608
610{
611 wxCHECK_RET( aItem->Type() == SCH_SHEET_T,
612 wxString::Format( wxT( "SCH_SHEET object cannot swap data with %s object." ),
613 aItem->GetClass() ) );
614
615 SCH_SHEET* sheet = ( SCH_SHEET* ) aItem;
616
617 std::swap( m_pos, sheet->m_pos );
618 std::swap( m_size, sheet->m_size );
619 m_fields.swap( sheet->m_fields );
620 m_pins.swap( sheet->m_pins );
621
622 // Update parent pointers after swapping.
623 for( SCH_SHEET_PIN* sheetPin : m_pins )
624 sheetPin->SetParent( this );
625
626 for( SCH_SHEET_PIN* sheetPin : sheet->m_pins )
627 sheetPin->SetParent( sheet );
628
629 for( SCH_FIELD& field : m_fields )
630 field.SetParent( this );
631
632 for( SCH_FIELD& field : sheet->m_fields )
633 field.SetParent( sheet );
634
635 std::swap( m_excludedFromSim, sheet->m_excludedFromSim );
636 std::swap( m_excludedFromBOM, sheet->m_excludedFromBOM );
637 std::swap( m_excludedFromBoard, sheet->m_excludedFromBoard );
638 std::swap( m_DNP, sheet->m_DNP );
639
640 std::swap( m_borderWidth, sheet->m_borderWidth );
641 std::swap( m_borderColor, sheet->m_borderColor );
642 std::swap( m_backgroundColor, sheet->m_backgroundColor );
643 std::swap( m_instances, sheet->m_instances );
644}
645
646
648{
649 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
650 return field;
651
652 m_fields.emplace_back( this, aFieldType );
653 return &m_fields.back();
654}
655
656
657const SCH_FIELD* SCH_SHEET::GetField( FIELD_T aFieldType ) const
658{
659 return FindField( m_fields, aFieldType );
660}
661
662
663SCH_FIELD* SCH_SHEET::GetField( const wxString& aFieldName )
664{
665 return FindField( m_fields, aFieldName );
666}
667
668
669const SCH_FIELD* SCH_SHEET::GetField( const wxString& aFieldName ) const
670{
671 return FindField( m_fields, aFieldName );
672}
673
674
676{
677 return NextFieldOrdinal( m_fields );
678}
679
680
681void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
682{
683 m_fields = aFields;
684
685 // Make sure that we get the UNIX variant of the file path
687}
688
689
691{
692 m_fields.emplace_back( aField );
693 return &m_fields.back();
694}
695
696
697void SCH_SHEET::SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath,
698 const wxString& aVariantName )
699{
700 wxCHECK( !aFieldName.IsEmpty(), /* void */ );
701
702 SCH_FIELD* field = GetField( aFieldName );
703
704 wxCHECK( field, /* void */ );
705
706 switch( field->GetId() )
707 {
709 {
710 // File names are stored using unix separators.
711 wxString tmp = aFieldText;
712 tmp.Replace( wxT( "\\" ), wxT( "/" ) );
714 break;
715 }
716
718 field->SetText( aFieldText );
719 break;
720
721 default:
722 {
723 wxString defaultText = field->GetText( aPath );
724
725 if( aVariantName.IsEmpty() )
726 {
727 if( aFieldText != defaultText )
728 field->SetText( aFieldText );
729 }
730 else
731 {
732 SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
733
734 wxCHECK( instance, /* void */ );
735
736 if( instance->m_Variants.contains( aVariantName ) )
737 {
738 if( aFieldText != defaultText )
739 instance->m_Variants[aVariantName].m_Fields[aFieldName] = aFieldText;
740 else
741 instance->m_Variants[aVariantName].m_Fields.erase( aFieldName );
742 }
743 else if( aFieldText != defaultText )
744 {
745 SCH_SHEET_VARIANT newVariant( aVariantName );
746
747 newVariant.InitializeAttributes( *this );
748 newVariant.m_Fields[aFieldName] = aFieldText;
749 instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
750 }
751 }
752
753 break;
754 }
755 }
756}
757
758
759wxString SCH_SHEET::GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
760 const wxString& aVariantName ) const
761{
762 wxCHECK( !aFieldName.IsEmpty(), wxEmptyString );
763
764 const SCH_FIELD* field = GetField( aFieldName );
765
766 wxCHECK( field, wxEmptyString );
767
768 switch( field->GetId() )
769 {
772 return field->GetText();
773 break;
774
775 default:
776 if( aVariantName.IsEmpty() )
777 {
778 return field->GetText();
779 }
780 else
781 {
782 const SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
783
784 if( instance->m_Variants.contains( aVariantName )
785 && instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
786 return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
787 }
788
789 break;
790 }
791
792 return field->GetText();
793}
794
795
797{
798 wxASSERT( aSheetPin != nullptr );
799 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
800
801 aSheetPin->SetParent( this );
802 m_pins.push_back( aSheetPin );
803 renumberPins();
804}
805
806
807void SCH_SHEET::RemovePin( const SCH_SHEET_PIN* aSheetPin )
808{
809 wxASSERT( aSheetPin != nullptr );
810 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
811
812 for( auto i = m_pins.begin(); i < m_pins.end(); ++i )
813 {
814 if( *i == aSheetPin )
815 {
816 m_pins.erase( i );
817 renumberPins();
818 return;
819 }
820 }
821}
822
823
824bool SCH_SHEET::HasPin( const wxString& aName ) const
825{
826 for( SCH_SHEET_PIN* pin : m_pins )
827 {
828 if( pin->GetText().Cmp( aName ) == 0 )
829 return true;
830 }
831
832 return false;
833}
834
835
836bool SCH_SHEET::doIsConnected( const VECTOR2I& aPosition ) const
837{
838 for( SCH_SHEET_PIN* sheetPin : m_pins )
839 {
840 if( sheetPin->GetPosition() == aPosition )
841 return true;
842 }
843
844 return false;
845}
846
847
849{
850 int leftRight = 0;
851 int topBottom = 0;
852
853 for( SCH_SHEET_PIN* pin : m_pins )
854 {
855 switch( pin->GetSide() )
856 {
857 case SHEET_SIDE::LEFT: leftRight++; break;
858 case SHEET_SIDE::RIGHT: leftRight++; break;
859 case SHEET_SIDE::TOP: topBottom++; break;
860 case SHEET_SIDE::BOTTOM: topBottom++; break;
861 default: break;
862 }
863 }
864
865 return topBottom > 0 && leftRight == 0;
866}
867
868
870{
871 for( SCH_SHEET_PIN* pin : m_pins )
872 {
873 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
874 const SCH_HIERLABEL* HLabel = nullptr;
875
876 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
877 {
878 if( !pin->GetText().Cmp( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
879 {
880 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
881 break;
882 }
883 }
884
885 if( HLabel == nullptr ) // Corresponding hierarchical label not found.
886 return true;
887 }
888
889 return false;
890}
891
892
893int bumpToNextGrid( const int aVal, const int aDirection )
894{
895 constexpr int gridSize = schIUScale.MilsToIU( 50 );
896
897 int base = aVal / gridSize;
898 int excess = abs( aVal % gridSize );
899
900 if( aDirection > 0 )
901 {
902 return ( base + 1 ) * gridSize;
903 }
904 else if( excess > 0 )
905 {
906 return ( base ) * gridSize;
907 }
908 else
909 {
910 return ( base - 1 ) * gridSize;
911 }
912}
913
914
915int SCH_SHEET::GetMinWidth( bool aFromLeft ) const
916{
917 int pinsLeft = m_pos.x + m_size.x;
918 int pinsRight = m_pos.x;
919
920 for( size_t i = 0; i < m_pins.size(); i++ )
921 {
922 SHEET_SIDE edge = m_pins[i]->GetSide();
923
924 if( edge == SHEET_SIDE::TOP || edge == SHEET_SIDE::BOTTOM )
925 {
926 BOX2I pinRect = m_pins[i]->GetBoundingBox();
927
928 pinsLeft = std::min( pinsLeft, pinRect.GetLeft() );
929 pinsRight = std::max( pinsRight, pinRect.GetRight() );
930 }
931 }
932
933 pinsLeft = bumpToNextGrid( pinsLeft, -1 );
934 pinsRight = bumpToNextGrid( pinsRight, 1 );
935
936 int pinMinWidth;
937
938 if( pinsLeft >= pinsRight )
939 pinMinWidth = 0;
940 else if( aFromLeft )
941 pinMinWidth = pinsRight - m_pos.x;
942 else
943 pinMinWidth = m_pos.x + m_size.x - pinsLeft;
944
945 return std::max( pinMinWidth, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
946}
947
948
949int SCH_SHEET::GetMinHeight( bool aFromTop ) const
950{
951 int pinsTop = m_pos.y + m_size.y;
952 int pinsBottom = m_pos.y;
953
954 for( size_t i = 0; i < m_pins.size(); i++ )
955 {
956 SHEET_SIDE edge = m_pins[i]->GetSide();
957
958 if( edge == SHEET_SIDE::RIGHT || edge == SHEET_SIDE::LEFT )
959 {
960 BOX2I pinRect = m_pins[i]->GetBoundingBox();
961
962 pinsTop = std::min( pinsTop, pinRect.GetTop() );
963 pinsBottom = std::max( pinsBottom, pinRect.GetBottom() );
964 }
965 }
966
967 pinsTop = bumpToNextGrid( pinsTop, -1 );
968 pinsBottom = bumpToNextGrid( pinsBottom, 1 );
969
970 int pinMinHeight;
971
972 if( pinsTop >= pinsBottom )
973 pinMinHeight = 0;
974 else if( aFromTop )
975 pinMinHeight = pinsBottom - m_pos.y;
976 else
977 pinMinHeight = m_pos.y + m_size.y - pinsTop;
978
979 return std::max( pinMinHeight, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
980}
981
982
984{
985 std::vector<SCH_SHEET_PIN*> pins = m_pins;
986
987 m_pins.clear();
988
989 for( SCH_SHEET_PIN* pin : pins )
990 {
991 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
992 const SCH_HIERLABEL* HLabel = nullptr;
993
994 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
995 {
996 if( pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) == 0 )
997 {
998 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
999 break;
1000 }
1001 }
1002
1003 if( HLabel )
1004 m_pins.push_back( pin );
1005 }
1006}
1007
1008
1010{
1011 for( SCH_SHEET_PIN* pin : m_pins )
1012 {
1013 if( pin->HitTest( aPosition ) )
1014 return pin;
1015 }
1016
1017 return nullptr;
1018}
1019
1020
1022{
1023 if( GetBorderWidth() > 0 )
1024 return GetBorderWidth();
1025
1026 if( Schematic() )
1028
1029 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
1030}
1031
1032
1034{
1035 SCH_FIELD* sheetNameField = GetField( FIELD_T::SHEET_NAME );
1036 VECTOR2I textSize = sheetNameField->GetTextSize();
1037 int borderMargin = KiROUND( GetPenWidth() / 2.0 ) + 4;
1038 int margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.5 );
1039
1040 if( IsVerticalOrientation() )
1041 {
1042 sheetNameField->SetTextPos( m_pos + VECTOR2I( -margin, m_size.y ) );
1043 sheetNameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1044 sheetNameField->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
1045 sheetNameField->SetTextAngle( ANGLE_VERTICAL );
1046 }
1047 else
1048 {
1049 sheetNameField->SetTextPos( m_pos + VECTOR2I( 0, -margin ) );
1050 sheetNameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1051 sheetNameField->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
1052 sheetNameField->SetTextAngle( ANGLE_HORIZONTAL );
1053 }
1054
1055 SCH_FIELD* sheetFilenameField = GetField( FIELD_T::SHEET_FILENAME );
1056
1057 textSize = sheetFilenameField->GetTextSize();
1058 margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.4 );
1059
1060 if( IsVerticalOrientation() )
1061 {
1062 sheetFilenameField->SetTextPos( m_pos + VECTOR2I( m_size.x + margin, m_size.y ) );
1063 sheetFilenameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1064 sheetFilenameField->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
1065 sheetFilenameField->SetTextAngle( ANGLE_VERTICAL );
1066 }
1067 else
1068 {
1069 sheetFilenameField->SetTextPos( m_pos + VECTOR2I( 0, m_size.y + margin ) );
1070 sheetFilenameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1071 sheetFilenameField->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
1072 sheetFilenameField->SetTextAngle( ANGLE_HORIZONTAL );
1073 }
1074
1075 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
1076 m_fieldsAutoplaced = aAlgo;
1077}
1078
1079
1080std::vector<int> SCH_SHEET::ViewGetLayers() const
1081{
1082 // Sheet pins are drawn by their parent sheet, so the parent needs to draw to LAYER_DANGLING
1085}
1086
1087
1089{
1090 VECTOR2I end;
1091 BOX2I box( m_pos, m_size );
1092 int lineWidth = GetPenWidth();
1093 int textLength = 0;
1094
1095 // Calculate bounding box X size:
1096 end.x = std::max( m_size.x, textLength );
1097
1098 // Calculate bounding box pos:
1099 end.y = m_size.y;
1100 end += m_pos;
1101
1102 box.SetEnd( end );
1103 box.Inflate( lineWidth / 2 );
1104
1105 return box;
1106}
1107
1108
1110{
1111 BOX2I bbox = GetBodyBoundingBox();
1112
1113 for( const SCH_FIELD& field : m_fields )
1114 bbox.Merge( field.GetBoundingBox() );
1115
1116 return bbox;
1117}
1118
1119
1121{
1122 BOX2I box( m_pos, m_size );
1123 return box.GetCenter();
1124}
1125
1126
1128{
1129 int n = 0;
1130
1131 if( m_screen )
1132 {
1133 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SYMBOL_T ) )
1134 {
1135 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
1136
1137 if( !symbol->IsPower() )
1138 n++;
1139 }
1140
1141 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1142 n += static_cast<const SCH_SHEET*>( aItem )->SymbolCount();
1143 }
1144
1145 return n;
1146}
1147
1148
1149bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
1150{
1151 if( m_screen )
1152 {
1153 // Only check the root sheet once and don't recurse.
1154 if( !GetParent() )
1155 {
1156 if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
1157 {
1158 *aScreen = m_screen;
1159 return true;
1160 }
1161 }
1162
1163 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1164 {
1165 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
1166 SCH_SCREEN* screen = sheet->m_screen;
1167
1168 // Must use the screen's path (which is always absolute) rather than the
1169 // sheet's (which could be relative).
1170 if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
1171 {
1172 *aScreen = screen;
1173 return true;
1174 }
1175
1176 if( sheet->SearchHierarchy( aFilename, aScreen ) )
1177 return true;
1178 }
1179 }
1180
1181 return false;
1182}
1183
1184
1186{
1187 if( m_screen )
1188 {
1189 aList->push_back( this );
1190
1191 if( m_screen == aScreen )
1192 return true;
1193
1194 for( EDA_ITEM* item : m_screen->Items().OfType( SCH_SHEET_T ) )
1195 {
1196 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1197
1198 if( sheet->LocatePathOfScreen( aScreen, aList ) )
1199 return true;
1200 }
1201
1202 aList->pop_back();
1203 }
1204
1205 return false;
1206}
1207
1208
1209int SCH_SHEET::CountSheets( const wxString& aFilename ) const
1210{
1211 int count = 0;
1212
1213 if( m_screen )
1214 {
1215 if( m_screen->GetFileName().Cmp( aFilename ) == 0 )
1216 count++;
1217
1218 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1219 count += static_cast<SCH_SHEET*>( aItem )->CountSheets( aFilename );
1220 }
1221
1222 return count;
1223}
1224
1225
1227{
1228 int count = 1; //1 = this!!
1229
1230 if( m_screen )
1231 {
1232 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1233 count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
1234 }
1235
1236 return count;
1237}
1238
1239
1241{
1242 int count = CountSheets();
1243
1244 if( IsVirtualRootSheet() )
1245 count--;
1246
1247 return count;
1248}
1249
1250
1251void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1252{
1253 // Don't use GetShownText(); we want to see the variable references here
1254 aList.emplace_back( _( "Sheet Name" ), KIUI::EllipsizeStatusText( aFrame, GetName() ) );
1255
1256 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1257 SCH_SHEET_PATH* currentSheet = nullptr;
1258 wxString currentVariant;
1259
1260 if( schframe )
1261 {
1262 SCH_SHEET_PATH path = schframe->GetCurrentSheet();
1263 path.push_back( this );
1264 currentSheet = &schframe->GetCurrentSheet();
1265 currentVariant = Schematic() ? Schematic()->GetCurrentVariant() : wxString();
1266
1267 aList.emplace_back( _( "Hierarchical Path" ), path.PathHumanReadable( false, true ) );
1268 }
1269
1270 // Don't use GetShownText(); we want to see the variable references here
1271 aList.emplace_back( _( "File Name" ), KIUI::EllipsizeStatusText( aFrame, GetFileName() ) );
1272
1273 wxArrayString msgs;
1274 wxString msg;
1275
1276 if( GetExcludedFromSim() )
1277 msgs.Add( _( "Simulation" ) );
1278
1279 if( GetExcludedFromBOM() )
1280 msgs.Add( _( "BOM" ) );
1281
1282 if( GetExcludedFromBoard() )
1283 msgs.Add( _( "Board" ) );
1284
1285 if( GetDNP( currentSheet, currentVariant ) )
1286 msgs.Add( _( "DNP" ) );
1287
1288 msg = wxJoin( msgs, '|' );
1289 msg.Replace( '|', wxS( ", " ) );
1290
1291 if( !msg.empty() )
1292 aList.emplace_back( _( "Exclude from" ), msg );
1293}
1294
1295
1296std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> SCH_SHEET::GetNoConnects() const
1297{
1298 std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> noConnects;
1299
1300 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( GetParent() );
1301
1302 // A top level sheet is parented to the root sheet rather than to the root screen, so reach
1303 // the screen that holds this sheet through the parent sheet instead
1304 if( !screen )
1305 {
1306 if( SCH_SHEET* parentSheet = dynamic_cast<SCH_SHEET*>( GetParent() ) )
1307 screen = parentSheet->GetScreen();
1308 }
1309
1310 if( screen )
1311 {
1312 for( SCH_SHEET_PIN* sheetPin : m_pins )
1313 {
1314 for( SCH_ITEM* noConnect : screen->Items().Overlapping( SCH_NO_CONNECT_T, sheetPin->GetTextPos() ) )
1315 noConnects[sheetPin] = static_cast<SCH_NO_CONNECT*>( noConnect );
1316 }
1317 }
1318
1319 return noConnects;
1320}
1321
1322
1324{
1325 VECTOR2I delta = aPosition - m_pos;
1326
1327 m_pos = aPosition;
1328
1329 for( SCH_FIELD& field : m_fields )
1330 field.Move( delta );
1331}
1332
1333
1334void SCH_SHEET::Move( const VECTOR2I& aMoveVector )
1335{
1336 m_pos += aMoveVector;
1337
1338 for( SCH_SHEET_PIN* pin : m_pins )
1339 pin->Move( aMoveVector );
1340
1341 for( SCH_FIELD& field : m_fields )
1342 field.Move( aMoveVector );
1343}
1344
1345
1346void SCH_SHEET::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
1347{
1348 VECTOR2I prev = m_pos;
1349
1350 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
1351 RotatePoint( &m_size.x, &m_size.y, aRotateCCW ? ANGLE_90 : ANGLE_270 );
1352
1353 if( m_size.x < 0 )
1354 {
1355 m_pos.x += m_size.x;
1356 m_size.x = -m_size.x;
1357 }
1358
1359 if( m_size.y < 0 )
1360 {
1361 m_pos.y += m_size.y;
1362 m_size.y = -m_size.y;
1363 }
1364
1365 // Pins must be rotated first as that's how we determine vertical vs horizontal
1366 // orientation for auto-placement
1367 for( SCH_SHEET_PIN* sheetPin : m_pins )
1368 sheetPin->Rotate( aCenter, aRotateCCW );
1369
1371 {
1373 }
1374 else
1375 {
1376 // Move the fields to the new position because the parent itself has moved.
1377 for( SCH_FIELD& field : m_fields )
1378 {
1379 VECTOR2I pos = field.GetTextPos();
1380 pos.x -= prev.x - m_pos.x;
1381 pos.y -= prev.y - m_pos.y;
1382 field.SetTextPos( pos );
1383 }
1384 }
1385}
1386
1387
1389{
1390 int dy = m_pos.y;
1391
1392 MIRROR( m_pos.y, aCenter );
1393 m_pos.y -= m_size.y;
1394 dy -= m_pos.y; // 0,dy is the move vector for this transform
1395
1396 for( SCH_SHEET_PIN* sheetPin : m_pins )
1397 sheetPin->MirrorVertically( aCenter );
1398
1399 for( SCH_FIELD& field : m_fields )
1400 {
1401 VECTOR2I pos = field.GetTextPos();
1402 pos.y -= dy;
1403 field.SetTextPos( pos );
1404 }
1405}
1406
1407
1409{
1410 int dx = m_pos.x;
1411
1412 MIRROR( m_pos.x, aCenter );
1413 m_pos.x -= m_size.x;
1414 dx -= m_pos.x; // dx,0 is the move vector for this transform
1415
1416 for( SCH_SHEET_PIN* sheetPin : m_pins )
1417 sheetPin->MirrorHorizontally( aCenter );
1418
1419 for( SCH_FIELD& field : m_fields )
1420 {
1421 VECTOR2I pos = field.GetTextPos();
1422 pos.x -= dx;
1423 field.SetTextPos( pos );
1424 }
1425}
1426
1427
1428void SCH_SHEET::SetPosition( const VECTOR2I& aPosition )
1429{
1430 // Remember the sheet and all pin sheet positions must be
1431 // modified. So use Move function to do that.
1432 Move( aPosition - m_pos );
1433}
1434
1435
1436void SCH_SHEET::Resize( const VECTOR2I& aSize )
1437{
1438 if( aSize == m_size )
1439 return;
1440
1441 m_size = aSize;
1442
1443 // Move the fields if we're in autoplace mode
1446
1447 // Move the sheet labels according to the new sheet size.
1448 for( SCH_SHEET_PIN* sheetPin : m_pins )
1449 sheetPin->ConstrainOnEdge( sheetPin->GetPosition(), false );
1450}
1451
1452
1453bool SCH_SHEET::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
1454{
1455 // Sheets are searchable via the child field and pin item text.
1456 return false;
1457}
1458
1459
1461{
1462 int id = 2;
1463
1464 for( SCH_SHEET_PIN* pin : m_pins )
1465 {
1466 pin->SetNumber( id );
1467 id++;
1468 }
1469}
1470
1471
1473{
1474 wxCHECK_MSG( Schematic(), SCH_SHEET_PATH(), "Can't call findSelf without a schematic" );
1475
1476 SCH_SHEET_PATH sheetPath = Schematic()->CurrentSheet();
1477
1478 while( !sheetPath.empty() && sheetPath.Last() != this )
1479 sheetPath.pop_back();
1480
1481 if( sheetPath.empty() )
1482 {
1483 // If we weren't in the hierarchy, then we must be a child of the current sheet.
1484 sheetPath = Schematic()->CurrentSheet();
1485 sheetPath.push_back( const_cast<SCH_SHEET*>( this ) );
1486 }
1487
1488 return sheetPath;
1489}
1490
1491
1492void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1493{
1494 for( SCH_SHEET_PIN* sheetPin : m_pins )
1495 {
1496 wxCHECK2_MSG( sheetPin->Type() == SCH_SHEET_PIN_T, continue,
1497 wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) );
1498
1499 sheetPin->GetEndPoints( aItemList );
1500 }
1501}
1502
1503
1504bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
1505 std::vector<DANGLING_END_ITEM>& aItemListByPos,
1506 const SCH_SHEET_PATH* aPath )
1507{
1508 bool changed = false;
1509
1510 for( SCH_SHEET_PIN* sheetPin : m_pins )
1511 changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
1512
1513 return changed;
1514}
1515
1516
1518 const SCH_SHEET_PATH* aInstance ) const
1519{
1520 // Do not compare to ourself.
1521 if( aItem == this )
1522 return false;
1523
1524 const SCH_SHEET* sheet = dynamic_cast<const SCH_SHEET*>( aItem );
1525
1526 // Don't compare against a different SCH_ITEM.
1527 wxCHECK( sheet, false );
1528
1529 if( GetPosition() != sheet->GetPosition() )
1530 return true;
1531
1532 // Technically this cannot happen because undo/redo does not support reloading sheet
1533 // file association changes. This was just added so that it doesn't get missed should
1534 // we ever fix the undo/redo issue.
1535 if( ( GetFileName() != sheet->GetFileName() ) || ( GetName() != sheet->GetName() ) )
1536 return true;
1537
1538 if( m_pins.size() != sheet->m_pins.size() )
1539 return true;
1540
1541 for( size_t i = 0; i < m_pins.size(); i++ )
1542 {
1543 if( m_pins[i]->HasConnectivityChanges( sheet->m_pins[i] ) )
1544 return true;
1545 }
1546
1547 return false;
1548}
1549
1550
1551std::vector<VECTOR2I> SCH_SHEET::GetConnectionPoints() const
1552{
1553 std::vector<VECTOR2I> retval;
1554
1555 for( SCH_SHEET_PIN* sheetPin : m_pins )
1556 retval.push_back( sheetPin->GetPosition() );
1557
1558 return retval;
1559}
1560
1561
1562INSPECT_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData,
1563 const std::vector<KICAD_T>& aScanTypes )
1564{
1565 for( KICAD_T scanType : aScanTypes )
1566 {
1567 // If caller wants to inspect my type
1568 if( scanType == SCH_LOCATE_ANY_T || scanType == Type() )
1569 {
1570 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1571 return INSPECT_RESULT::QUIT;
1572 }
1573
1574 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1575 {
1576 // Test the sheet fields.
1577 for( SCH_FIELD& field : m_fields )
1578 {
1579 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1580 return INSPECT_RESULT::QUIT;
1581 }
1582 }
1583
1584 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_SHEET_PIN_T )
1585 {
1586 // Test the sheet labels.
1587 for( SCH_SHEET_PIN* sheetPin : m_pins )
1588 {
1589 if( INSPECT_RESULT::QUIT == aInspector( sheetPin, this ) )
1590 return INSPECT_RESULT::QUIT;
1591 }
1592 }
1593 }
1594
1596}
1597
1598
1599void SCH_SHEET::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1600{
1601 for( SCH_FIELD& field : m_fields )
1602 aFunction( &field );
1603
1604 for( SCH_SHEET_PIN* pin : m_pins )
1605 aFunction( pin );
1606}
1607
1608
1609wxString SCH_SHEET::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1610{
1611 const SCH_FIELD* sheetnameField = GetField( FIELD_T::SHEET_NAME );
1612
1613 return wxString::Format( _( "Hierarchical Sheet '%s'" ),
1614 aFull ? sheetnameField->GetShownText( FOR_GUI )
1615 : KIUI::EllipsizeMenuText( sheetnameField->GetText() ) );
1616}
1617
1618
1623
1624
1625bool SCH_SHEET::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1626{
1627 BOX2I rect = GetBodyBoundingBox();
1628
1629 rect.Inflate( aAccuracy );
1630
1631 return rect.Contains( aPosition );
1632}
1633
1634
1635bool SCH_SHEET::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1636{
1637 BOX2I rect = aRect;
1638
1639 rect.Inflate( aAccuracy );
1640
1641 if( aContained )
1642 return rect.Contains( GetBodyBoundingBox() );
1643
1644 return rect.Intersects( GetBodyBoundingBox() );
1645}
1646
1647
1648bool SCH_SHEET::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
1649{
1650 return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
1651}
1652
1653
1654void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1655 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1656{
1657 if( aBackground && !aPlotter->GetColorMode() )
1658 return;
1659
1660 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1661 COLOR4D borderColor = GetBorderColor();
1662 COLOR4D backgroundColor = GetBackgroundColor();
1663 SCH_SHEET_PATH instance;
1664 wxString variantName;
1665
1666 if( Schematic() )
1667 {
1668 instance = Schematic()->CurrentSheet();
1669 variantName = Schematic()->GetCurrentVariant();
1670 }
1671
1672 bool dnp = GetDNP( &instance, variantName );
1673
1674 if( renderSettings->m_OverrideItemColors || borderColor == COLOR4D::UNSPECIFIED )
1675 borderColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET );
1676
1677 if( renderSettings->m_OverrideItemColors || backgroundColor == COLOR4D::UNSPECIFIED )
1678 backgroundColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET_BACKGROUND );
1679
1680 if( borderColor.m_text && Schematic() )
1681 borderColor = COLOR4D( ResolveText( *borderColor.m_text, &Schematic()->CurrentSheet() ) );
1682
1683 if( backgroundColor.m_text && Schematic() )
1684 backgroundColor = COLOR4D( ResolveText( *backgroundColor.m_text, &Schematic()->CurrentSheet() ) );
1685
1686 if( aDimmed || dnp )
1687 {
1688 borderColor.Desaturate();
1689 borderColor = borderColor.Mix( backgroundColor, 0.5f );
1690 }
1691
1692 if( aBackground && backgroundColor.a > 0.0 )
1693 {
1694 aPlotter->SetColor( backgroundColor );
1695 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::FILLED_SHAPE, 1, 0 );
1696 }
1697 else
1698 {
1699 aPlotter->SetColor( borderColor );
1700
1701 int penWidth = GetEffectivePenWidth( getRenderSettings( aPlotter ) );
1702 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::NO_FILL, penWidth, 0 );
1703 }
1704
1705 // Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
1706 if( aPlotOpts.m_PDFHierarchicalLinks )
1707 {
1708 aPlotter->HyperlinkBox( GetBoundingBox(),
1709 EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1710 }
1711 else if( aPlotOpts.m_PDFPropertyPopups )
1712 {
1713 std::vector<wxString> properties;
1714
1715 properties.emplace_back( EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1716
1717 for( const SCH_FIELD& field : GetFields() )
1718 {
1719 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1720 field.GetName(),
1721 field.GetShownText( FOR_GUI ) ) );
1722 }
1723
1724 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
1725 }
1726
1727 // Plot sheet pins
1728 for( SCH_SHEET_PIN* sheetPin : m_pins )
1729 sheetPin->Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed || dnp );
1730
1731 // Plot the fields
1732 for( SCH_FIELD& field : m_fields )
1733 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed || dnp );
1734
1735 if( dnp && renderSettings->m_ShowDNPMarkers )
1736 {
1737 BOX2I bbox = GetBodyBoundingBox();
1738 BOX2I pins = GetBoundingBox();
1739 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
1740 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
1741 int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
1742
1743 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
1744 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
1745 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
1746
1747 aPlotter->SetColor( renderSettings->GetLayerColor( LAYER_DNP_MARKER ) );
1748
1749 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, nullptr );
1750
1751 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
1752 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
1753 strokeWidth, nullptr );
1754 }
1755}
1756
1757
1759{
1760 wxCHECK_MSG( Type() == aItem.Type(), *this,
1761 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
1762 GetClass() );
1763
1764 if( &aItem != this )
1765 {
1766 SCH_ITEM::operator=( aItem );
1767
1768 SCH_SHEET* sheet = (SCH_SHEET*) &aItem;
1769
1770 m_pos = sheet->m_pos;
1771 m_size = sheet->m_size;
1772 m_fields = sheet->m_fields;
1773
1774 for( SCH_SHEET_PIN* pin : sheet->m_pins )
1775 {
1776 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
1777 m_pins.back()->SetParent( this );
1778 }
1779
1780 for( const SCH_SHEET_INSTANCE& instance : sheet->m_instances )
1781 m_instances.emplace_back( instance );
1782 }
1783
1784 return *this;
1785}
1786
1787
1788bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
1789{
1790 if( Type() != aItem.Type() )
1791 return Type() < aItem.Type();
1792
1793 const SCH_SHEET* otherSheet = static_cast<const SCH_SHEET*>( &aItem );
1794
1795 if( GetName() != otherSheet->GetName() )
1796 return GetName() < otherSheet->GetName();
1797
1798 if( GetFileName() != otherSheet->GetFileName() )
1799 return GetFileName() < otherSheet->GetFileName();
1800
1801 return false;
1802}
1803
1804
1805void SCH_SHEET::RemoveInstance( const KIID_PATH& aInstancePath )
1806{
1807 // Search for an existing path and remove it if found (should not occur)
1808 // (search from back to avoid invalidating iterator on remove)
1809 for( int ii = m_instances.size() - 1; ii >= 0; --ii )
1810 {
1811 if( m_instances[ii].m_Path == aInstancePath )
1812 {
1813 wxLogTrace( traceSchSheetPaths, "Removing sheet instance:\n"
1814 " sheet path %s\n"
1815 " page %s, from project %s.",
1816 aInstancePath.AsString(),
1817 m_instances[ii].m_PageNumber,
1818 m_instances[ii].m_ProjectName );
1819
1820 m_instances.erase( m_instances.begin() + ii );
1821 }
1822 }
1823}
1824
1825
1827{
1828 SCH_SHEET_INSTANCE oldInstance;
1829
1830 if( getInstance( oldInstance, aInstance.m_Path ) )
1831 RemoveInstance( aInstance.m_Path );
1832
1833 m_instances.emplace_back( aInstance );
1834
1835}
1836
1837
1839{
1840 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1841 {
1842 // if aSheetPath is found, nothing to do:
1843 if( instance.m_Path == aPath )
1844 return false;
1845 }
1846
1847 wxLogTrace( traceSchSheetPaths, wxT( "Adding instance `%s` to sheet `%s`." ),
1848 aPath.AsString(),
1849 ( GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : GetName() );
1850
1851 SCH_SHEET_INSTANCE instance;
1852
1853 instance.m_Path = aPath;
1854
1855 // This entry does not exist: add it with an empty page number.
1856 m_instances.emplace_back( instance );
1857 return true;
1858}
1859
1860
1861bool SCH_SHEET::getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
1862 bool aTestFromEnd ) const
1863{
1864 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1865 {
1866 if( !aTestFromEnd )
1867 {
1868 if( instance.m_Path == aSheetPath )
1869 {
1870 aInstance = instance;
1871 return true;
1872 }
1873 }
1874 else if( instance.m_Path.EndsWith( aSheetPath ) )
1875 {
1876 aInstance = instance;
1877 return true;
1878 }
1879 }
1880
1881 return false;
1882}
1883
1884
1886{
1887 for( SCH_SHEET_INSTANCE& instance : m_instances )
1888 {
1889 if( instance.m_Path == aSheetPath )
1890 return &instance;
1891 }
1892
1893 return nullptr;
1894}
1895
1896
1897const SCH_SHEET_INSTANCE* SCH_SHEET::getInstance( const KIID_PATH& aSheetPath ) const
1898{
1899 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1900 {
1901 if( instance.m_Path == aSheetPath )
1902 return &instance;
1903 }
1904
1905 return nullptr;
1906}
1907
1908
1910{
1911 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1912 {
1913 if( instance.m_Path.size() == 0 )
1914 return true;
1915 }
1916
1917 return false;
1918}
1919
1920
1922{
1923 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1924 {
1925 if( instance.m_Path.size() == 0 )
1926 return instance;
1927 }
1928
1929 wxFAIL;
1930
1932
1933 return dummy;
1934}
1935
1936
1937wxString SCH_SHEET::getPageNumber( const KIID_PATH& aParentPath ) const
1938{
1939 wxString pageNumber;
1940
1941 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1942 {
1943 if( instance.m_Path == aParentPath )
1944 {
1945 pageNumber = instance.m_PageNumber;
1946 break;
1947 }
1948 }
1949
1950 return pageNumber;
1951}
1952
1953
1954void SCH_SHEET::setPageNumber( const KIID_PATH& aPath, const wxString& aPageNumber )
1955{
1956 for( SCH_SHEET_INSTANCE& instance : m_instances )
1957 {
1958 if( instance.m_Path == aPath )
1959 {
1960 instance.m_PageNumber = aPageNumber;
1961 break;
1962 }
1963 }
1964}
1965
1966
1968{
1969 return GetName() != aOther.GetName() || GetFileName() != aOther.GetFileName()
1970 || GetScreen() != aOther.GetScreen() || HasPageNumberChanges( aOther );
1971}
1972
1974{
1975 // Avoid self comparison.
1976 if( &aOther == this )
1977 return false;
1978
1979 // A difference in the instance data count implies a page numbering change.
1980 if( GetInstances().size() != aOther.GetInstances().size() )
1981 return true;
1982
1983 std::vector<SCH_SHEET_INSTANCE> instances = GetInstances();
1984 std::vector<SCH_SHEET_INSTANCE> otherInstances = aOther.GetInstances();
1985
1986 // Sorting may not be necessary but there is no guarantee that sheet
1987 // instance data will be in the correct KIID_PATH order. We should
1988 // probably use a std::map instead of a std::vector to store the sheet
1989 // instance data.
1990 std::sort( instances.begin(), instances.end(),
1991 []( const SCH_SHEET_INSTANCE& aLhs, const SCH_SHEET_INSTANCE& aRhs )
1992 {
1993 if( aLhs.m_Path > aRhs.m_Path )
1994 return true;
1995
1996 return false;
1997 } );
1998 std::sort( otherInstances.begin(), otherInstances.end(),
1999 []( const SCH_SHEET_INSTANCE& aLhs, const SCH_SHEET_INSTANCE& aRhs )
2000 {
2001 if( aLhs.m_Path > aRhs.m_Path )
2002 return true;
2003
2004 return false;
2005 } );
2006
2007 auto itThis = instances.begin();
2008 auto itOther = otherInstances.begin();
2009
2010 while( itThis != instances.end() )
2011 {
2012 if( ( itThis->m_Path == itOther->m_Path )
2013 && ( itThis->m_PageNumber != itOther->m_PageNumber ) )
2014 {
2015 return true;
2016 }
2017
2018 itThis++;
2019 itOther++;
2020 }
2021
2022 return false;
2023}
2024
2025
2026int SCH_SHEET::ComparePageNum( const wxString& aPageNumberA, const wxString& aPageNumberB )
2027{
2028 if( aPageNumberA == aPageNumberB )
2029 return 0; // A == B
2030
2031 // First sort numerically if the page numbers are integers
2032 long pageA, pageB;
2033 bool isIntegerPageA = aPageNumberA.ToLong( &pageA );
2034 bool isIntegerPageB = aPageNumberB.ToLong( &pageB );
2035
2036 if( isIntegerPageA && isIntegerPageB )
2037 {
2038 if( pageA < pageB )
2039 return -1; //A < B
2040 else
2041 return 1; // A > B
2042 }
2043
2044 // Numerical page numbers always before strings
2045 if( isIntegerPageA )
2046 return -1; //A < B
2047 else if( isIntegerPageB )
2048 return 1; // A > B
2049
2050 // If not numeric, then sort as strings using natural sort
2051 int result = StrNumCmp( aPageNumberA, aPageNumberB );
2052
2053 // Divide by zero bad.
2054 wxCHECK( result != 0, 0 );
2055
2057
2058 return result;
2059}
2060
2061
2062bool SCH_SHEET::operator==( const SCH_ITEM& aOther ) const
2063{
2064 if( Type() != aOther.Type() )
2065 return false;
2066
2067 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
2068
2069 if( m_pos != other->m_pos )
2070 return false;
2071
2072 if( m_size != other->m_size )
2073 return false;
2074
2075 if( GetExcludedFromSim() != other->GetExcludedFromSim() )
2076 return false;
2077
2078 if( GetExcludedFromBOM() != other->GetExcludedFromBOM() )
2079 return false;
2080
2081 if( GetExcludedFromBoard() != other->GetExcludedFromBoard() )
2082 return false;
2083
2084 if( GetDNP() != other->GetDNP() )
2085 return false;
2086
2087 if( GetBorderColor() != other->GetBorderColor() )
2088 return false;
2089
2090 if( GetBackgroundColor() != other->GetBackgroundColor() )
2091 return false;
2092
2093 if( GetBorderWidth() != other->GetBorderWidth() )
2094 return false;
2095
2096 if( GetFields().size() != other->GetFields().size() )
2097 return false;
2098
2099 for( size_t i = 0; i < GetFields().size(); ++i )
2100 {
2101 if( !( GetFields()[i] == other->GetFields()[i] ) )
2102 return false;
2103 }
2104
2105 return true;
2106}
2107
2108
2109double SCH_SHEET::Similarity( const SCH_ITEM& aOther ) const
2110{
2111 if( Type() != aOther.Type() )
2112 return 0.0;
2113
2114 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
2115
2116 if( m_screen->GetFileName() == other->m_screen->GetFileName() )
2117 return 1.0;
2118
2119 return 0.0;
2120}
2121
2122
2123void SCH_SHEET::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SHEET_VARIANT& aVariant )
2124{
2125 SCH_SHEET_INSTANCE* instance = getInstance( aInstance );
2126
2127 // The instance path must already exist.
2128 if( !instance )
2129 return;
2130
2131 instance->m_Variants.insert( std::make_pair( aVariant.m_Name, aVariant ) );
2132}
2133
2134
2135void SCH_SHEET::DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantName )
2136{
2137 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2138
2139 // The instance path must already exist.
2140 if( !instance || !instance->m_Variants.contains( aVariantName ) )
2141 return;
2142
2143 instance->m_Variants.erase( aVariantName );
2144}
2145
2146
2147void SCH_SHEET::ClearVariantField( const KIID_PATH& aPath, const wxString& aVariantName,
2148 const wxString& aFieldName )
2149{
2150 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2151
2152 if( !instance || !instance->m_Variants.contains( aVariantName ) )
2153 return;
2154
2155 instance->m_Variants[aVariantName].m_Fields.erase( aFieldName );
2156}
2157
2158
2159void SCH_SHEET::RenameVariant( const KIID_PATH& aPath, const wxString& aOldName,
2160 const wxString& aNewName )
2161{
2162 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2163
2164 // The instance path must already exist and contain the old variant.
2165 if( !instance || !instance->m_Variants.contains( aOldName ) )
2166 return;
2167
2168 // Get the variant data, update the name, and re-insert with new key
2169 SCH_SHEET_VARIANT variant = instance->m_Variants[aOldName];
2170 variant.m_Name = aNewName;
2171 instance->m_Variants.erase( aOldName );
2172 instance->m_Variants.insert( std::make_pair( aNewName, variant ) );
2173}
2174
2175
2176void SCH_SHEET::CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
2177 const wxString& aNewVariant )
2178{
2179 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2180
2181 // The instance path must already exist and contain the source variant.
2182 if( !instance || !instance->m_Variants.contains( aSourceVariant ) )
2183 return;
2184
2185 // Copy the variant data with a new name
2186 SCH_SHEET_VARIANT variant = instance->m_Variants[aSourceVariant];
2187 variant.m_Name = aNewVariant;
2188 instance->m_Variants.insert( std::make_pair( aNewVariant, variant ) );
2189}
2190
2191
2192void SCH_SHEET::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2193{
2194 if( !aInstance || aVariantName.IsEmpty() )
2195 {
2196 m_DNP = aEnable;
2197 return;
2198 }
2199
2200 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
2201
2202 wxCHECK_MSG( instance, /* void */,
2203 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
2204 aInstance->PathHumanReadable() ) );
2205
2206 if( aVariantName.IsEmpty() )
2207 {
2208 m_DNP = aEnable;
2209 }
2210 else
2211 {
2212 if( instance->m_Variants.contains( aVariantName ) )
2213 {
2214 instance->m_Variants[aVariantName].m_DNP = aEnable;
2215 }
2216 else if( aEnable != m_DNP )
2217 {
2218 SCH_SHEET_VARIANT variant( aVariantName );
2219
2220 variant.InitializeAttributes( *this );
2221 variant.m_DNP = aEnable;
2222 AddVariant( *aInstance, variant );
2223 }
2224 }
2225}
2226
2227
2228bool SCH_SHEET::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2229{
2230 if( !aInstance || aVariantName.IsEmpty() )
2231 return m_DNP;
2232
2233 SCH_SHEET_INSTANCE instance;
2234
2235 if( !getInstance( instance, aInstance->Path() ) )
2236 return m_DNP;
2237
2238 if( instance.m_Variants.contains( aVariantName ) )
2239 return instance.m_Variants[aVariantName].m_DNP;
2240
2241 // If the variant has not been defined, return the default DNP setting.
2242 return m_DNP;
2243}
2244
2245
2247{
2248 return GetDNP( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2249}
2250
2251
2252void SCH_SHEET::SetDNPProp( bool aEnable )
2253{
2254 SetDNP( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2255}
2256
2257
2258void SCH_SHEET::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2259{
2260 if( !aInstance || aVariantName.IsEmpty() )
2261 {
2262 m_excludedFromSim = aEnable;
2263 return;
2264 }
2265
2266 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
2267
2268 wxCHECK_MSG( instance, /* void */,
2269 wxString::Format( wxS( "Cannot get m_excludedFromSim attribute for invalid sheet path '%s'." ),
2270 aInstance->PathHumanReadable() ) );
2271
2272 if( aVariantName.IsEmpty() )
2273 {
2274 m_excludedFromSim = aEnable;
2275 }
2276 else
2277 {
2278 if( instance->m_Variants.contains( aVariantName ) )
2279 {
2280 instance->m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
2281 }
2282 else if( aEnable != m_excludedFromSim )
2283 {
2284 SCH_SHEET_VARIANT variant( aVariantName );
2285
2286 variant.InitializeAttributes( *this );
2287 variant.m_ExcludedFromSim = aEnable;
2288 AddVariant( *aInstance, variant );
2289 }
2290 }
2291}
2292
2293
2294bool SCH_SHEET::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2295{
2296 if( !aInstance || aVariantName.IsEmpty() )
2297 return m_excludedFromSim;
2298
2299 SCH_SHEET_INSTANCE instance;
2300
2301 if( !getInstance( instance, aInstance->Path() ) )
2302 return m_excludedFromSim;
2303
2304 if( instance.m_Variants.contains( aVariantName ) )
2305 return instance.m_Variants[aVariantName].m_ExcludedFromSim;
2306
2307 // If the variant has not been defined, return the default DNP setting.
2308 return m_excludedFromSim;
2309}
2310
2311
2313{
2314 return GetExcludedFromSim( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2315}
2316
2317
2319{
2320 SetExcludedFromSim( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2321}
2322
2323
2324void SCH_SHEET::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2325{
2326 if( !aInstance || aVariantName.IsEmpty() )
2327 {
2328 m_excludedFromBOM = aEnable;
2329 return;
2330 }
2331
2332 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
2333
2334 wxCHECK_MSG( instance, /* void */,
2335 wxString::Format( wxS( "Cannot get m_excludedFromBOM attribute for invalid sheet path '%s'." ),
2336 aInstance->PathHumanReadable() ) );
2337
2338 if( aVariantName.IsEmpty() )
2339 {
2340 m_excludedFromBOM = aEnable;
2341 }
2342 else
2343 {
2344 if( instance->m_Variants.contains( aVariantName ) )
2345 {
2346 instance->m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
2347 }
2348 else if( aEnable != m_excludedFromBOM )
2349 {
2350 SCH_SHEET_VARIANT variant( aVariantName );
2351
2352 variant.InitializeAttributes( *this );
2353 variant.m_ExcludedFromBOM = aEnable;
2354 AddVariant( *aInstance, variant );
2355 }
2356 }
2357}
2358
2359
2360bool SCH_SHEET::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2361{
2362 if( !aInstance || aVariantName.IsEmpty() )
2363 return m_excludedFromBOM;
2364
2365 SCH_SHEET_INSTANCE instance;
2366
2367 if( !getInstance( instance, aInstance->Path() ) )
2368 return m_excludedFromBOM;
2369
2370 if( instance.m_Variants.contains( aVariantName ) )
2371 return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
2372
2373 // If the variant has not been defined, return the default DNP setting.
2374 return m_excludedFromBOM;
2375}
2376
2377
2379{
2380 return GetExcludedFromBOM( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2381}
2382
2383
2385{
2386 SetExcludedFromBOM( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2387}
2388
2389
2390#if defined(DEBUG)
2391
2392void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
2393{
2394 // XML output:
2395 wxString s = GetClass();
2396
2397 NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">" << " sheet_name=\""
2398 << TO_UTF8( GetName() ) << '"' << ">\n";
2399
2400 // show all the pins, and check the linked list integrity
2401 for( SCH_SHEET_PIN* sheetPin : m_pins )
2402 sheetPin->Show( nestLevel + 1, os );
2403
2404 NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n" << std::flush;
2405}
2406
2407#endif
2408
2409static struct SCH_SHEET_DESC
2410{
2412 {
2416
2417 propMgr.AddProperty( new PROPERTY<SCH_SHEET, wxString>( _HKI( "Sheet Name" ),
2419 .SetValidator( []( const wxAny&& aValue, EDA_ITEM* ) -> VALIDATOR_RESULT
2420 {
2421 wxString value;
2422
2423 if( !aValue.GetAs( &value ) )
2424 return {};
2425
2426 wxString msg = GetFieldValidationErrorMessage( FIELD_T::SHEET_NAME, value );
2427
2428 if( msg.empty() )
2429 return {};
2430
2431 return std::make_unique<VALIDATION_ERROR_MSG>( msg );
2432 } );
2433
2434 propMgr.AddProperty( new PROPERTY<SCH_SHEET, int>( _HKI( "Border Width" ),
2436
2437 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Border Color" ),
2439
2440 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Background Color" ),
2442
2443 const wxString groupAttributes = _HKI( "Attributes" );
2444
2445 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Board" ),
2447 groupAttributes );
2448 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Simulation" ),
2450 groupAttributes );
2451 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Bill of Materials" ),
2453 groupAttributes );
2454 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Do not Populate" ),
2456 groupAttributes );
2457 }
const char * name
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
BITMAPS
A list of all bitmap identifiers.
@ add_hierarchical_subsheet
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr const Vec GetEnd() const
Definition box2.h:209
constexpr coord_type GetY() const
Definition box2.h:205
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr coord_type GetX() const
Definition box2.h:204
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:653
constexpr const Vec GetCenter() const
Definition box2.h:227
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr coord_type GetLeft() const
Definition box2.h:225
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr void SetEnd(coord_type x, coord_type y)
Definition box2.h:294
constexpr coord_type GetTop() const
Definition box2.h:226
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
constexpr coord_type GetBottom() const
Definition box2.h:219
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:399
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
std::vector< PROPERTY_BASE * > GetCustomPropertiesAsInspectables() const
Definition eda_item.cpp:200
const KIID m_Uuid
Definition eda_item.h:597
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
virtual VECTOR2I GetTextSize() const
Definition eda_text.h:301
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:539
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:373
static wxString GotoPageHref(const wxString &aDestination)
Generate a href to a page in the current schematic.
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:263
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:365
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition sch_rtree.h:253
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:396
double a
Alpha component.
Definition color4d.h:393
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:530
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition color4d.h:292
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxString AsString() const
Definition kiid.cpp:423
Definition kiid.h:46
Base plotter engine class.
Definition plotter.h:136
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:167
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0)=0
virtual void HyperlinkBox(const BOX2I &aBox, const wxString &aDestinationURL)
Create a clickable hyperlink with a rectangular click area.
Definition plotter.h:506
bool GetColorMode() const
Definition plotter.h:164
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:441
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:517
virtual void SetColor(const COLOR4D &color)=0
Container for project specific data.
Definition project.h:63
PROPERTY_BASE(const wxString &aName, PROPERTY_DISPLAY aDisplay=PT_DEFAULT, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType=ORIGIN_TRANSFORMS::NOT_A_COORD)
< Used to generate unique IDs. Must come up front so it's initialized before ctor.
Definition property.h:201
PROPERTY_BASE & SetGroup(const wxString &aGroup)
Definition property.h:366
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition property.h:368
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
bool IsTopLevelSheet(const SCH_SHEET *aSheet) const
Check if a sheet is a top-level sheet (direct child of virtual root).
SCHEMATIC_SETTINGS & Settings() const
wxString GetCurrentVariant() const
Return the current variant being edited.
void GetContextualTextVars(wxArrayString *aVars) const
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:303
Schematic editor (Eeschema) main window.
SCH_SHEET_PATH & GetCurrentSheet() const
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:138
FIELD_T GetId() const
Definition sch_field.h:142
wxString GetUntranslatedName() const
Get the untranslated field name for storage, variable look-up, etc.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString, int aDepth=0) const
void SetText(const wxString &aText) override
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
void SetLocked(bool aLocked) override
Definition sch_item.h:256
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:78
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:739
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:281
bool IsLocked() const override
Definition sch_item.cpp:158
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
Definition sch_item.h:637
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:794
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
AUTOPLACE_ALGO GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition sch_item.h:636
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:390
wxString GetClass() const override
Return the class name.
Definition sch_item.h:175
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition sch_item.cpp:824
SCH_LAYER_ID m_layer
Definition sch_item.h:790
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
const wxString & GetFileName() const
Definition sch_screen.h:153
size_t BaseHash() const override
Return type-id of the Base class.
Definition sch_sheet.cpp:67
SCH_SHEET_FIELD_PROPERTY(const wxString &aName)
Definition sch_sheet.cpp:59
wxAny getter(const void *obj) const override
void setter(void *obj, wxAny &v) override
Definition sch_sheet.cpp:70
size_t OwnerHash() const override
Return type-id of the Owner class.
Definition sch_sheet.cpp:66
size_t TypeHash() const override
Return type-id of the property type.
Definition sch_sheet.cpp:68
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool GetExcludedFromBOM() const
bool empty() const
Forwarded method from std::vector.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
wxString GetPageNumber() const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
bool GetExcludedFromSim() const
bool GetExcludedFromBoard() const
bool GetDNP() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Variant information for a schematic sheet.
void InitializeAttributes(const SCH_SHEET &aSheet)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this sheet.
friend SCH_SHEET_PATH
Definition sch_sheet.h:607
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition sch_sheet.h:154
friend class SCH_SHEET_PIN
Definition sch_sheet.h:683
void ClearVariantField(const KIID_PATH &aPath, const wxString &aVariantName, const wxString &aFieldName)
VECTOR2I m_size
Definition sch_sheet.h:700
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:390
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:384
bool getInstance(SCH_SHEET_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void SetExcludedFromSim(bool aExcludeFromSim, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from simulation flag.
void CopyVariant(const KIID_PATH &aPath, const wxString &aSourceVariant, const wxString &aNewVariant)
void SetSize(const VECTOR2I &aSize)
Definition sch_sheet.h:148
void RemoveInstance(const KIID_PATH &aInstancePath)
void SetDNP(bool aDNP, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
bool addInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
bool HasRootInstance() const
Check to see if this sheet has a root sheet instance.
void SyncUuidToScreen()
Take the identity of the screen this sheet owns.
wxString GetClass() const override
Return the class name.
Definition sch_sheet.h:72
wxString getPageNumber(const KIID_PATH &aParentPath) const
Return the sheet page number for aParentPath.
void SetExcludedFromBOM(bool aExcludeFromBOM, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from schematic bill of materials flag.
int GetPenWidth() const override
std::map< SCH_SHEET_PIN *, SCH_NO_CONNECT * > GetNoConnects() const
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
bool IsTopLevelSheet() const
Check if this sheet is a top-level sheet.
SCH_SHEET_PATH findSelf() const
Get the sheetpath of this sheet.
bool GetDNPProp() const
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
bool GetExcludedFromBoardProp() const
Definition sch_sheet.h:481
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
bool GetExcludedFromBOMProp() const
VECTOR2I m_pos
Definition sch_sheet.h:699
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the sheet's fields.
Definition sch_sheet.h:91
KIGFX::COLOR4D m_borderColor
Definition sch_sheet.h:702
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
bool m_excludedFromBOM
Definition sch_sheet.h:695
wxString GetName() const
Definition sch_sheet.h:142
void renumberPins()
Renumber the sheet pins in the sheet.
VECTOR2I GetRotationCenter() const
Rotating around the boundingBox's center can cause walking when the sheetname or filename is longer t...
bool HasHierarchyChanges(const SCH_SHEET &aOther) const
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool operator<(const SCH_ITEM &aItem) const override
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
void SetPositionIgnoringPins(const VECTOR2I &aPosition)
friend SCHEMATIC
Definition sch_sheet.h:609
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool LocatePathOfScreen(SCH_SCREEN *aScreen, SCH_SHEET_PATH *aList)
Search the existing hierarchy for an instance of screen loaded from aFileName.
std::vector< SCH_SHEET_INSTANCE > m_instances
Definition sch_sheet.h:705
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
bool m_excludedFromSim
Definition sch_sheet.h:694
void SetPosition(const VECTOR2I &aPosition) override
wxString GetFieldText(const wxString &aFieldName, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString) const
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition sch_sheet.h:157
int SymbolCount() const
Count our own symbols, without the power symbols.
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.
void SetDNPProp(bool aEnable)
void AddInstance(const SCH_SHEET_INSTANCE &aInstance)
int GetMinWidth(bool aFromLeft) const
Return the minimum width of the sheet based on the widths of the sheet pin text.
bool operator==(const SCH_ITEM &aOther) const override
SCH_SCREEN * m_screen
Definition sch_sheet.h:687
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
std::vector< SCH_FIELD > m_fields
Definition sch_sheet.h:692
void RenameVariant(const KIID_PATH &aPath, const wxString &aOldName, const wxString &aNewName)
VECTOR2I GetSize() const
Definition sch_sheet.h:147
KIGFX::COLOR4D m_backgroundColor
Definition sch_sheet.h:703
void SetExcludedFromBoard(bool aExclude, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear exclude from board netlist flag.
Definition sch_sheet.h:469
void DeleteVariant(const KIID_PATH &aPath, const wxString &aVariantName)
SCH_SHEET(EDA_ITEM *aParent=nullptr, const VECTOR2I &aPos=VECTOR2I(0, 0), VECTOR2I aSize=VECTOR2I(schIUScale.MilsToIU(MIN_SHEET_WIDTH), schIUScale.MilsToIU(MIN_SHEET_HEIGHT)))
void SetName(const wxString &aName)
Definition sch_sheet.h:143
int CountSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
int GetNextFieldOrdinal() const
Return the next ordinal for a user field for this sheet.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
void SetExcludedFromSimProp(bool aEnable)
VECTOR2I GetPosition() const override
Definition sch_sheet.h:504
const BOX2I GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
bool HasPin(const wxString &aName) const
Check if the sheet already has a sheet pin named aName.
static int ComparePageNum(const wxString &aPageNumberA, const wxString &aPageNumberB)
Compare page numbers of schematic sheets.
std::vector< PROPERTY_BASE * > GetDynamicProperties() const override
Return dynamically-computed properties specific to this object instance (e.g.
void SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
int CountActiveSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
SCH_SHEET & operator=(const SCH_ITEM &aSheet)
bool HasPageNumberChanges(const SCH_SHEET &aOther) const
Check if the instance data of this sheet has any changes compared to aOther.
const SCH_SHEET_INSTANCE & GetRootInstance() const
Return the root sheet instance data.
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
bool m_excludedFromBoard
Definition sch_sheet.h:696
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
KIGFX::COLOR4D GetBorderColor() const
Definition sch_sheet.h:153
std::vector< SCH_SHEET_PIN * > m_pins
Definition sch_sheet.h:691
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...
void SetBorderWidth(int aWidth)
Definition sch_sheet.h:151
std::map< wxString, std::unique_ptr< SCH_SHEET_FIELD_PROPERTY > > m_dynamicPropertyCache
Definition sch_sheet.h:707
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a @aField to the list of fields.
void setPageNumber(const KIID_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
bool IsVirtualRootSheet() const
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
int GetMinHeight(bool aFromTop) const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flags.
bool GetExcludedFromSimProp() const
void SetExcludedFromBoardProp(bool aExclude)
Definition sch_sheet.h:482
int m_borderWidth
Definition sch_sheet.h:701
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos, const SCH_SHEET_PATH *aPath=nullptr) override
Test the schematic item to aItemList to check if it's dangling state has changed.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition sch_sheet.h:475
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
int GetBorderWidth() const
Definition sch_sheet.h:150
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
bool m_DNP
Definition sch_sheet.h:697
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:241
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
void SetExcludedFromBOMProp(bool aEnable)
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
void AddVariant(const SCH_SHEET_PATH &aInstance, const SCH_SHEET_VARIANT &aVariant)
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:519
bool IsVerticalOrientation() const
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Test if aPosition is inside or on the boundary of this item.
KIGFX::COLOR4D GetBackgroundColor() const
Definition sch_sheet.h:156
Schematic symbol object.
Definition sch_symbol.h:75
bool IsPower() const override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
wxString m_Name
bool m_ExcludedFromBOM
std::map< wxString, wxString > m_Fields
bool m_ExcludedFromSim
@ FOR_GUI
Definition common.h:89
@ INTERNAL
Definition common.h:92
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:424
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:419
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:418
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:427
@ NO_FILL
Definition eda_fill.h:30
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
RECURSE_MODE
Definition eda_item.h:50
INSPECT_RESULT
Definition eda_item.h:44
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:91
a few functions useful in geometry calculations.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
KIID niluuid(0)
@ LAYER_DANGLING
Definition layer_ids.h:499
@ LAYER_SHEETNAME
Definition layer_ids.h:494
@ LAYER_SHEET_BACKGROUND
Definition layer_ids.h:507
@ LAYER_HIERLABEL
Definition layer_ids.h:479
@ LAYER_SHEETFIELDS
Definition layer_ids.h:496
@ LAYER_SHEET
Definition layer_ids.h:493
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:517
@ LAYER_SHEETFILENAME
Definition layer_ids.h:495
@ LAYER_DNP_MARKER
Definition layer_ids.h:500
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:41
Message panel definition file.
bool BoxHitTest(const VECTOR2I &aHitPoint, const BOX2I &aHittee, int aAccuracy)
Perform a point-to-box hit test.
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
KICOMMON_API void PackColor(types::Color &aOutput, const KIGFX::COLOR4D &aInput)
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API KIGFX::COLOR4D UnpackColor(const types::Color &aInput)
KICOMMON_API void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackDistance(types::Distance &aOutput, int aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
#define _HKI(x)
Definition page_info.cpp:40
see class PGM_BASE
#define TYPE_HASH(x)
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
Definition sch_field.h:393
int NextFieldOrdinal(const std::vector< SCH_FIELD > &aFields)
Definition sch_field.h:382
AUTOPLACE_ALGO
Definition sch_item.h:68
@ AUTOPLACE_MANUAL
Definition sch_item.h:71
@ AUTOPLACE_NONE
Definition sch_item.h:69
@ AUTOPLACE_AUTO
Definition sch_item.h:70
int bumpToNextGrid(const int aVal, const int aDirection)
static struct SCH_SHEET_DESC _SCH_SHEET_DESC
#define MIN_SHEET_HEIGHT
Definition sch_sheet.h:41
#define MIN_SHEET_WIDTH
Definition sch_sheet.h:40
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
std::vector< FAB_LAYER_COLOR > dummy
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
bool m_PDFPropertyPopups
Definition sch_plotter.h:62
bool m_PDFHierarchicalLinks
Definition sch_plotter.h:63
A simple container for sheet instance information.
std::map< wxString, SCH_SHEET_VARIANT > m_Variants
A list of sheet variants.
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ TRANSLATED
std::string path
KIBIS_PIN * pin
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
int delta
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_TOP
wxLogTrace helper definitions.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ SCH_NO_CONNECT_T
Definition typeinfo.h:156
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_LOCATE_ANY_T
Definition typeinfo.h:195
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_SHEET_PIN_T
Definition typeinfo.h:170
wxString GetFieldValidationErrorMessage(FIELD_T aFieldId, const wxString &aValue)
Return the error message if aValue is invalid for aFieldId.
Custom text control validator definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682