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