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