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( SCH_FIELD* aField, const wxString& aFieldName, const wxString& aFieldText,
692 const SCH_SHEET_PATH* aPath, const wxString& aVariantName )
693{
694 switch( aField->GetId() )
695 {
697 {
698 // File names are stored using unix separators.
699 wxString tmp = aFieldText;
700 tmp.Replace( wxT( "\\" ), wxT( "/" ) );
702 break;
703 }
704
706 aField->SetText( aFieldText );
707 break;
708
709 default:
710 {
711 wxString defaultText = aField->GetText( aPath );
712
713 if( aVariantName.IsEmpty() )
714 {
715 if( aFieldText != defaultText )
716 aField->SetText( aFieldText );
717 }
718 else
719 {
720 SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
721
722 wxCHECK( instance, /* void */ );
723
724 bool changed = false;
725
726 if( instance->m_Variants.contains( aVariantName ) )
727 {
728 auto& fields = instance->m_Variants[aVariantName].m_Fields;
729
730 if( aFieldText != defaultText )
731 {
732 auto [entry, inserted] = fields.try_emplace( aFieldName, aFieldText );
733 changed = inserted || std::exchange( entry->second, aFieldText ) != aFieldText;
734 }
735 else
736 {
737 changed = fields.erase( aFieldName ) != 0;
738 }
739 }
740 else if( aFieldText != defaultText )
741 {
742 SCH_SHEET_VARIANT newVariant( aVariantName );
743
744 newVariant.InitializeAttributes( *this );
745 newVariant.m_Fields[aFieldName] = aFieldText;
746 instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
747 changed = true;
748 }
749
750 if( changed )
752 }
753
754 break;
755 }
756 }
757}
758
759
760void SCH_SHEET::SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath,
761 const wxString& aVariantName )
762{
763 wxCHECK_MSG( !aFieldName.IsEmpty(), /* void */, wxT( "Can't set text on a field with no name!" ) );
764
765 SCH_FIELD* field = GetField( aFieldName );
766
767 wxCHECK_MSG( field, /* void */, wxT( "Can't set text on a field not yet added to the sheet!" ) );
768
769 SetFieldText( field, aFieldName, aFieldText, aPath, aVariantName );
770}
771
772
773wxString SCH_SHEET::GetFieldText( const SCH_FIELD* aField, const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
774 const wxString& aVariantName ) const
775{
776 switch( aField->GetId() )
777 {
780 return aField->GetText();
781 break;
782
783 default:
784 if( aVariantName.IsEmpty() )
785 {
786 return aField->GetText();
787 }
788 else
789 {
790 const SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
791
792 if( instance->m_Variants.contains( aVariantName )
793 && instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
794 {
795 return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
796 }
797 }
798
799 break;
800 }
801
802 return aField->GetText();
803}
804
805
806wxString SCH_SHEET::GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
807 const wxString& aVariantName ) const
808{
809 wxCHECK_MSG( !aFieldName.IsEmpty(), wxEmptyString, wxT( "Can't get text from a field with no name!" ) );
810
811 const SCH_FIELD* field = GetField( aFieldName );
812
813 wxCHECK_MSG( field, wxEmptyString, wxT( "Can't get text from a field not yet added to the sheet!" ) );
814
815 return GetFieldText( field, aFieldName, aPath, aVariantName );
816}
817
818
820{
821 wxASSERT( aSheetPin != nullptr );
822 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
823
824 if( SCH_SCREEN* screen = GetParentScreen() )
825 screen->BumpConnectivityRevision();
826
827 aSheetPin->SetParent( this );
828 m_pins.push_back( aSheetPin );
829 renumberPins();
830}
831
832
833void SCH_SHEET::RemovePin( const SCH_SHEET_PIN* aSheetPin )
834{
835 wxASSERT( aSheetPin != nullptr );
836 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
837
838 for( auto i = m_pins.begin(); i < m_pins.end(); ++i )
839 {
840 if( *i == aSheetPin )
841 {
842 if( SCH_SCREEN* screen = GetParentScreen() )
843 screen->BumpConnectivityRevision();
844
845 m_pins.erase( i );
846 delete aSheetPin;
847
848 renumberPins();
849 return;
850 }
851 }
852}
853
854
855bool SCH_SHEET::HasPin( const wxString& aName ) const
856{
857 for( SCH_SHEET_PIN* pin : m_pins )
858 {
859 if( pin->GetText().Cmp( aName ) == 0 )
860 return true;
861 }
862
863 return false;
864}
865
866
867bool SCH_SHEET::doIsConnected( const VECTOR2I& aPosition ) const
868{
869 for( SCH_SHEET_PIN* sheetPin : m_pins )
870 {
871 if( sheetPin->GetPosition() == aPosition )
872 return true;
873 }
874
875 return false;
876}
877
878
880{
881 int leftRight = 0;
882 int topBottom = 0;
883
884 for( SCH_SHEET_PIN* pin : m_pins )
885 {
886 switch( pin->GetSide() )
887 {
888 case SHEET_SIDE::LEFT: leftRight++; break;
889 case SHEET_SIDE::RIGHT: leftRight++; break;
890 case SHEET_SIDE::TOP: topBottom++; break;
891 case SHEET_SIDE::BOTTOM: topBottom++; break;
892 default: break;
893 }
894 }
895
896 return topBottom > 0 && leftRight == 0;
897}
898
899
901{
902 for( SCH_SHEET_PIN* pin : m_pins )
903 {
904 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
905 const SCH_HIERLABEL* HLabel = nullptr;
906
907 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
908 {
909 if( !pin->GetText().Cmp( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
910 {
911 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
912 break;
913 }
914 }
915
916 if( HLabel == nullptr ) // Corresponding hierarchical label not found.
917 return true;
918 }
919
920 return false;
921}
922
923
924int bumpToNextGrid( const int aVal, const int aDirection )
925{
926 constexpr int gridSize = schIUScale.MilsToIU( 50 );
927
928 int base = aVal / gridSize;
929 int excess = abs( aVal % gridSize );
930
931 // Use floor division for negative coordinates between grid lines.
932 if( aVal < 0 && excess > 0 )
933 --base;
934
935 if( aDirection > 0 )
936 {
937 return ( base + 1 ) * gridSize;
938 }
939 else if( excess > 0 )
940 {
941 return ( base ) * gridSize;
942 }
943 else
944 {
945 return ( base - 1 ) * gridSize;
946 }
947}
948
949
950int SCH_SHEET::GetMinWidth( bool aFromLeft ) const
951{
952 int pinsLeft = m_pos.x + m_size.x;
953 int pinsRight = m_pos.x;
954
955 for( SCH_SHEET_PIN* pin : m_pins)
956 {
957 SHEET_SIDE edge = pin->GetSide();
958
959 if( edge == SHEET_SIDE::TOP || edge == SHEET_SIDE::BOTTOM )
960 {
961 BOX2I pinRect = pin->GetBoundingBox();
962
963 pinsLeft = std::min( pinsLeft, pinRect.GetLeft() );
964 pinsRight = std::max( pinsRight, pinRect.GetRight() );
965 }
966 }
967
968 pinsLeft = bumpToNextGrid( pinsLeft, -1 );
969 pinsRight = bumpToNextGrid( pinsRight, 1 );
970
971 int pinMinWidth;
972
973 if( pinsLeft >= pinsRight )
974 pinMinWidth = 0;
975 else if( aFromLeft )
976 pinMinWidth = pinsRight - m_pos.x;
977 else
978 pinMinWidth = m_pos.x + m_size.x - pinsLeft;
979
980 return std::max( pinMinWidth, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
981}
982
983
984int SCH_SHEET::GetMinHeight( bool aFromTop ) const
985{
986 int pinsTop = m_pos.y + m_size.y;
987 int pinsBottom = m_pos.y;
988
989 for( SCH_SHEET_PIN* pin : m_pins )
990 {
991 SHEET_SIDE edge = pin->GetSide();
992
993 if( edge == SHEET_SIDE::RIGHT || edge == SHEET_SIDE::LEFT )
994 {
995 BOX2I pinRect = pin->GetBoundingBox();
996
997 pinsTop = std::min( pinsTop, pinRect.GetTop() );
998 pinsBottom = std::max( pinsBottom, pinRect.GetBottom() );
999 }
1000 }
1001
1002 pinsTop = bumpToNextGrid( pinsTop, -1 );
1003 pinsBottom = bumpToNextGrid( pinsBottom, 1 );
1004
1005 int pinMinHeight;
1006
1007 if( pinsTop >= pinsBottom )
1008 pinMinHeight = 0;
1009 else if( aFromTop )
1010 pinMinHeight = pinsBottom - m_pos.y;
1011 else
1012 pinMinHeight = m_pos.y + m_size.y - pinsTop;
1013
1014 return std::max( pinMinHeight, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
1015}
1016
1017
1019{
1020 if( SCH_SCREEN* screen = GetParentScreen() )
1021 screen->BumpConnectivityRevision();
1022
1023 std::vector<SCH_SHEET_PIN*> pins = m_pins;
1024
1025 m_pins.clear();
1026
1027 for( SCH_SHEET_PIN* pin : pins )
1028 {
1029 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
1030 const SCH_HIERLABEL* HLabel = nullptr;
1031
1032 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
1033 {
1034 if( pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) == 0 )
1035 {
1036 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
1037 break;
1038 }
1039 }
1040
1041 if( HLabel )
1042 m_pins.push_back( pin );
1043 else
1044 delete pin;
1045 }
1046}
1047
1048
1050{
1051 for( SCH_SHEET_PIN* pin : m_pins )
1052 {
1053 if( pin->HitTest( aPosition ) )
1054 return pin;
1055 }
1056
1057 return nullptr;
1058}
1059
1060
1062{
1063 if( GetBorderWidth() > 0 )
1064 return GetBorderWidth();
1065
1066 if( Schematic() )
1068
1069 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
1070}
1071
1072
1074{
1075 SCH_FIELD* sheetNameField = GetField( FIELD_T::SHEET_NAME );
1076 VECTOR2I textSize = sheetNameField->GetTextSize();
1077 int borderMargin = KiROUND( GetPenWidth() / 2.0 ) + 4;
1078 int margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.5 );
1079
1080 if( IsVerticalOrientation() )
1081 {
1082 sheetNameField->SetTextPos( m_pos + VECTOR2I( -margin, m_size.y ) );
1083 sheetNameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1084 sheetNameField->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
1085 sheetNameField->SetTextAngle( ANGLE_VERTICAL );
1086 }
1087 else
1088 {
1089 sheetNameField->SetTextPos( m_pos + VECTOR2I( 0, -margin ) );
1090 sheetNameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1091 sheetNameField->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
1092 sheetNameField->SetTextAngle( ANGLE_HORIZONTAL );
1093 }
1094
1095 SCH_FIELD* sheetFilenameField = GetField( FIELD_T::SHEET_FILENAME );
1096
1097 textSize = sheetFilenameField->GetTextSize();
1098 margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.4 );
1099
1100 if( IsVerticalOrientation() )
1101 {
1102 sheetFilenameField->SetTextPos( m_pos + VECTOR2I( m_size.x + margin, m_size.y ) );
1103 sheetFilenameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1104 sheetFilenameField->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
1105 sheetFilenameField->SetTextAngle( ANGLE_VERTICAL );
1106 }
1107 else
1108 {
1109 sheetFilenameField->SetTextPos( m_pos + VECTOR2I( 0, m_size.y + margin ) );
1110 sheetFilenameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1111 sheetFilenameField->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
1112 sheetFilenameField->SetTextAngle( ANGLE_HORIZONTAL );
1113 }
1114
1115 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
1116 m_fieldsAutoplaced = aAlgo;
1117}
1118
1119
1120std::vector<int> SCH_SHEET::ViewGetLayers() const
1121{
1122 // Sheet pins are drawn by their parent sheet, so the parent needs to draw to LAYER_DANGLING
1125}
1126
1127
1129{
1130 VECTOR2I end;
1131 BOX2I box( m_pos, m_size );
1132 int lineWidth = GetPenWidth();
1133 int textLength = 0;
1134
1135 // Calculate bounding box X size:
1136 end.x = std::max( m_size.x, textLength );
1137
1138 // Calculate bounding box pos:
1139 end.y = m_size.y;
1140 end += m_pos;
1141
1142 box.SetEnd( end );
1143 box.Inflate( lineWidth / 2 );
1144
1145 return box;
1146}
1147
1148
1150{
1151 BOX2I bbox = GetBodyBoundingBox();
1152
1153 for( const SCH_FIELD& field : m_fields )
1154 if( field.IsVisible() )
1155 bbox.Merge( field.GetBoundingBox() );
1156
1157 for( const SCH_SHEET_PIN* pin : m_pins )
1158 bbox.Merge( pin->GetBoundingBox() );
1159
1160 return bbox;
1161}
1162
1163
1165{
1166 BOX2I box( m_pos, m_size );
1167 return box.GetCenter();
1168}
1169
1170
1172{
1173 int n = 0;
1174
1175 if( m_screen )
1176 {
1177 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SYMBOL_T ) )
1178 {
1179 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
1180
1181 if( !symbol->IsPower() )
1182 n++;
1183 }
1184
1185 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1186 n += static_cast<const SCH_SHEET*>( aItem )->SymbolCount();
1187 }
1188
1189 return n;
1190}
1191
1192
1193bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
1194{
1195 if( m_screen )
1196 {
1197 // Only check the root sheet once and don't recurse.
1198 if( !GetParent() )
1199 {
1200 if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
1201 {
1202 *aScreen = m_screen;
1203 return true;
1204 }
1205 }
1206
1207 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1208 {
1209 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
1210 SCH_SCREEN* screen = sheet->m_screen;
1211
1212 // Must use the screen's path (which is always absolute) rather than the
1213 // sheet's (which could be relative).
1214 if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
1215 {
1216 *aScreen = screen;
1217 return true;
1218 }
1219
1220 if( sheet->SearchHierarchy( aFilename, aScreen ) )
1221 return true;
1222 }
1223 }
1224
1225 return false;
1226}
1227
1228
1230{
1231 if( m_screen )
1232 {
1233 aList->push_back( this );
1234
1235 if( m_screen == aScreen )
1236 return true;
1237
1238 for( EDA_ITEM* item : m_screen->Items().OfType( SCH_SHEET_T ) )
1239 {
1240 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1241
1242 if( sheet->LocatePathOfScreen( aScreen, aList ) )
1243 return true;
1244 }
1245
1246 aList->pop_back();
1247 }
1248
1249 return false;
1250}
1251
1252
1253int SCH_SHEET::CountSheets( const wxString& aFilename ) const
1254{
1255 int count = 0;
1256
1257 if( m_screen )
1258 {
1259 if( m_screen->GetFileName().Cmp( aFilename ) == 0 )
1260 count++;
1261
1262 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1263 count += static_cast<SCH_SHEET*>( aItem )->CountSheets( aFilename );
1264 }
1265
1266 return count;
1267}
1268
1269
1271{
1272 int count = 1; //1 = this!!
1273
1274 if( m_screen )
1275 {
1276 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
1277 count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
1278 }
1279
1280 return count;
1281}
1282
1283
1285{
1286 int count = CountSheets();
1287
1288 if( IsVirtualRootSheet() )
1289 count--;
1290
1291 return count;
1292}
1293
1294
1295void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1296{
1297 // Don't use GetShownText(); we want to see the variable references here
1298 aList.emplace_back( _( "Sheet Name" ), KIUI::EllipsizeStatusText( aFrame, GetName() ) );
1299
1300 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
1301 SCH_SHEET_PATH* currentSheet = nullptr;
1302 wxString currentVariant;
1303
1304 if( schframe )
1305 {
1306 SCH_SHEET_PATH path = schframe->GetCurrentSheet();
1307 path.push_back( this );
1308 currentSheet = &schframe->GetCurrentSheet();
1309 currentVariant = Schematic() ? Schematic()->GetCurrentVariant() : wxString();
1310
1311 aList.emplace_back( _( "Hierarchical Path" ), path.PathHumanReadable( false, true ) );
1312 }
1313
1314 // Don't use GetShownText(); we want to see the variable references here
1315 aList.emplace_back( _( "File Name" ), KIUI::EllipsizeStatusText( aFrame, GetFileName() ) );
1316
1317 wxArrayString msgs;
1318 wxString msg;
1319
1320 if( GetExcludedFromSim() )
1321 msgs.Add( _( "Simulation" ) );
1322
1323 if( GetExcludedFromBOM() )
1324 msgs.Add( _( "BOM" ) );
1325
1326 if( GetExcludedFromBoard() )
1327 msgs.Add( _( "Board" ) );
1328
1329 if( GetDNP( currentSheet, currentVariant ) )
1330 msgs.Add( _( "DNP" ) );
1331
1332 msg = wxJoin( msgs, '|' );
1333 msg.Replace( '|', wxS( ", " ) );
1334
1335 if( !msg.empty() )
1336 aList.emplace_back( _( "Exclude from" ), msg );
1337}
1338
1339
1340std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> SCH_SHEET::GetNoConnects() const
1341{
1342 std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> noConnects;
1343
1344 SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( GetParent() );
1345
1346 // A top level sheet is parented to the root sheet rather than to the root screen, so reach
1347 // the screen that holds this sheet through the parent sheet instead
1348 if( !screen )
1349 {
1350 if( SCH_SHEET* parentSheet = dynamic_cast<SCH_SHEET*>( GetParent() ) )
1351 screen = parentSheet->GetScreen();
1352 }
1353
1354 if( screen )
1355 {
1356 for( SCH_SHEET_PIN* sheetPin : m_pins )
1357 {
1358 for( SCH_ITEM* noConnect : screen->Items().Overlapping( SCH_NO_CONNECT_T, sheetPin->GetTextPos() ) )
1359 noConnects[sheetPin] = static_cast<SCH_NO_CONNECT*>( noConnect );
1360 }
1361 }
1362
1363 return noConnects;
1364}
1365
1366
1368{
1369 VECTOR2I delta = aPosition - m_pos;
1370
1371 m_pos = aPosition;
1372
1373 for( SCH_FIELD& field : m_fields )
1374 field.Move( delta );
1375}
1376
1377
1378void SCH_SHEET::Move( const VECTOR2I& aMoveVector )
1379{
1380 m_pos += aMoveVector;
1381
1382 for( SCH_SHEET_PIN* pin : m_pins )
1383 pin->Move( aMoveVector );
1384
1385 for( SCH_FIELD& field : m_fields )
1386 field.Move( aMoveVector );
1387}
1388
1389
1390void SCH_SHEET::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
1391{
1392 VECTOR2I prev = m_pos;
1393
1394 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
1395 RotatePoint( &m_size.x, &m_size.y, aRotateCCW ? ANGLE_90 : ANGLE_270 );
1396
1397 if( m_size.x < 0 )
1398 {
1399 m_pos.x += m_size.x;
1400 m_size.x = -m_size.x;
1401 }
1402
1403 if( m_size.y < 0 )
1404 {
1405 m_pos.y += m_size.y;
1406 m_size.y = -m_size.y;
1407 }
1408
1409 // Pins must be rotated first as that's how we determine vertical vs horizontal
1410 // orientation for auto-placement
1411 for( SCH_SHEET_PIN* sheetPin : m_pins )
1412 sheetPin->Rotate( aCenter, aRotateCCW );
1413
1415 {
1417 }
1418 else
1419 {
1420 // Move the fields to the new position because the parent itself has moved.
1421 for( SCH_FIELD& field : m_fields )
1422 {
1423 VECTOR2I pos = field.GetTextPos();
1424 pos.x -= prev.x - m_pos.x;
1425 pos.y -= prev.y - m_pos.y;
1426 field.SetTextPos( pos );
1427 }
1428 }
1429}
1430
1431
1433{
1434 int dy = m_pos.y;
1435
1436 MIRROR( m_pos.y, aCenter );
1437 m_pos.y -= m_size.y;
1438 dy -= m_pos.y; // 0,dy is the move vector for this transform
1439
1440 for( SCH_SHEET_PIN* sheetPin : m_pins )
1441 sheetPin->MirrorVertically( aCenter );
1442
1443 for( SCH_FIELD& field : m_fields )
1444 {
1445 VECTOR2I pos = field.GetTextPos();
1446 pos.y -= dy;
1447 field.SetTextPos( pos );
1448 }
1449}
1450
1451
1453{
1454 int dx = m_pos.x;
1455
1456 MIRROR( m_pos.x, aCenter );
1457 m_pos.x -= m_size.x;
1458 dx -= m_pos.x; // dx,0 is the move vector for this transform
1459
1460 for( SCH_SHEET_PIN* sheetPin : m_pins )
1461 sheetPin->MirrorHorizontally( aCenter );
1462
1463 for( SCH_FIELD& field : m_fields )
1464 {
1465 VECTOR2I pos = field.GetTextPos();
1466 pos.x -= dx;
1467 field.SetTextPos( pos );
1468 }
1469}
1470
1471
1472void SCH_SHEET::SetPosition( const VECTOR2I& aPosition )
1473{
1474 // Remember the sheet and all pin sheet positions must be
1475 // modified. So use Move function to do that.
1476 Move( aPosition - m_pos );
1477}
1478
1479
1480void SCH_SHEET::Resize( const VECTOR2I& aSize )
1481{
1482 if( aSize == m_size )
1483 return;
1484
1485 m_size = aSize;
1486
1487 // Move the fields if we're in autoplace mode
1490
1491 // Move the sheet labels according to the new sheet size.
1492 for( SCH_SHEET_PIN* sheetPin : m_pins )
1493 sheetPin->ConstrainOnEdge( sheetPin->GetPosition(), false );
1494}
1495
1496
1497bool SCH_SHEET::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
1498{
1499 // Sheets are searchable via the child field and pin item text.
1500 return false;
1501}
1502
1503
1505{
1506 int id = 2;
1507
1508 for( SCH_SHEET_PIN* pin : m_pins )
1509 {
1510 pin->SetNumber( id );
1511 id++;
1512 }
1513}
1514
1515
1517{
1518 wxCHECK_MSG( Schematic(), SCH_SHEET_PATH(), "Can't call findSelf without a schematic" );
1519
1520 SCH_SHEET_PATH sheetPath = Schematic()->CurrentSheet();
1521
1522 while( !sheetPath.empty() && sheetPath.Last() != this )
1523 sheetPath.pop_back();
1524
1525 if( sheetPath.empty() )
1526 {
1527 // If we weren't in the hierarchy, then we must be a child of the current sheet.
1528 sheetPath = Schematic()->CurrentSheet();
1529 sheetPath.push_back( const_cast<SCH_SHEET*>( this ) );
1530 }
1531
1532 return sheetPath;
1533}
1534
1535
1536void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1537{
1538 for( SCH_SHEET_PIN* sheetPin : m_pins )
1539 {
1540 wxCHECK2_MSG( sheetPin->Type() == SCH_SHEET_PIN_T, continue,
1541 wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) );
1542
1543 sheetPin->GetEndPoints( aItemList );
1544 }
1545}
1546
1547
1548bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
1549 std::vector<DANGLING_END_ITEM>& aItemListByPos,
1550 const SCH_SHEET_PATH* aPath )
1551{
1552 bool changed = false;
1553
1554 for( SCH_SHEET_PIN* sheetPin : m_pins )
1555 changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
1556
1557 return changed;
1558}
1559
1560
1561bool SCH_SHEET::HasConnectivityChanges( const SCH_ITEM* aItem, const SCH_SHEET_PATH* aInstance ) const
1562{
1563 // Do not compare to ourself.
1564 if( aItem == this )
1565 return false;
1566
1567 const SCH_SHEET* sheet = dynamic_cast<const SCH_SHEET*>( aItem );
1568
1569 // Don't compare against a different SCH_ITEM.
1570 wxCHECK( sheet, false );
1571
1572 if( GetPosition() != sheet->GetPosition() )
1573 return true;
1574
1575 // Technically this cannot happen because undo/redo does not support reloading sheet
1576 // file association changes. This was just added so that it doesn't get missed should
1577 // we ever fix the undo/redo issue.
1578 if( ( GetFileName() != sheet->GetFileName() ) || ( GetName() != sheet->GetName() ) )
1579 return true;
1580
1581 if( m_pins.size() != sheet->m_pins.size() )
1582 return true;
1583
1584 for( size_t i = 0; i < m_pins.size(); i++ )
1585 {
1586 if( m_pins[i]->HasConnectivityChanges( sheet->m_pins[i] ) )
1587 return true;
1588 }
1589
1590 return false;
1591}
1592
1593
1594std::vector<VECTOR2I> SCH_SHEET::GetConnectionPoints() const
1595{
1596 std::vector<VECTOR2I> retval;
1597
1598 for( SCH_SHEET_PIN* sheetPin : m_pins )
1599 retval.push_back( sheetPin->GetPosition() );
1600
1601 return retval;
1602}
1603
1604
1605INSPECT_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData, const std::vector<KICAD_T>& aScanTypes )
1606{
1607 for( KICAD_T scanType : aScanTypes )
1608 {
1609 // If caller wants to inspect my type
1610 if( scanType == SCH_LOCATE_ANY_T || scanType == Type() )
1611 {
1612 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1613 return INSPECT_RESULT::QUIT;
1614 }
1615
1616 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1617 {
1618 // Test the sheet fields.
1619 for( SCH_FIELD& field : m_fields )
1620 {
1621 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1622 return INSPECT_RESULT::QUIT;
1623 }
1624 }
1625
1626 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_SHEET_PIN_T )
1627 {
1628 // Test the sheet labels.
1629 for( SCH_SHEET_PIN* sheetPin : m_pins )
1630 {
1631 if( INSPECT_RESULT::QUIT == aInspector( sheetPin, this ) )
1632 return INSPECT_RESULT::QUIT;
1633 }
1634 }
1635 }
1636
1638}
1639
1640
1641void SCH_SHEET::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1642{
1643 for( SCH_FIELD& field : m_fields )
1644 aFunction( &field );
1645
1646 for( SCH_SHEET_PIN* pin : m_pins )
1647 aFunction( pin );
1648}
1649
1650
1651wxString SCH_SHEET::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1652{
1653 const SCH_FIELD* sheetnameField = GetField( FIELD_T::SHEET_NAME );
1654
1655 return wxString::Format( _( "Hierarchical Sheet '%s'" ),
1656 aFull ? sheetnameField->GetShownText( FOR_GUI )
1657 : KIUI::EllipsizeMenuText( sheetnameField->GetText() ) );
1658}
1659
1660
1665
1666
1667bool SCH_SHEET::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1668{
1669 BOX2I rect = GetBodyBoundingBox();
1670
1671 rect.Inflate( aAccuracy );
1672
1673 return rect.Contains( aPosition );
1674}
1675
1676
1677bool SCH_SHEET::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1678{
1679 BOX2I rect = aRect;
1680
1681 rect.Inflate( aAccuracy );
1682
1683 if( aContained )
1684 return rect.Contains( GetBodyBoundingBox() );
1685
1686 return rect.Intersects( GetBodyBoundingBox() );
1687}
1688
1689
1690bool SCH_SHEET::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
1691{
1692 return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
1693}
1694
1695
1696void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1697 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1698{
1699 if( aBackground && !aPlotter->GetColorMode() )
1700 return;
1701
1702 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1703 COLOR4D borderColor = GetBorderColor();
1704 COLOR4D backgroundColor = GetBackgroundColor();
1705 SCH_SHEET_PATH instance;
1706 wxString variantName;
1707
1708 if( Schematic() )
1709 {
1710 instance = Schematic()->CurrentSheet();
1711 variantName = Schematic()->GetCurrentVariant();
1712 }
1713
1714 bool dnp = GetDNP( &instance, variantName );
1715
1716 if( renderSettings->m_OverrideItemColors || borderColor == COLOR4D::UNSPECIFIED )
1717 borderColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET );
1718
1719 if( renderSettings->m_OverrideItemColors || backgroundColor == COLOR4D::UNSPECIFIED )
1720 backgroundColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET_BACKGROUND );
1721
1722 if( borderColor.m_text && Schematic() )
1723 borderColor = COLOR4D( ResolveText( *borderColor.m_text, &Schematic()->CurrentSheet() ) );
1724
1725 if( backgroundColor.m_text && Schematic() )
1726 backgroundColor = COLOR4D( ResolveText( *backgroundColor.m_text, &Schematic()->CurrentSheet() ) );
1727
1728 if( aDimmed || dnp )
1729 {
1730 borderColor.Desaturate();
1731 borderColor = borderColor.Mix( backgroundColor, 0.5f );
1732 }
1733
1734 if( aBackground && backgroundColor.a > 0.0 )
1735 {
1736 aPlotter->SetColor( backgroundColor );
1737 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::FILLED_SHAPE, 1, 0 );
1738 }
1739 else
1740 {
1741 aPlotter->SetColor( borderColor );
1742
1743 int penWidth = GetEffectivePenWidth( getRenderSettings( aPlotter ) );
1744 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::NO_FILL, penWidth, 0 );
1745 }
1746
1747 // Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
1748 if( aPlotOpts.m_PDFHierarchicalLinks )
1749 {
1750 aPlotter->HyperlinkBox( GetBoundingBox(), EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1751 }
1752 else if( aPlotOpts.m_PDFPropertyPopups )
1753 {
1754 std::vector<wxString> properties;
1755
1756 properties.emplace_back( EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1757
1758 for( const SCH_FIELD& field : GetFields() )
1759 {
1760 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1761 field.GetName(),
1762 field.GetShownText( FOR_GUI ) ) );
1763 }
1764
1765 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
1766 }
1767
1768 // Plot sheet pins
1769 for( SCH_SHEET_PIN* sheetPin : m_pins )
1770 sheetPin->Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed || dnp );
1771
1772 // Plot the fields
1773 for( SCH_FIELD& field : m_fields )
1774 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed || dnp );
1775
1776 if( dnp && renderSettings->m_ShowDNPMarkers )
1777 {
1778 BOX2I bbox = GetBodyBoundingBox();
1779 BOX2I pins = GetBoundingBox();
1780 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
1781 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
1782 int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
1783
1784 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
1785 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
1786 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
1787
1788 aPlotter->SetColor( renderSettings->GetLayerColor( LAYER_DNP_MARKER ) );
1789
1790 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, nullptr );
1791
1792 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
1793 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
1794 strokeWidth, nullptr );
1795 }
1796}
1797
1798
1800{
1801 wxCHECK_MSG( Type() == aItem.Type(), *this,
1802 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) + GetClass() );
1803
1804 if( &aItem != this )
1805 {
1806 SCH_ITEM::operator=( aItem );
1807
1808 SCH_SHEET* sheet = (SCH_SHEET*) &aItem;
1809
1810 m_pos = sheet->m_pos;
1811 m_size = sheet->m_size;
1812 m_fields = sheet->m_fields;
1813
1814 // Reparent fields after assignment to new sheet.
1815 for( SCH_FIELD& field : m_fields )
1816 field.SetParent( this );
1817
1818 for( SCH_SHEET_PIN* pin : m_pins )
1819 delete pin;
1820
1821 m_pins.clear();
1822
1823 for( SCH_SHEET_PIN* pin : sheet->m_pins )
1824 {
1825 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
1826 m_pins.back()->SetParent( this );
1827 }
1828
1829 m_instances.clear();
1830
1831 for( const SCH_SHEET_INSTANCE& instance : sheet->m_instances )
1832 m_instances.emplace_back( instance );
1833 }
1834
1835 return *this;
1836}
1837
1838
1839bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
1840{
1841 if( Type() != aItem.Type() )
1842 return Type() < aItem.Type();
1843
1844 const SCH_SHEET* otherSheet = static_cast<const SCH_SHEET*>( &aItem );
1845
1846 if( GetName() != otherSheet->GetName() )
1847 return GetName() < otherSheet->GetName();
1848
1849 if( GetFileName() != otherSheet->GetFileName() )
1850 return GetFileName() < otherSheet->GetFileName();
1851
1852 return false;
1853}
1854
1855
1856void SCH_SHEET::RemoveInstance( const KIID_PATH& aInstancePath )
1857{
1858 // Search for an existing path and remove it if found (should not occur)
1859 // (search from back to avoid invalidating iterator on remove)
1860 for( int ii = (int) m_instances.size() - 1; ii >= 0; --ii )
1861 {
1862 if( m_instances[ii].m_Path == aInstancePath )
1863 {
1864 wxLogTrace( traceSchSheetPaths, "Removing sheet instance:\n"
1865 " sheet path %s\n"
1866 " page %s, from project %s.",
1867 aInstancePath.AsString(),
1868 m_instances[ii].m_PageNumber,
1869 m_instances[ii].m_ProjectName );
1870
1871 m_instances.erase( m_instances.begin() + ii );
1872 }
1873 }
1874}
1875
1876
1878{
1879 SCH_SHEET_INSTANCE oldInstance;
1880
1881 if( getInstance( oldInstance, aInstance.m_Path ) )
1882 RemoveInstance( aInstance.m_Path );
1883
1884 m_instances.emplace_back( aInstance );
1885
1886}
1887
1888
1890{
1891 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1892 {
1893 // if aSheetPath is found, nothing to do:
1894 if( instance.m_Path == aPath )
1895 return false;
1896 }
1897
1898 wxLogTrace( traceSchSheetPaths, wxT( "Adding instance `%s` to sheet `%s`." ), aPath.AsString(),
1899 GetName().IsEmpty() ? wxString( wxT( "root" ) ) : GetName() );
1900
1901 SCH_SHEET_INSTANCE instance;
1902
1903 instance.m_Path = aPath;
1904
1905 // This entry does not exist: add it with an empty page number.
1906 m_instances.emplace_back( instance );
1907 return true;
1908}
1909
1910
1911bool SCH_SHEET::getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath, bool aTestFromEnd ) const
1912{
1913 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1914 {
1915 if( !aTestFromEnd )
1916 {
1917 if( instance.m_Path == aSheetPath )
1918 {
1919 aInstance = instance;
1920 return true;
1921 }
1922 }
1923 else if( instance.m_Path.EndsWith( aSheetPath ) )
1924 {
1925 aInstance = instance;
1926 return true;
1927 }
1928 }
1929
1930 return false;
1931}
1932
1933
1935{
1936 for( SCH_SHEET_INSTANCE& instance : m_instances )
1937 {
1938 if( instance.m_Path == aSheetPath )
1939 return &instance;
1940 }
1941
1942 return nullptr;
1943}
1944
1945
1946const SCH_SHEET_INSTANCE* SCH_SHEET::getInstance( const KIID_PATH& aSheetPath ) const
1947{
1948 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1949 {
1950 if( instance.m_Path == aSheetPath )
1951 return &instance;
1952 }
1953
1954 return nullptr;
1955}
1956
1957
1959{
1960 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1961 {
1962 if( instance.m_Path.size() == 0 )
1963 return true;
1964 }
1965
1966 return false;
1967}
1968
1969
1971{
1972 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1973 {
1974 if( instance.m_Path.size() == 0 )
1975 return instance;
1976 }
1977
1978 wxFAIL;
1979
1981
1982 return dummy;
1983}
1984
1985
1986wxString SCH_SHEET::getPageNumber( const KIID_PATH& aParentPath ) const
1987{
1988 wxString pageNumber;
1989
1990 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1991 {
1992 if( instance.m_Path == aParentPath )
1993 {
1994 pageNumber = instance.m_PageNumber;
1995 break;
1996 }
1997 }
1998
1999 return pageNumber;
2000}
2001
2002
2003void SCH_SHEET::setPageNumber( const KIID_PATH& aPath, const wxString& aPageNumber )
2004{
2005 for( SCH_SHEET_INSTANCE& instance : m_instances )
2006 {
2007 if( instance.m_Path == aPath )
2008 {
2009 instance.m_PageNumber = aPageNumber;
2010 break;
2011 }
2012 }
2013}
2014
2015
2017{
2018 return GetName() != aOther.GetName()
2019 || GetFileName() != aOther.GetFileName()
2020 || GetScreen() != aOther.GetScreen()
2021 || HasPageNumberChanges( aOther );
2022}
2023
2024
2026{
2027 return !std::ranges::equal( m_pins, aOther.m_pins, {}, &SCH_SHEET_PIN::m_Uuid, &SCH_SHEET_PIN::m_Uuid );
2028}
2029
2030
2032{
2033 // Avoid self comparison.
2034 if( &aOther == this )
2035 return false;
2036
2037 // A difference in the instance data count implies a page numbering change.
2038 if( GetInstances().size() != aOther.GetInstances().size() )
2039 return true;
2040
2041 std::vector<SCH_SHEET_INSTANCE> instances = GetInstances();
2042 std::vector<SCH_SHEET_INSTANCE> otherInstances = aOther.GetInstances();
2043
2044 // Sorting may not be necessary but there is no guarantee that sheet
2045 // instance data will be in the correct KIID_PATH order. We should
2046 // probably use a std::map instead of a std::vector to store the sheet
2047 // instance data.
2048 std::sort( instances.begin(), instances.end(),
2049 []( const SCH_SHEET_INSTANCE& aLhs, const SCH_SHEET_INSTANCE& aRhs )
2050 {
2051 if( aLhs.m_Path > aRhs.m_Path )
2052 return true;
2053
2054 return false;
2055 } );
2056 std::sort( otherInstances.begin(), otherInstances.end(),
2057 []( const SCH_SHEET_INSTANCE& aLhs, const SCH_SHEET_INSTANCE& aRhs )
2058 {
2059 if( aLhs.m_Path > aRhs.m_Path )
2060 return true;
2061
2062 return false;
2063 } );
2064
2065 auto itThis = instances.begin();
2066 auto itOther = otherInstances.begin();
2067
2068 while( itThis != instances.end() )
2069 {
2070 if( itThis->m_Path == itOther->m_Path
2071 && itThis->m_PageNumber != itOther->m_PageNumber )
2072 {
2073 return true;
2074 }
2075
2076 itThis++;
2077 itOther++;
2078 }
2079
2080 return false;
2081}
2082
2083
2084int SCH_SHEET::ComparePageNum( const wxString& aPageNumberA, const wxString& aPageNumberB )
2085{
2086 if( aPageNumberA == aPageNumberB )
2087 return 0; // A == B
2088
2089 // First sort numerically if the page numbers are integers
2090 long pageA, pageB;
2091 bool isIntegerPageA = aPageNumberA.ToLong( &pageA );
2092 bool isIntegerPageB = aPageNumberB.ToLong( &pageB );
2093
2094 if( isIntegerPageA && isIntegerPageB )
2095 {
2096 if( pageA < pageB )
2097 return -1; //A < B
2098 else
2099 return 1; // A > B
2100 }
2101
2102 // Numerical page numbers always before strings
2103 if( isIntegerPageA )
2104 return -1; //A < B
2105 else if( isIntegerPageB )
2106 return 1; // A > B
2107
2108 // If not numeric, then sort as strings using natural sort
2109 int result = StrNumCmp( aPageNumberA, aPageNumberB );
2110
2111 // Divide by zero bad.
2112 wxCHECK( result != 0, 0 );
2113
2115
2116 return result;
2117}
2118
2119
2120bool SCH_SHEET::operator==( const SCH_ITEM& aOther ) const
2121{
2122 if( Type() != aOther.Type() )
2123 return false;
2124
2125 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
2126
2127 if( m_pos != other->m_pos )
2128 return false;
2129
2130 if( m_size != other->m_size )
2131 return false;
2132
2133 if( GetExcludedFromSim() != other->GetExcludedFromSim() )
2134 return false;
2135
2136 if( GetExcludedFromBOM() != other->GetExcludedFromBOM() )
2137 return false;
2138
2139 if( GetExcludedFromBoard() != other->GetExcludedFromBoard() )
2140 return false;
2141
2142 if( GetDNP() != other->GetDNP() )
2143 return false;
2144
2145 if( GetBorderColor() != other->GetBorderColor() )
2146 return false;
2147
2148 if( GetBackgroundColor() != other->GetBackgroundColor() )
2149 return false;
2150
2151 if( GetBorderWidth() != other->GetBorderWidth() )
2152 return false;
2153
2154 if( GetFields().size() != other->GetFields().size() )
2155 return false;
2156
2157 for( size_t i = 0; i < GetFields().size(); ++i )
2158 {
2159 if( GetFields()[i] != other->GetFields()[i] )
2160 return false;
2161 }
2162
2163 if( GetPins().size() != other->GetPins().size() )
2164 return false;
2165
2166 for( size_t ii = 0; ii < GetPins().size(); ++ii )
2167 {
2168 if( !GetPins()[ii]->operator==( other->GetPins()[ii] ) )
2169 return false;
2170 }
2171
2172 return true;
2173}
2174
2175
2176double SCH_SHEET::Similarity( const SCH_ITEM& aOther ) const
2177{
2178 if( Type() != aOther.Type() )
2179 return 0.0;
2180
2181 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
2182
2183 if( m_screen->GetFileName() == other->m_screen->GetFileName() )
2184 return 1.0;
2185
2186 return 0.0;
2187}
2188
2189
2190void SCH_SHEET::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SHEET_VARIANT& aVariant )
2191{
2192 SCH_SHEET_INSTANCE* instance = getInstance( aInstance );
2193
2194 // The instance path must already exist.
2195 if( !instance )
2196 return;
2197
2198 if( instance->m_Variants.insert( std::make_pair( aVariant.m_Name, aVariant ) ).second )
2200}
2201
2202
2203void SCH_SHEET::DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantName )
2204{
2205 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2206
2207 // The instance path must already exist.
2208 if( !instance || !instance->m_Variants.contains( aVariantName ) )
2209 return;
2210
2211 instance->m_Variants.erase( aVariantName );
2212
2214}
2215
2216
2217void SCH_SHEET::ClearVariantField( const KIID_PATH& aPath, const wxString& aVariantName,
2218 const wxString& aFieldName )
2219{
2220 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2221
2222 if( !instance || !instance->m_Variants.contains( aVariantName ) )
2223 return;
2224
2225 if( instance->m_Variants[aVariantName].m_Fields.erase( aFieldName ) )
2227}
2228
2229
2230void SCH_SHEET::RenameVariant( const KIID_PATH& aPath, const wxString& aOldName, const wxString& aNewName )
2231{
2232 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2233
2234 // The instance path must already exist and contain the old variant.
2235 if( aOldName == aNewName || !instance || !instance->m_Variants.contains( aOldName ) )
2236 return;
2237
2238 // Get the variant data, update the name, and re-insert with new key
2239 SCH_SHEET_VARIANT variant = instance->m_Variants[aOldName];
2240 variant.m_Name = aNewName;
2241 instance->m_Variants.erase( aOldName );
2242 instance->m_Variants.insert( std::make_pair( aNewName, variant ) );
2243
2245}
2246
2247
2248void SCH_SHEET::CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant, const wxString& aNewVariant )
2249{
2250 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
2251
2252 // The instance path must already exist and contain the source variant.
2253 if( !instance || !instance->m_Variants.contains( aSourceVariant ) )
2254 return;
2255
2256 // Copy the variant data with a new name
2257 SCH_SHEET_VARIANT variant = instance->m_Variants[aSourceVariant];
2258 variant.m_Name = aNewVariant;
2259
2260 if( instance->m_Variants.insert( std::make_pair( aNewVariant, variant ) ).second )
2262}
2263
2264
2265void SCH_SHEET::setVariantAttribute( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName,
2266 bool SCH_SHEET::*aBase, bool SCH_SHEET_VARIANT::*aOverride )
2267{
2268 bool* attribute = &( this->*aBase );
2269
2270 if( aInstance && !aVariantName.IsEmpty() )
2271 {
2272 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
2273
2274 wxCHECK_MSG( instance, /* void */,
2275 wxString::Format( wxS( "Cannot set attribute for invalid sheet path '%s'." ),
2276 aInstance->PathHumanReadable() ) );
2277
2278 auto variant = instance->m_Variants.find( aVariantName );
2279
2280 if( variant == instance->m_Variants.end() )
2281 {
2282 if( aEnable == this->*aBase )
2283 return;
2284
2285 SCH_SHEET_VARIANT newVariant( aVariantName );
2286 newVariant.InitializeAttributes( *this );
2287 newVariant.*aOverride = aEnable;
2288 AddVariant( *aInstance, newVariant );
2289 return;
2290 }
2291
2292 attribute = &( variant->second.*aOverride );
2293 }
2294
2295 if( *attribute == aEnable )
2296 return;
2297
2298 *attribute = aEnable;
2300}
2301
2302
2303void SCH_SHEET::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2304{
2305 setVariantAttribute( aEnable, aInstance, aVariantName, &SCH_SHEET::m_DNP, &SCH_SHEET_VARIANT::m_DNP );
2306}
2307
2308
2309bool SCH_SHEET::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2310{
2311 if( !aInstance || aVariantName.IsEmpty() )
2312 return m_DNP;
2313
2314 SCH_SHEET_INSTANCE instance;
2315
2316 if( !getInstance( instance, aInstance->Path() ) )
2317 return m_DNP;
2318
2319 if( instance.m_Variants.contains( aVariantName ) )
2320 return instance.m_Variants[aVariantName].m_DNP;
2321
2322 // If the variant has not been defined, return the default DNP setting.
2323 return m_DNP;
2324}
2325
2326
2328{
2329 return GetDNP( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2330}
2331
2332
2333void SCH_SHEET::SetDNPProp( bool aEnable )
2334{
2335 SetDNP( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2336}
2337
2338
2339void SCH_SHEET::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2340{
2341 setVariantAttribute( aEnable, aInstance, aVariantName, &SCH_SHEET::m_excludedFromSim,
2343}
2344
2345
2346bool SCH_SHEET::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2347{
2348 if( !aInstance || aVariantName.IsEmpty() )
2349 return m_excludedFromSim;
2350
2351 SCH_SHEET_INSTANCE instance;
2352
2353 if( !getInstance( instance, aInstance->Path() ) )
2354 return m_excludedFromSim;
2355
2356 if( instance.m_Variants.contains( aVariantName ) )
2357 return instance.m_Variants[aVariantName].m_ExcludedFromSim;
2358
2359 // If the variant has not been defined, return the default DNP setting.
2360 return m_excludedFromSim;
2361}
2362
2363
2365{
2366 return GetExcludedFromSim( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2367}
2368
2369
2371{
2372 SetExcludedFromSim( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2373}
2374
2375
2376void SCH_SHEET::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2377{
2378 setVariantAttribute( aEnable, aInstance, aVariantName, &SCH_SHEET::m_excludedFromBOM,
2380}
2381
2382
2383bool SCH_SHEET::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2384{
2385 if( !aInstance || aVariantName.IsEmpty() )
2386 return m_excludedFromBOM;
2387
2388 SCH_SHEET_INSTANCE instance;
2389
2390 if( !getInstance( instance, aInstance->Path() ) )
2391 return m_excludedFromBOM;
2392
2393 if( instance.m_Variants.contains( aVariantName ) )
2394 return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
2395
2396 // If the variant has not been defined, return the default DNP setting.
2397 return m_excludedFromBOM;
2398}
2399
2400
2402{
2403 return GetExcludedFromBOM( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2404}
2405
2406
2408{
2409 SetExcludedFromBOM( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2410}
2411
2412
2413#if defined(DEBUG)
2414
2415void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
2416{
2417 // XML output:
2418 wxString s = GetClass();
2419
2420 NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">" << " sheet_name=\""
2421 << TO_UTF8( GetName() ) << '"' << ">\n";
2422
2423 // show all the pins, and check the linked list integrity
2424 for( SCH_SHEET_PIN* sheetPin : m_pins )
2425 sheetPin->Show( nestLevel + 1, os );
2426
2427 NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n" << std::flush;
2428}
2429
2430#endif
2431
2432static struct SCH_SHEET_DESC
2433{
2435 {
2439
2440 propMgr.AddProperty( new PROPERTY<SCH_SHEET, wxString>( _HKI( "Sheet Name" ),
2442 .SetValidator( []( const wxAny&& aValue, EDA_ITEM* ) -> VALIDATOR_RESULT
2443 {
2444 wxString value;
2445
2446 if( !aValue.GetAs( &value ) )
2447 return {};
2448
2449 wxString msg = GetFieldValidationErrorMessage( FIELD_T::SHEET_NAME, value );
2450
2451 if( msg.empty() )
2452 return {};
2453
2454 return std::make_unique<VALIDATION_ERROR_MSG>( msg );
2455 } );
2456
2457 propMgr.AddProperty( new PROPERTY<SCH_SHEET, int>( _HKI( "Border Width" ),
2459
2460 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Border Color" ),
2462
2463 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Background Color" ),
2465
2466 const wxString groupAttributes = _HKI( "Attributes" );
2467
2468 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Board" ),
2470 groupAttributes );
2471 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Simulation" ),
2473 groupAttributes );
2474 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Bill of Materials" ),
2476 groupAttributes );
2477 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Do not Populate" ),
2479 groupAttributes );
2480 }
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: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: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: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: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: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