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, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <cstdlib>
27
28#include <bitmaps.h>
29#include <core/mirror.h>
30#include <core/kicad_algo.h>
31#include <sch_draw_panel.h>
32#include <trigo.h>
33#include <sch_edit_frame.h>
34#include <plotters/plotter.h>
35#include <sch_plotter.h>
36#include <string_utils.h>
37#include <widgets/msgpanel.h>
38#include <math/util.h> // for KiROUND
40#include <sch_sheet.h>
41#include <sch_sheet_path.h>
42#include <sch_sheet_pin.h>
43#include <sch_no_connect.h>
44#include <sch_symbol.h>
45#include <sch_painter.h>
46#include <schematic.h>
48#include <trace_helpers.h>
49#include <validators.h>
51#include <properties/property.h>
53#include <pgm_base.h>
54#include <wx/log.h>
55
81
82
84 SCH_ITEM( aSheet )
85{
86 m_pos = aSheet.m_pos;
87 m_size = aSheet.m_size;
88 m_layer = aSheet.m_layer;
89 const_cast<KIID&>( m_Uuid ) = aSheet.m_Uuid;
90 m_fields = aSheet.m_fields;
92 m_screen = aSheet.m_screen;
93
97 m_DNP = aSheet.m_DNP;
98
102 m_instances = aSheet.m_instances;
103
104 for( SCH_SHEET_PIN* pin : aSheet.m_pins )
105 {
106 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
107 m_pins.back()->SetParent( this );
108 }
109
110 for( SCH_FIELD& field : m_fields )
111 field.SetParent( this );
112
113 if( m_screen )
114 m_screen->IncRefCount();
115}
116
117
119{
120 // also, look at the associated sheet & its reference count
121 // perhaps it should be deleted also.
122 if( m_screen )
123 {
124 m_screen->DecRefCount();
125
126 if( m_screen->GetRefCount() == 0 )
127 delete m_screen;
128 }
129
130 // We own our pins; delete them
131 for( SCH_SHEET_PIN* pin : m_pins )
132 delete pin;
133}
134
135
137{
138 return new SCH_SHEET( *this );
139}
140
141
143{
144 if( aScreen == m_screen )
145 return;
146
147 if( m_screen != nullptr )
148 {
149 m_screen->DecRefCount();
150
151 if( m_screen->GetRefCount() == 0 )
152 {
153 delete m_screen;
154 m_screen = nullptr;
155 }
156 }
157
158 m_screen = aScreen;
159
160 if( m_screen )
161 m_screen->IncRefCount();
162}
163
164
166{
167 if( m_screen == nullptr )
168 return 0;
169
170 return m_screen->GetRefCount();
171}
172
173
175{
176 wxCHECK_MSG( Schematic(), false, "Can't call IsVirtualRootSheet without setting a schematic" );
177
178 return m_Uuid == niluuid;
179}
180
181
183{
184 wxCHECK_MSG( Schematic(), false, "Can't call IsTopLevelSheet without setting a schematic" );
185
186 return Schematic()->IsTopLevelSheet( this );
187}
188
189
190void SCH_SHEET::GetContextualTextVars( wxArrayString* aVars ) const
191{
192 auto add =
193 [&]( const wxString& aVar )
194 {
195 if( !alg::contains( *aVars, aVar ) )
196 aVars->push_back( aVar );
197 };
198
199 for( const SCH_FIELD& field : m_fields )
200 {
201 if( field.IsMandatory() )
202 add( field.GetCanonicalName().Upper() );
203 else
204 add( field.GetName() );
205 }
206
207 SCH_SHEET_PATH sheetPath = findSelf();
208
209 if( sheetPath.size() >= 2 )
210 {
211 sheetPath.pop_back();
212 sheetPath.Last()->GetContextualTextVars( aVars );
213 }
214 else if( Schematic() )
215 {
217 }
218
219 add( wxT( "#" ) );
220 add( wxT( "##" ) );
221 add( wxT( "SHEETPATH" ) );
222 add( wxT( "EXCLUDE_FROM_BOM" ) );
223 add( wxT( "EXCLUDE_FROM_BOARD" ) );
224 add( wxT( "EXCLUDE_FROM_SIM" ) );
225 add( wxT( "DNP" ) );
226 add( wxT( "ERC_ERROR <message_text>" ) );
227 add( wxT( "ERC_WARNING <message_text>" ) );
228
229 m_screen->GetTitleBlock().GetContextualTextVars( aVars );
230}
231
232
233bool SCH_SHEET::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
234{
235 wxCHECK( aPath, false );
236
237 SCHEMATIC* schematic = Schematic();
238
239 if( !schematic )
240 return false;
241
242 if( token->Contains( ':' ) )
243 {
244 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
245 return true;
246 }
247
248 for( const SCH_FIELD& field : m_fields )
249 {
250 wxString fieldName = field.IsMandatory() ? field.GetCanonicalName().Upper()
251 : field.GetName();
252
253 if( token->IsSameAs( fieldName ) )
254 {
255 *token = field.GetShownText( aPath, false, aDepth + 1 );
256 return true;
257 }
258 }
259
260 PROJECT* project = &schematic->Project();
261 wxString variant = schematic->GetCurrentVariant();
262
263 // We cannot resolve text variables initially on load as we need to first load the screen and
264 // then parse the hierarchy. So skip the resolution if the screen isn't set yet
265 if( m_screen && m_screen->GetTitleBlock().TextVarResolver( token, project ) )
266 {
267 return true;
268 }
269
270 if( token->IsSameAs( wxT( "#" ) ) )
271 {
272 *token = wxString::Format( "%s", aPath->GetPageNumber() );
273 return true;
274 }
275 else if( token->IsSameAs( wxT( "##" ) ) )
276 {
277 *token = wxString::Format( wxT( "%d" ), (int) schematic->Hierarchy().size() );
278 return true;
279 }
280 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
281 {
282 *token = aPath->PathHumanReadable();
283 return true;
284 }
285 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) )
286 {
287 *token = wxEmptyString;
288
289 if( aPath->GetExcludedFromBOM( variant ) || this->ResolveExcludedFromBOM( aPath, variant ) )
290 *token = _( "Excluded from BOM" );
291
292 return true;
293 }
294 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) )
295 {
296 *token = wxEmptyString;
297
298 if( aPath->GetExcludedFromBoard( variant ) || this->ResolveExcludedFromBoard( aPath, variant ) )
299 *token = _( "Excluded from board" );
300
301 return true;
302 }
303 else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) )
304 {
305 *token = wxEmptyString;
306
307 if( aPath->GetExcludedFromSim( variant ) || this->ResolveExcludedFromSim( aPath, variant ) )
308 *token = _( "Excluded from simulation" );
309
310 return true;
311 }
312 else if( token->IsSameAs( wxT( "DNP" ) ) )
313 {
314 *token = wxEmptyString;
315
316 if( aPath->GetDNP( variant ) || this->ResolveDNP( aPath, variant ) )
317 *token = _( "DNP" );
318
319 return true;
320 }
321
322 // See if parent can resolve it (these will recurse to ancestors)
323
324 if( aPath->size() >= 2 )
325 {
326 SCH_SHEET_PATH path = *aPath;
327 path.pop_back();
328
329 if( path.Last()->ResolveTextVar( &path, token, aDepth + 1 ) )
330 return true;
331 }
332 else
333 {
334 if( schematic->ResolveTextVar( aPath, token, aDepth + 1 ) )
335 return true;
336 }
337
338 return false;
339}
340
341
343{
344 wxCHECK_RET( aItem->Type() == SCH_SHEET_T,
345 wxString::Format( wxT( "SCH_SHEET object cannot swap data with %s object." ),
346 aItem->GetClass() ) );
347
348 SCH_SHEET* sheet = ( SCH_SHEET* ) aItem;
349
350 std::swap( m_pos, sheet->m_pos );
351 std::swap( m_size, sheet->m_size );
352 m_fields.swap( sheet->m_fields );
353 std::swap( m_fieldsAutoplaced, sheet->m_fieldsAutoplaced );
354 m_pins.swap( sheet->m_pins );
355
356 // Update parent pointers after swapping.
357 for( SCH_SHEET_PIN* sheetPin : m_pins )
358 sheetPin->SetParent( this );
359
360 for( SCH_SHEET_PIN* sheetPin : sheet->m_pins )
361 sheetPin->SetParent( sheet );
362
363 for( SCH_FIELD& field : m_fields )
364 field.SetParent( this );
365
366 for( SCH_FIELD& field : sheet->m_fields )
367 field.SetParent( sheet );
368
369 std::swap( m_excludedFromSim, sheet->m_excludedFromSim );
370 std::swap( m_excludedFromBOM, sheet->m_excludedFromBOM );
371 std::swap( m_excludedFromBoard, sheet->m_excludedFromBoard );
372 std::swap( m_DNP, sheet->m_DNP );
373
374 std::swap( m_borderWidth, sheet->m_borderWidth );
375 std::swap( m_borderColor, sheet->m_borderColor );
376 std::swap( m_backgroundColor, sheet->m_backgroundColor );
377 std::swap( m_instances, sheet->m_instances );
378}
379
380
382{
383 if( SCH_FIELD* field = FindField( m_fields, aFieldType ) )
384 return field;
385
386 m_fields.emplace_back( this, aFieldType );
387 return &m_fields.back();
388}
389
390
391const SCH_FIELD* SCH_SHEET::GetField( FIELD_T aFieldType ) const
392{
393 return FindField( m_fields, aFieldType );
394}
395
396
397SCH_FIELD* SCH_SHEET::GetField( const wxString& aFieldName )
398{
399 return FindField( m_fields, aFieldName );
400}
401
402
403const SCH_FIELD* SCH_SHEET::GetField( const wxString& aFieldName ) const
404{
405 return FindField( m_fields, aFieldName );
406}
407
408
410{
411 return NextFieldOrdinal( m_fields );
412}
413
414
415void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
416{
417 m_fields = aFields;
418
419 // Make sure that we get the UNIX variant of the file path
421}
422
423
425{
426 m_fields.emplace_back( aField );
427 return &m_fields.back();
428}
429
430
431void SCH_SHEET::SetFieldText( const wxString& aFieldName, const wxString& aFieldText, const SCH_SHEET_PATH* aPath,
432 const wxString& aVariantName )
433{
434 wxCHECK( !aFieldName.IsEmpty(), /* void */ );
435
436 SCH_FIELD* field = GetField( aFieldName );
437
438 wxCHECK( field, /* void */ );
439
440 switch( field->GetId() )
441 {
443 {
444 // File names are stored using unix separators.
445 wxString tmp = aFieldText;
446 tmp.Replace( wxT( "\\" ), wxT( "/" ) );
448 break;
449 }
450
452 field->SetText( aFieldText );
453 break;
454
455 default:
456 {
457 wxString defaultText = field->GetText( aPath );
458
459 if( aVariantName.IsEmpty() )
460 {
461 if( aFieldText != defaultText )
462 field->SetText( aFieldText );
463 }
464 else
465 {
466 SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
467
468 wxCHECK( instance, /* void */ );
469
470 if( instance->m_Variants.contains( aVariantName ) )
471 {
472 if( aFieldText != defaultText )
473 instance->m_Variants[aVariantName].m_Fields[aFieldName] = aFieldText;
474 else
475 instance->m_Variants[aVariantName].m_Fields.erase( aFieldName );
476 }
477 else if( aFieldText != defaultText )
478 {
479 SCH_SHEET_VARIANT newVariant( aVariantName );
480
481 newVariant.InitializeAttributes( *this );
482 newVariant.m_Fields[aFieldName] = aFieldText;
483 instance->m_Variants.insert( std::make_pair( aVariantName, newVariant ) );
484 }
485 }
486
487 break;
488 }
489 }
490}
491
492
493wxString SCH_SHEET::GetFieldText( const wxString& aFieldName, const SCH_SHEET_PATH* aPath,
494 const wxString& aVariantName ) const
495{
496 wxCHECK( !aFieldName.IsEmpty(), wxEmptyString );
497
498 const SCH_FIELD* field = GetField( aFieldName );
499
500 wxCHECK( field, wxEmptyString );
501
502 switch( field->GetId() )
503 {
506 return field->GetText();
507 break;
508
509 default:
510 if( aVariantName.IsEmpty() )
511 {
512 return field->GetText();
513 }
514 else
515 {
516 const SCH_SHEET_INSTANCE* instance = getInstance( *aPath );
517
518 if( instance->m_Variants.contains( aVariantName )
519 && instance->m_Variants.at( aVariantName ).m_Fields.contains( aFieldName ) )
520 return instance->m_Variants.at( aVariantName ).m_Fields.at( aFieldName );
521 }
522
523 break;
524 }
525
526 return field->GetText();
527}
528
529
531{
532 wxASSERT( aSheetPin != nullptr );
533 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
534
535 aSheetPin->SetParent( this );
536 m_pins.push_back( aSheetPin );
537 renumberPins();
538}
539
540
541void SCH_SHEET::RemovePin( const SCH_SHEET_PIN* aSheetPin )
542{
543 wxASSERT( aSheetPin != nullptr );
544 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
545
546 for( auto i = m_pins.begin(); i < m_pins.end(); ++i )
547 {
548 if( *i == aSheetPin )
549 {
550 m_pins.erase( i );
551 renumberPins();
552 return;
553 }
554 }
555}
556
557
558bool SCH_SHEET::HasPin( const wxString& aName ) const
559{
560 for( SCH_SHEET_PIN* pin : m_pins )
561 {
562 if( pin->GetText().Cmp( aName ) == 0 )
563 return true;
564 }
565
566 return false;
567}
568
569
570bool SCH_SHEET::doIsConnected( const VECTOR2I& aPosition ) const
571{
572 for( SCH_SHEET_PIN* sheetPin : m_pins )
573 {
574 if( sheetPin->GetPosition() == aPosition )
575 return true;
576 }
577
578 return false;
579}
580
581
583{
584 int leftRight = 0;
585 int topBottom = 0;
586
587 for( SCH_SHEET_PIN* pin : m_pins )
588 {
589 switch( pin->GetSide() )
590 {
591 case SHEET_SIDE::LEFT: leftRight++; break;
592 case SHEET_SIDE::RIGHT: leftRight++; break;
593 case SHEET_SIDE::TOP: topBottom++; break;
594 case SHEET_SIDE::BOTTOM: topBottom++; break;
595 default: break;
596 }
597 }
598
599 return topBottom > 0 && leftRight == 0;
600}
601
602
604{
605 for( SCH_SHEET_PIN* pin : m_pins )
606 {
607 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
608 const SCH_HIERLABEL* HLabel = nullptr;
609
610 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
611 {
612 if( !pin->GetText().Cmp( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
613 {
614 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
615 break;
616 }
617 }
618
619 if( HLabel == nullptr ) // Corresponding hierarchical label not found.
620 return true;
621 }
622
623 return false;
624}
625
626
627int bumpToNextGrid( const int aVal, const int aDirection )
628{
629 constexpr int gridSize = schIUScale.MilsToIU( 50 );
630
631 int base = aVal / gridSize;
632 int excess = abs( aVal % gridSize );
633
634 if( aDirection > 0 )
635 {
636 return ( base + 1 ) * gridSize;
637 }
638 else if( excess > 0 )
639 {
640 return ( base ) * gridSize;
641 }
642 else
643 {
644 return ( base - 1 ) * gridSize;
645 }
646}
647
648
649int SCH_SHEET::GetMinWidth( bool aFromLeft ) const
650{
651 int pinsLeft = m_pos.x + m_size.x;
652 int pinsRight = m_pos.x;
653
654 for( size_t i = 0; i < m_pins.size(); i++ )
655 {
656 SHEET_SIDE edge = m_pins[i]->GetSide();
657
658 if( edge == SHEET_SIDE::TOP || edge == SHEET_SIDE::BOTTOM )
659 {
660 BOX2I pinRect = m_pins[i]->GetBoundingBox();
661
662 pinsLeft = std::min( pinsLeft, pinRect.GetLeft() );
663 pinsRight = std::max( pinsRight, pinRect.GetRight() );
664 }
665 }
666
667 pinsLeft = bumpToNextGrid( pinsLeft, -1 );
668 pinsRight = bumpToNextGrid( pinsRight, 1 );
669
670 int pinMinWidth;
671
672 if( pinsLeft >= pinsRight )
673 pinMinWidth = 0;
674 else if( aFromLeft )
675 pinMinWidth = pinsRight - m_pos.x;
676 else
677 pinMinWidth = m_pos.x + m_size.x - pinsLeft;
678
679 return std::max( pinMinWidth, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
680}
681
682
683int SCH_SHEET::GetMinHeight( bool aFromTop ) const
684{
685 int pinsTop = m_pos.y + m_size.y;
686 int pinsBottom = m_pos.y;
687
688 for( size_t i = 0; i < m_pins.size(); i++ )
689 {
690 SHEET_SIDE edge = m_pins[i]->GetSide();
691
692 if( edge == SHEET_SIDE::RIGHT || edge == SHEET_SIDE::LEFT )
693 {
694 BOX2I pinRect = m_pins[i]->GetBoundingBox();
695
696 pinsTop = std::min( pinsTop, pinRect.GetTop() );
697 pinsBottom = std::max( pinsBottom, pinRect.GetBottom() );
698 }
699 }
700
701 pinsTop = bumpToNextGrid( pinsTop, -1 );
702 pinsBottom = bumpToNextGrid( pinsBottom, 1 );
703
704 int pinMinHeight;
705
706 if( pinsTop >= pinsBottom )
707 pinMinHeight = 0;
708 else if( aFromTop )
709 pinMinHeight = pinsBottom - m_pos.y;
710 else
711 pinMinHeight = m_pos.y + m_size.y - pinsTop;
712
713 return std::max( pinMinHeight, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
714}
715
716
718{
719 std::vector<SCH_SHEET_PIN*> pins = m_pins;
720
721 m_pins.clear();
722
723 for( SCH_SHEET_PIN* pin : pins )
724 {
725 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
726 const SCH_HIERLABEL* HLabel = nullptr;
727
728 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
729 {
730 if( pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) == 0 )
731 {
732 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
733 break;
734 }
735 }
736
737 if( HLabel )
738 m_pins.push_back( pin );
739 }
740}
741
742
744{
745 for( SCH_SHEET_PIN* pin : m_pins )
746 {
747 if( pin->HitTest( aPosition ) )
748 return pin;
749 }
750
751 return nullptr;
752}
753
754
756{
757 if( GetBorderWidth() > 0 )
758 return GetBorderWidth();
759
760 if( Schematic() )
762
763 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
764}
765
766
768{
769 SCH_FIELD* sheetNameField = GetField( FIELD_T::SHEET_NAME );
770 VECTOR2I textSize = sheetNameField->GetTextSize();
771 int borderMargin = KiROUND( GetPenWidth() / 2.0 ) + 4;
772 int margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.5 );
773
775 {
776 sheetNameField->SetTextPos( m_pos + VECTOR2I( -margin, m_size.y ) );
777 sheetNameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
778 sheetNameField->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
779 sheetNameField->SetTextAngle( ANGLE_VERTICAL );
780 }
781 else
782 {
783 sheetNameField->SetTextPos( m_pos + VECTOR2I( 0, -margin ) );
784 sheetNameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
785 sheetNameField->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
786 sheetNameField->SetTextAngle( ANGLE_HORIZONTAL );
787 }
788
789 SCH_FIELD* sheetFilenameField = GetField( FIELD_T::SHEET_FILENAME );
790
791 textSize = sheetFilenameField->GetTextSize();
792 margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.4 );
793
795 {
796 sheetFilenameField->SetTextPos( m_pos + VECTOR2I( m_size.x + margin, m_size.y ) );
797 sheetFilenameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
798 sheetFilenameField->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
799 sheetFilenameField->SetTextAngle( ANGLE_VERTICAL );
800 }
801 else
802 {
803 sheetFilenameField->SetTextPos( m_pos + VECTOR2I( 0, m_size.y + margin ) );
804 sheetFilenameField->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
805 sheetFilenameField->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
806 sheetFilenameField->SetTextAngle( ANGLE_HORIZONTAL );
807 }
808
809 if( aAlgo == AUTOPLACE_AUTO || aAlgo == AUTOPLACE_MANUAL )
810 m_fieldsAutoplaced = aAlgo;
811}
812
813
814std::vector<int> SCH_SHEET::ViewGetLayers() const
815{
816 // Sheet pins are drawn by their parent sheet, so the parent needs to draw to LAYER_DANGLING
819}
820
821
823{
825 BOX2I box( m_pos, m_size );
826 int lineWidth = GetPenWidth();
827 int textLength = 0;
828
829 // Calculate bounding box X size:
830 end.x = std::max( m_size.x, textLength );
831
832 // Calculate bounding box pos:
833 end.y = m_size.y;
834 end += m_pos;
835
836 box.SetEnd( end );
837 box.Inflate( lineWidth / 2 );
838
839 return box;
840}
841
842
844{
845 BOX2I bbox = GetBodyBoundingBox();
846
847 for( const SCH_FIELD& field : m_fields )
848 bbox.Merge( field.GetBoundingBox() );
849
850 return bbox;
851}
852
853
855{
856 BOX2I box( m_pos, m_size );
857 return box.GetCenter();
858}
859
860
862{
863 int n = 0;
864
865 if( m_screen )
866 {
867 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SYMBOL_T ) )
868 {
869 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
870
871 if( !symbol->IsPower() )
872 n++;
873 }
874
875 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
876 n += static_cast<const SCH_SHEET*>( aItem )->SymbolCount();
877 }
878
879 return n;
880}
881
882
883bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
884{
885 if( m_screen )
886 {
887 // Only check the root sheet once and don't recurse.
888 if( !GetParent() )
889 {
890 if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
891 {
892 *aScreen = m_screen;
893 return true;
894 }
895 }
896
897 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
898 {
899 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
900 SCH_SCREEN* screen = sheet->m_screen;
901
902 // Must use the screen's path (which is always absolute) rather than the
903 // sheet's (which could be relative).
904 if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
905 {
906 *aScreen = screen;
907 return true;
908 }
909
910 if( sheet->SearchHierarchy( aFilename, aScreen ) )
911 return true;
912 }
913 }
914
915 return false;
916}
917
918
920{
921 if( m_screen )
922 {
923 aList->push_back( this );
924
925 if( m_screen == aScreen )
926 return true;
927
928 for( EDA_ITEM* item : m_screen->Items().OfType( SCH_SHEET_T ) )
929 {
930 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
931
932 if( sheet->LocatePathOfScreen( aScreen, aList ) )
933 return true;
934 }
935
936 aList->pop_back();
937 }
938
939 return false;
940}
941
942
943int SCH_SHEET::CountSheets( const wxString& aFilename ) const
944{
945 int count = 0;
946
947 if( m_screen )
948 {
949 if( m_screen->GetFileName().Cmp( aFilename ) == 0 )
950 count++;
951
952 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
953 count += static_cast<SCH_SHEET*>( aItem )->CountSheets( aFilename );
954 }
955
956 return count;
957}
958
959
961{
962 int count = 1; //1 = this!!
963
964 if( m_screen )
965 {
966 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
967 count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
968 }
969
970 return count;
971}
972
973
975{
976 int count = CountSheets();
977
978 if( IsVirtualRootSheet() )
979 count--;
980
981 return count;
982}
983
984
985void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
986{
987 // Don't use GetShownText(); we want to see the variable references here
988 aList.emplace_back( _( "Sheet Name" ), KIUI::EllipsizeStatusText( aFrame, GetName() ) );
989
990 SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
991 SCH_SHEET_PATH* currentSheet = nullptr;
992 wxString currentVariant;
993
994 if( schframe )
995 {
996 SCH_SHEET_PATH path = schframe->GetCurrentSheet();
997 path.push_back( this );
998 currentSheet = &schframe->GetCurrentSheet();
999 currentVariant = Schematic() ? Schematic()->GetCurrentVariant() : wxString();
1000
1001 aList.emplace_back( _( "Hierarchical Path" ), path.PathHumanReadable( false, true ) );
1002 }
1003
1004 // Don't use GetShownText(); we want to see the variable references here
1005 aList.emplace_back( _( "File Name" ), KIUI::EllipsizeStatusText( aFrame, GetFileName() ) );
1006
1007 wxArrayString msgs;
1008 wxString msg;
1009
1010 if( GetExcludedFromSim() )
1011 msgs.Add( _( "Simulation" ) );
1012
1013 if( GetExcludedFromBOM() )
1014 msgs.Add( _( "BOM" ) );
1015
1016 if( GetExcludedFromBoard() )
1017 msgs.Add( _( "Board" ) );
1018
1019 if( GetDNP( currentSheet, currentVariant ) )
1020 msgs.Add( _( "DNP" ) );
1021
1022 msg = wxJoin( msgs, '|' );
1023 msg.Replace( '|', wxS( ", " ) );
1024
1025 if( !msg.empty() )
1026 aList.emplace_back( _( "Exclude from" ), msg );
1027}
1028
1029
1030std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> SCH_SHEET::GetNoConnects() const
1031{
1032 std::map<SCH_SHEET_PIN*, SCH_NO_CONNECT*> noConnects;
1033
1034 if( SCH_SCREEN* screen = dynamic_cast<SCH_SCREEN*>( GetParent() ) )
1035 {
1036 for( SCH_SHEET_PIN* sheetPin : m_pins )
1037 {
1038 for( SCH_ITEM* noConnect : screen->Items().Overlapping( SCH_NO_CONNECT_T, sheetPin->GetTextPos() ) )
1039 noConnects[sheetPin] = static_cast<SCH_NO_CONNECT*>( noConnect );
1040 }
1041 }
1042
1043 return noConnects;
1044}
1045
1046
1048{
1049 VECTOR2I delta = aPosition - m_pos;
1050
1051 m_pos = aPosition;
1052
1053 for( SCH_FIELD& field : m_fields )
1054 field.Move( delta );
1055}
1056
1057
1058void SCH_SHEET::Move( const VECTOR2I& aMoveVector )
1059{
1060 m_pos += aMoveVector;
1061
1062 for( SCH_SHEET_PIN* pin : m_pins )
1063 pin->Move( aMoveVector );
1064
1065 for( SCH_FIELD& field : m_fields )
1066 field.Move( aMoveVector );
1067}
1068
1069
1070void SCH_SHEET::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
1071{
1072 VECTOR2I prev = m_pos;
1073
1074 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
1075 RotatePoint( &m_size.x, &m_size.y, aRotateCCW ? ANGLE_90 : ANGLE_270 );
1076
1077 if( m_size.x < 0 )
1078 {
1079 m_pos.x += m_size.x;
1080 m_size.x = -m_size.x;
1081 }
1082
1083 if( m_size.y < 0 )
1084 {
1085 m_pos.y += m_size.y;
1086 m_size.y = -m_size.y;
1087 }
1088
1089 // Pins must be rotated first as that's how we determine vertical vs horizontal
1090 // orientation for auto-placement
1091 for( SCH_SHEET_PIN* sheetPin : m_pins )
1092 sheetPin->Rotate( aCenter, aRotateCCW );
1093
1095 {
1097 }
1098 else
1099 {
1100 // Move the fields to the new position because the parent itself has moved.
1101 for( SCH_FIELD& field : m_fields )
1102 {
1103 VECTOR2I pos = field.GetTextPos();
1104 pos.x -= prev.x - m_pos.x;
1105 pos.y -= prev.y - m_pos.y;
1106 field.SetTextPos( pos );
1107 }
1108 }
1109}
1110
1111
1113{
1114 int dy = m_pos.y;
1115
1116 MIRROR( m_pos.y, aCenter );
1117 m_pos.y -= m_size.y;
1118 dy -= m_pos.y; // 0,dy is the move vector for this transform
1119
1120 for( SCH_SHEET_PIN* sheetPin : m_pins )
1121 sheetPin->MirrorVertically( aCenter );
1122
1123 for( SCH_FIELD& field : m_fields )
1124 {
1125 VECTOR2I pos = field.GetTextPos();
1126 pos.y -= dy;
1127 field.SetTextPos( pos );
1128 }
1129}
1130
1131
1133{
1134 int dx = m_pos.x;
1135
1136 MIRROR( m_pos.x, aCenter );
1137 m_pos.x -= m_size.x;
1138 dx -= m_pos.x; // dx,0 is the move vector for this transform
1139
1140 for( SCH_SHEET_PIN* sheetPin : m_pins )
1141 sheetPin->MirrorHorizontally( aCenter );
1142
1143 for( SCH_FIELD& field : m_fields )
1144 {
1145 VECTOR2I pos = field.GetTextPos();
1146 pos.x -= dx;
1147 field.SetTextPos( pos );
1148 }
1149}
1150
1151
1152void SCH_SHEET::SetPosition( const VECTOR2I& aPosition )
1153{
1154 // Remember the sheet and all pin sheet positions must be
1155 // modified. So use Move function to do that.
1156 Move( aPosition - m_pos );
1157}
1158
1159
1160void SCH_SHEET::Resize( const VECTOR2I& aSize )
1161{
1162 if( aSize == m_size )
1163 return;
1164
1165 m_size = aSize;
1166
1167 // Move the fields if we're in autoplace mode
1170
1171 // Move the sheet labels according to the new sheet size.
1172 for( SCH_SHEET_PIN* sheetPin : m_pins )
1173 sheetPin->ConstrainOnEdge( sheetPin->GetPosition(), false );
1174}
1175
1176
1177bool SCH_SHEET::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
1178{
1179 // Sheets are searchable via the child field and pin item text.
1180 return false;
1181}
1182
1183
1185{
1186 int id = 2;
1187
1188 for( SCH_SHEET_PIN* pin : m_pins )
1189 {
1190 pin->SetNumber( id );
1191 id++;
1192 }
1193}
1194
1195
1197{
1198 wxCHECK_MSG( Schematic(), SCH_SHEET_PATH(), "Can't call findSelf without a schematic" );
1199
1200 SCH_SHEET_PATH sheetPath = Schematic()->CurrentSheet();
1201
1202 while( !sheetPath.empty() && sheetPath.Last() != this )
1203 sheetPath.pop_back();
1204
1205 if( sheetPath.empty() )
1206 {
1207 // If we weren't in the hierarchy, then we must be a child of the current sheet.
1208 sheetPath = Schematic()->CurrentSheet();
1209 sheetPath.push_back( const_cast<SCH_SHEET*>( this ) );
1210 }
1211
1212 return sheetPath;
1213}
1214
1215
1216void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
1217{
1218 for( SCH_SHEET_PIN* sheetPin : m_pins )
1219 {
1220 wxCHECK2_MSG( sheetPin->Type() == SCH_SHEET_PIN_T, continue,
1221 wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) );
1222
1223 sheetPin->GetEndPoints( aItemList );
1224 }
1225}
1226
1227
1228bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
1229 std::vector<DANGLING_END_ITEM>& aItemListByPos,
1230 const SCH_SHEET_PATH* aPath )
1231{
1232 bool changed = false;
1233
1234 for( SCH_SHEET_PIN* sheetPin : m_pins )
1235 changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
1236
1237 return changed;
1238}
1239
1240
1242 const SCH_SHEET_PATH* aInstance ) const
1243{
1244 // Do not compare to ourself.
1245 if( aItem == this )
1246 return false;
1247
1248 const SCH_SHEET* sheet = dynamic_cast<const SCH_SHEET*>( aItem );
1249
1250 // Don't compare against a different SCH_ITEM.
1251 wxCHECK( sheet, false );
1252
1253 if( GetPosition() != sheet->GetPosition() )
1254 return true;
1255
1256 // Technically this cannot happen because undo/redo does not support reloading sheet
1257 // file association changes. This was just added so that it doesn't get missed should
1258 // we ever fix the undo/redo issue.
1259 if( ( GetFileName() != sheet->GetFileName() ) || ( GetName() != sheet->GetName() ) )
1260 return true;
1261
1262 if( m_pins.size() != sheet->m_pins.size() )
1263 return true;
1264
1265 for( size_t i = 0; i < m_pins.size(); i++ )
1266 {
1267 if( m_pins[i]->HasConnectivityChanges( sheet->m_pins[i] ) )
1268 return true;
1269 }
1270
1271 return false;
1272}
1273
1274
1275std::vector<VECTOR2I> SCH_SHEET::GetConnectionPoints() const
1276{
1277 std::vector<VECTOR2I> retval;
1278
1279 for( SCH_SHEET_PIN* sheetPin : m_pins )
1280 retval.push_back( sheetPin->GetPosition() );
1281
1282 return retval;
1283}
1284
1285
1286INSPECT_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData,
1287 const std::vector<KICAD_T>& aScanTypes )
1288{
1289 for( KICAD_T scanType : aScanTypes )
1290 {
1291 // If caller wants to inspect my type
1292 if( scanType == SCH_LOCATE_ANY_T || scanType == Type() )
1293 {
1294 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1295 return INSPECT_RESULT::QUIT;
1296 }
1297
1298 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1299 {
1300 // Test the sheet fields.
1301 for( SCH_FIELD& field : m_fields )
1302 {
1303 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1304 return INSPECT_RESULT::QUIT;
1305 }
1306 }
1307
1308 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_SHEET_PIN_T )
1309 {
1310 // Test the sheet labels.
1311 for( SCH_SHEET_PIN* sheetPin : m_pins )
1312 {
1313 if( INSPECT_RESULT::QUIT == aInspector( sheetPin, this ) )
1314 return INSPECT_RESULT::QUIT;
1315 }
1316 }
1317 }
1318
1320}
1321
1322
1323void SCH_SHEET::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction, RECURSE_MODE aMode )
1324{
1325 for( SCH_FIELD& field : m_fields )
1326 aFunction( &field );
1327
1328 for( SCH_SHEET_PIN* pin : m_pins )
1329 aFunction( pin );
1330}
1331
1332
1333wxString SCH_SHEET::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1334{
1335 const SCH_FIELD* sheetnameField = GetField( FIELD_T::SHEET_NAME );
1336
1337 return wxString::Format( _( "Hierarchical Sheet '%s'" ),
1338 aFull ? sheetnameField->GetShownText( false )
1339 : KIUI::EllipsizeMenuText( sheetnameField->GetText() ) );
1340}
1341
1342
1347
1348
1349bool SCH_SHEET::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1350{
1351 BOX2I rect = GetBodyBoundingBox();
1352
1353 rect.Inflate( aAccuracy );
1354
1355 return rect.Contains( aPosition );
1356}
1357
1358
1359bool SCH_SHEET::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1360{
1361 BOX2I rect = aRect;
1362
1363 rect.Inflate( aAccuracy );
1364
1365 if( aContained )
1366 return rect.Contains( GetBodyBoundingBox() );
1367
1368 return rect.Intersects( GetBodyBoundingBox() );
1369}
1370
1371
1372bool SCH_SHEET::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
1373{
1374 return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
1375}
1376
1377
1378void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1379 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1380{
1381 if( aBackground && !aPlotter->GetColorMode() )
1382 return;
1383
1384 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1385 COLOR4D borderColor = GetBorderColor();
1386 COLOR4D backgroundColor = GetBackgroundColor();
1387
1388 if( renderSettings->m_OverrideItemColors || borderColor == COLOR4D::UNSPECIFIED )
1389 borderColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET );
1390
1391 if( renderSettings->m_OverrideItemColors || backgroundColor == COLOR4D::UNSPECIFIED )
1392 backgroundColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET_BACKGROUND );
1393
1394 if( borderColor.m_text && Schematic() )
1395 borderColor = COLOR4D( ResolveText( *borderColor.m_text, &Schematic()->CurrentSheet() ) );
1396
1397 if( backgroundColor.m_text && Schematic() )
1398 backgroundColor = COLOR4D( ResolveText( *backgroundColor.m_text, &Schematic()->CurrentSheet() ) );
1399
1400 if( aBackground && backgroundColor.a > 0.0 )
1401 {
1402 aPlotter->SetColor( backgroundColor );
1403 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::FILLED_SHAPE, 1, 0 );
1404 }
1405 else
1406 {
1407 aPlotter->SetColor( borderColor );
1408
1409 int penWidth = GetEffectivePenWidth( getRenderSettings( aPlotter ) );
1410 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::NO_FILL, penWidth, 0 );
1411 }
1412
1413 // Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
1414 if( aPlotOpts.m_PDFHierarchicalLinks )
1415 {
1416 aPlotter->HyperlinkBox( GetBoundingBox(),
1417 EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1418 }
1419 else if( aPlotOpts.m_PDFPropertyPopups )
1420 {
1421 std::vector<wxString> properties;
1422
1423 properties.emplace_back( EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1424
1425 for( const SCH_FIELD& field : GetFields() )
1426 {
1427 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), field.GetName(),
1428 field.GetShownText( false ) ) );
1429 }
1430
1431 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
1432 }
1433
1434 // Plot sheet pins
1435 for( SCH_SHEET_PIN* sheetPin : m_pins )
1436 sheetPin->Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1437
1438 // Plot the fields
1439 for( SCH_FIELD& field : m_fields )
1440 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1441
1442 SCH_SHEET_PATH instance;
1443 wxString variantName;
1444
1445 if( Schematic() )
1446 {
1447 instance = Schematic()->CurrentSheet();
1448 variantName = Schematic()->GetCurrentVariant();
1449 }
1450
1451 if( GetDNP( &instance, variantName) )
1452 {
1453 BOX2I bbox = GetBodyBoundingBox();
1454 BOX2I pins = GetBoundingBox();
1455 VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ),
1456 std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) );
1457 int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
1458
1459 margins.x = std::max( margins.x * 0.6, margins.y * 0.3 );
1460 margins.y = std::max( margins.y * 0.6, margins.x * 0.3 );
1461 bbox.Inflate( KiROUND( margins.x ), KiROUND( margins.y ) );
1462
1463 aPlotter->SetColor( renderSettings->GetLayerColor( LAYER_DNP_MARKER ) );
1464
1465 aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, nullptr );
1466
1467 aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ),
1468 bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ),
1469 strokeWidth, nullptr );
1470 }
1471}
1472
1473
1475{
1476 wxCHECK_MSG( Type() == aItem.Type(), *this,
1477 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
1478 GetClass() );
1479
1480 if( &aItem != this )
1481 {
1482 SCH_ITEM::operator=( aItem );
1483
1484 SCH_SHEET* sheet = (SCH_SHEET*) &aItem;
1485
1486 m_pos = sheet->m_pos;
1487 m_size = sheet->m_size;
1488 m_fields = sheet->m_fields;
1489
1490 for( SCH_SHEET_PIN* pin : sheet->m_pins )
1491 {
1492 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
1493 m_pins.back()->SetParent( this );
1494 }
1495
1496 for( const SCH_SHEET_INSTANCE& instance : sheet->m_instances )
1497 m_instances.emplace_back( instance );
1498 }
1499
1500 return *this;
1501}
1502
1503
1504bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
1505{
1506 if( Type() != aItem.Type() )
1507 return Type() < aItem.Type();
1508
1509 const SCH_SHEET* otherSheet = static_cast<const SCH_SHEET*>( &aItem );
1510
1511 if( GetName() != otherSheet->GetName() )
1512 return GetName() < otherSheet->GetName();
1513
1514 if( GetFileName() != otherSheet->GetFileName() )
1515 return GetFileName() < otherSheet->GetFileName();
1516
1517 return false;
1518}
1519
1520
1521void SCH_SHEET::RemoveInstance( const KIID_PATH& aInstancePath )
1522{
1523 // Search for an existing path and remove it if found (should not occur)
1524 // (search from back to avoid invalidating iterator on remove)
1525 for( int ii = m_instances.size() - 1; ii >= 0; --ii )
1526 {
1527 if( m_instances[ii].m_Path == aInstancePath )
1528 {
1529 wxLogTrace( traceSchSheetPaths, "Removing sheet instance:\n"
1530 " sheet path %s\n"
1531 " page %s, from project %s.",
1532 aInstancePath.AsString(),
1533 m_instances[ii].m_PageNumber,
1534 m_instances[ii].m_ProjectName );
1535
1536 m_instances.erase( m_instances.begin() + ii );
1537 }
1538 }
1539}
1540
1541
1543{
1544 SCH_SHEET_INSTANCE oldInstance;
1545
1546 if( getInstance( oldInstance, aInstance.m_Path ) )
1547 RemoveInstance( aInstance.m_Path );
1548
1549 m_instances.emplace_back( aInstance );
1550
1551}
1552
1553
1555{
1556 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1557 {
1558 // if aSheetPath is found, nothing to do:
1559 if( instance.m_Path == aPath )
1560 return false;
1561 }
1562
1563 wxLogTrace( traceSchSheetPaths, wxT( "Adding instance `%s` to sheet `%s`." ),
1564 aPath.AsString(),
1565 ( GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : GetName() );
1566
1567 SCH_SHEET_INSTANCE instance;
1568
1569 instance.m_Path = aPath;
1570
1571 // This entry does not exist: add it with an empty page number.
1572 m_instances.emplace_back( instance );
1573 return true;
1574}
1575
1576
1577bool SCH_SHEET::getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
1578 bool aTestFromEnd ) const
1579{
1580 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1581 {
1582 if( !aTestFromEnd )
1583 {
1584 if( instance.m_Path == aSheetPath )
1585 {
1586 aInstance = instance;
1587 return true;
1588 }
1589 }
1590 else if( instance.m_Path.EndsWith( aSheetPath ) )
1591 {
1592 aInstance = instance;
1593 return true;
1594 }
1595 }
1596
1597 return false;
1598}
1599
1600
1602{
1603 for( SCH_SHEET_INSTANCE& instance : m_instances )
1604 {
1605 if( instance.m_Path == aSheetPath )
1606 return &instance;
1607 }
1608
1609 return nullptr;
1610}
1611
1612
1613const SCH_SHEET_INSTANCE* SCH_SHEET::getInstance( const KIID_PATH& aSheetPath ) const
1614{
1615 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1616 {
1617 if( instance.m_Path == aSheetPath )
1618 return &instance;
1619 }
1620
1621 return nullptr;
1622}
1623
1624
1626{
1627 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1628 {
1629 if( instance.m_Path.size() == 0 )
1630 return true;
1631 }
1632
1633 return false;
1634}
1635
1636
1638{
1639 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1640 {
1641 if( instance.m_Path.size() == 0 )
1642 return instance;
1643 }
1644
1645 wxFAIL;
1646
1648
1649 return dummy;
1650}
1651
1652
1653wxString SCH_SHEET::getPageNumber( const KIID_PATH& aParentPath ) const
1654{
1655 wxString pageNumber;
1656
1657 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1658 {
1659 if( instance.m_Path == aParentPath )
1660 {
1661 pageNumber = instance.m_PageNumber;
1662 break;
1663 }
1664 }
1665
1666 return pageNumber;
1667}
1668
1669
1670void SCH_SHEET::setPageNumber( const KIID_PATH& aPath, const wxString& aPageNumber )
1671{
1672 for( SCH_SHEET_INSTANCE& instance : m_instances )
1673 {
1674 if( instance.m_Path == aPath )
1675 {
1676 instance.m_PageNumber = aPageNumber;
1677 break;
1678 }
1679 }
1680}
1681
1682
1684{
1685 // Avoid self comparison.
1686 if( &aOther == this )
1687 return false;
1688
1689 // A difference in the instance data count implies a page numbering change.
1690 if( GetInstances().size() != aOther.GetInstances().size() )
1691 return true;
1692
1693 std::vector<SCH_SHEET_INSTANCE> instances = GetInstances();
1694 std::vector<SCH_SHEET_INSTANCE> otherInstances = aOther.GetInstances();
1695
1696 // Sorting may not be necessary but there is no guarantee that sheet
1697 // instance data will be in the correct KIID_PATH order. We should
1698 // probably use a std::map instead of a std::vector to store the sheet
1699 // instance data.
1700 std::sort( instances.begin(), instances.end(),
1701 []( const SCH_SHEET_INSTANCE& aLhs, const SCH_SHEET_INSTANCE& aRhs )
1702 {
1703 if( aLhs.m_Path > aRhs.m_Path )
1704 return true;
1705
1706 return false;
1707 } );
1708 std::sort( otherInstances.begin(), otherInstances.end(),
1709 []( const SCH_SHEET_INSTANCE& aLhs, const SCH_SHEET_INSTANCE& aRhs )
1710 {
1711 if( aLhs.m_Path > aRhs.m_Path )
1712 return true;
1713
1714 return false;
1715 } );
1716
1717 auto itThis = instances.begin();
1718 auto itOther = otherInstances.begin();
1719
1720 while( itThis != instances.end() )
1721 {
1722 if( ( itThis->m_Path == itOther->m_Path )
1723 && ( itThis->m_PageNumber != itOther->m_PageNumber ) )
1724 {
1725 return true;
1726 }
1727
1728 itThis++;
1729 itOther++;
1730 }
1731
1732 return false;
1733}
1734
1735
1736int SCH_SHEET::ComparePageNum( const wxString& aPageNumberA, const wxString& aPageNumberB )
1737{
1738 if( aPageNumberA == aPageNumberB )
1739 return 0; // A == B
1740
1741 // First sort numerically if the page numbers are integers
1742 long pageA, pageB;
1743 bool isIntegerPageA = aPageNumberA.ToLong( &pageA );
1744 bool isIntegerPageB = aPageNumberB.ToLong( &pageB );
1745
1746 if( isIntegerPageA && isIntegerPageB )
1747 {
1748 if( pageA < pageB )
1749 return -1; //A < B
1750 else
1751 return 1; // A > B
1752 }
1753
1754 // Numerical page numbers always before strings
1755 if( isIntegerPageA )
1756 return -1; //A < B
1757 else if( isIntegerPageB )
1758 return 1; // A > B
1759
1760 // If not numeric, then sort as strings using natural sort
1761 int result = StrNumCmp( aPageNumberA, aPageNumberB );
1762
1763 // Divide by zero bad.
1764 wxCHECK( result != 0, 0 );
1765
1767
1768 return result;
1769}
1770
1771
1772bool SCH_SHEET::operator==( const SCH_ITEM& aOther ) const
1773{
1774 if( Type() != aOther.Type() )
1775 return false;
1776
1777 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
1778
1779 if( m_pos != other->m_pos )
1780 return false;
1781
1782 if( m_size != other->m_size )
1783 return false;
1784
1785 if( GetExcludedFromSim() != other->GetExcludedFromSim() )
1786 return false;
1787
1788 if( GetExcludedFromBOM() != other->GetExcludedFromBOM() )
1789 return false;
1790
1791 if( GetExcludedFromBoard() != other->GetExcludedFromBoard() )
1792 return false;
1793
1794 if( GetDNP() != other->GetDNP() )
1795 return false;
1796
1797 if( GetBorderColor() != other->GetBorderColor() )
1798 return false;
1799
1800 if( GetBackgroundColor() != other->GetBackgroundColor() )
1801 return false;
1802
1803 if( GetBorderWidth() != other->GetBorderWidth() )
1804 return false;
1805
1806 if( GetFields().size() != other->GetFields().size() )
1807 return false;
1808
1809 for( size_t i = 0; i < GetFields().size(); ++i )
1810 {
1811 if( !( GetFields()[i] == other->GetFields()[i] ) )
1812 return false;
1813 }
1814
1815 return true;
1816}
1817
1818
1819double SCH_SHEET::Similarity( const SCH_ITEM& aOther ) const
1820{
1821 if( Type() != aOther.Type() )
1822 return 0.0;
1823
1824 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
1825
1826 if( m_screen->GetFileName() == other->m_screen->GetFileName() )
1827 return 1.0;
1828
1829 return 0.0;
1830}
1831
1832
1833void SCH_SHEET::AddVariant( const SCH_SHEET_PATH& aInstance, const SCH_SHEET_VARIANT& aVariant )
1834{
1835 SCH_SHEET_INSTANCE* instance = getInstance( aInstance );
1836
1837 // The instance path must already exist.
1838 if( !instance )
1839 return;
1840
1841 instance->m_Variants.insert( std::make_pair( aVariant.m_Name, aVariant ) );
1842}
1843
1844
1845void SCH_SHEET::DeleteVariant( const KIID_PATH& aPath, const wxString& aVariantName )
1846{
1847 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
1848
1849 // The instance path must already exist.
1850 if( !instance || !instance->m_Variants.contains( aVariantName ) )
1851 return;
1852
1853 instance->m_Variants.erase( aVariantName );
1854}
1855
1856
1857void SCH_SHEET::RenameVariant( const KIID_PATH& aPath, const wxString& aOldName,
1858 const wxString& aNewName )
1859{
1860 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
1861
1862 // The instance path must already exist and contain the old variant.
1863 if( !instance || !instance->m_Variants.contains( aOldName ) )
1864 return;
1865
1866 // Get the variant data, update the name, and re-insert with new key
1867 SCH_SHEET_VARIANT variant = instance->m_Variants[aOldName];
1868 variant.m_Name = aNewName;
1869 instance->m_Variants.erase( aOldName );
1870 instance->m_Variants.insert( std::make_pair( aNewName, variant ) );
1871}
1872
1873
1874void SCH_SHEET::CopyVariant( const KIID_PATH& aPath, const wxString& aSourceVariant,
1875 const wxString& aNewVariant )
1876{
1877 SCH_SHEET_INSTANCE* instance = getInstance( aPath );
1878
1879 // The instance path must already exist and contain the source variant.
1880 if( !instance || !instance->m_Variants.contains( aSourceVariant ) )
1881 return;
1882
1883 // Copy the variant data with a new name
1884 SCH_SHEET_VARIANT variant = instance->m_Variants[aSourceVariant];
1885 variant.m_Name = aNewVariant;
1886 instance->m_Variants.insert( std::make_pair( aNewVariant, variant ) );
1887}
1888
1889
1890void SCH_SHEET::SetDNP( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
1891{
1892 if( !aInstance || aVariantName.IsEmpty() )
1893 {
1894 m_DNP = aEnable;
1895 return;
1896 }
1897
1898 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
1899
1900 wxCHECK_MSG( instance, /* void */,
1901 wxString::Format( wxS( "Cannot get DNP attribute for invalid sheet path '%s'." ),
1902 aInstance->PathHumanReadable() ) );
1903
1904 if( aVariantName.IsEmpty() )
1905 {
1906 m_DNP = aEnable;
1907 }
1908 else
1909 {
1910 if( instance->m_Variants.contains( aVariantName ) && ( aEnable != instance->m_Variants[aVariantName].m_DNP ) )
1911 {
1912 instance->m_Variants[aVariantName].m_DNP = aEnable;
1913 }
1914 else
1915 {
1916 SCH_SHEET_VARIANT variant( aVariantName );
1917
1918 variant.InitializeAttributes( *this );
1919 variant.m_DNP = aEnable;
1920 AddVariant( *aInstance, variant );
1921 }
1922 }
1923}
1924
1925
1926bool SCH_SHEET::GetDNP( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
1927{
1928 if( !aInstance || aVariantName.IsEmpty() )
1929 return m_DNP;
1930
1931 SCH_SHEET_INSTANCE instance;
1932
1933 if( !getInstance( instance, aInstance->Path() ) )
1934 return m_DNP;
1935
1936 if( aVariantName.IsEmpty() )
1937 return m_DNP;
1938 else if( instance.m_Variants.contains( aVariantName ) )
1939 return instance.m_Variants[aVariantName].m_DNP;
1940
1941 // If the variant has not been defined, return the default DNP setting.
1942 return m_DNP;
1943}
1944
1945
1947{
1948 return GetDNP( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
1949}
1950
1951
1952void SCH_SHEET::SetDNPProp( bool aEnable )
1953{
1954 SetDNP( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
1955}
1956
1957
1958void SCH_SHEET::SetExcludedFromSim( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
1959{
1960 if( !aInstance || aVariantName.IsEmpty() )
1961 {
1962 m_excludedFromSim = aEnable;
1963 return;
1964 }
1965
1966 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
1967
1968 wxCHECK_MSG( instance, /* void */,
1969 wxString::Format( wxS( "Cannot get m_excludedFromSim attribute for invalid sheet path '%s'." ),
1970 aInstance->PathHumanReadable() ) );
1971
1972 if( aVariantName.IsEmpty() )
1973 {
1974 m_excludedFromSim = aEnable;
1975 }
1976 else
1977 {
1978 if( instance->m_Variants.contains( aVariantName )
1979 && ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromSim ) )
1980 {
1981 instance->m_Variants[aVariantName].m_ExcludedFromSim = aEnable;
1982 }
1983 else
1984 {
1985 SCH_SHEET_VARIANT variant( aVariantName );
1986
1987 variant.InitializeAttributes( *this );
1988 variant.m_ExcludedFromSim = aEnable;
1989 AddVariant( *aInstance, variant );
1990 }
1991 }
1992}
1993
1994
1995bool SCH_SHEET::GetExcludedFromSim( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
1996{
1997 if( !aInstance || aVariantName.IsEmpty() )
1998 return m_excludedFromSim;
1999
2000 SCH_SHEET_INSTANCE instance;
2001
2002 if( !getInstance( instance, aInstance->Path() ) )
2003 return m_excludedFromSim;
2004
2005 if( aVariantName.IsEmpty() )
2006 return m_excludedFromSim;
2007 else if( instance.m_Variants.contains( aVariantName ) )
2008 return instance.m_Variants[aVariantName].m_ExcludedFromSim;
2009
2010 // If the variant has not been defined, return the default DNP setting.
2011 return m_excludedFromSim;
2012}
2013
2014
2016{
2017 return GetExcludedFromSim( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2018}
2019
2020
2022{
2023 SetExcludedFromSim( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2024}
2025
2026
2027void SCH_SHEET::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName )
2028{
2029 if( !aInstance || aVariantName.IsEmpty() )
2030 {
2031 m_excludedFromBOM = aEnable;
2032 return;
2033 }
2034
2035 SCH_SHEET_INSTANCE* instance = getInstance( *aInstance );
2036
2037 wxCHECK_MSG( instance, /* void */,
2038 wxString::Format( wxS( "Cannot get m_excludedFromBOM attribute for invalid sheet path '%s'." ),
2039 aInstance->PathHumanReadable() ) );
2040
2041 if( aVariantName.IsEmpty() )
2042 {
2043 m_excludedFromBOM = aEnable;
2044 }
2045 else
2046 {
2047 if( instance->m_Variants.contains( aVariantName )
2048 && ( aEnable != instance->m_Variants[aVariantName].m_ExcludedFromBOM ) )
2049 {
2050 instance->m_Variants[aVariantName].m_ExcludedFromBOM = aEnable;
2051 }
2052 else
2053 {
2054 SCH_SHEET_VARIANT variant( aVariantName );
2055
2056 variant.InitializeAttributes( *this );
2057 variant.m_ExcludedFromBOM = aEnable;
2058 AddVariant( *aInstance, variant );
2059 }
2060 }
2061}
2062
2063
2064bool SCH_SHEET::GetExcludedFromBOM( const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) const
2065{
2066 if( !aInstance || aVariantName.IsEmpty() )
2067 return m_excludedFromBOM;
2068
2069 SCH_SHEET_INSTANCE instance;
2070
2071 if( !getInstance( instance, aInstance->Path() ) )
2072 return m_excludedFromBOM;
2073
2074 if( aVariantName.IsEmpty() )
2075 return m_excludedFromBOM;
2076 else if( instance.m_Variants.contains( aVariantName ) )
2077 return instance.m_Variants[aVariantName].m_ExcludedFromBOM;
2078
2079 // If the variant has not been defined, return the default DNP setting.
2080 return m_excludedFromBOM;
2081}
2082
2083
2085{
2086 return GetExcludedFromBOM( &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2087}
2088
2089
2091{
2092 SetExcludedFromBOM( aEnable, &Schematic()->CurrentSheet(), Schematic()->GetCurrentVariant() );
2093}
2094
2095
2096#if defined(DEBUG)
2097
2098void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
2099{
2100 // XML output:
2101 wxString s = GetClass();
2102
2103 NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">" << " sheet_name=\""
2104 << TO_UTF8( GetName() ) << '"' << ">\n";
2105
2106 // show all the pins, and check the linked list integrity
2107 for( SCH_SHEET_PIN* sheetPin : m_pins )
2108 sheetPin->Show( nestLevel + 1, os );
2109
2110 NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n" << std::flush;
2111}
2112
2113#endif
2114
2115static struct SCH_SHEET_DESC
2116{
2118 {
2122
2123 propMgr.AddProperty( new PROPERTY<SCH_SHEET, wxString>( _HKI( "Sheet Name" ),
2125 .SetValidator( []( const wxAny&& aValue, EDA_ITEM* ) -> VALIDATOR_RESULT
2126 {
2127 wxString value;
2128
2129 if( !aValue.GetAs( &value ) )
2130 return {};
2131
2132 wxString msg = GetFieldValidationErrorMessage( FIELD_T::SHEET_NAME, value );
2133
2134 if( msg.empty() )
2135 return {};
2136
2137 return std::make_unique<VALIDATION_ERROR_MSG>( msg );
2138 } );
2139
2140 propMgr.AddProperty( new PROPERTY<SCH_SHEET, int>( _HKI( "Border Width" ),
2143
2144 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Border Color" ),
2146
2147 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Background Color" ),
2149
2150 const wxString groupAttributes = _HKI( "Attributes" );
2151
2152 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Board" ),
2154 groupAttributes );
2155 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Simulation" ),
2157 groupAttributes );
2158 propMgr.AddProperty(
2159 new PROPERTY<SCH_SHEET, bool>( _HKI( "Exclude From Bill of Materials" ),
2162 groupAttributes );
2163 propMgr.AddProperty( new PROPERTY<SCH_SHEET, bool>( _HKI( "Do not Populate" ),
2165 groupAttributes );
2166 }
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BITMAPS
A list of all bitmap identifiers.
@ add_hierarchical_subsheet
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr const Vec GetEnd() const
Definition box2.h:212
constexpr coord_type GetY() const
Definition box2.h:208
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr coord_type GetX() const
Definition box2.h:207
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:658
constexpr const Vec GetCenter() const
Definition box2.h:230
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr coord_type GetLeft() const
Definition box2.h:228
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr coord_type GetRight() const
Definition box2.h:217
constexpr void SetEnd(coord_type x, coord_type y)
Definition box2.h:297
constexpr coord_type GetTop() const
Definition box2.h:229
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:311
constexpr coord_type GetBottom() const
Definition box2.h:222
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:402
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:100
const KIID m_Uuid
Definition eda_item.h:528
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
EDA_ITEM * GetParent() const
Definition eda_item.h:114
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:41
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:109
void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:560
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:401
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:283
VECTOR2I GetTextSize() const
Definition eda_text.h:272
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:393
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
std::shared_ptr< wxString > m_text
Definition color4d.h:399
double a
Alpha component.
Definition color4d.h:396
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxString AsString() const
Definition kiid.cpp:365
Definition kiid.h:48
Base plotter engine class.
Definition plotter.h:136
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:167
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0)=0
virtual void HyperlinkBox(const BOX2I &aBox, const wxString &aDestinationURL)
Create a clickable hyperlink with a rectangular click area.
Definition plotter.h:506
bool GetColorMode() const
Definition plotter.h:164
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:540
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:517
virtual void SetColor(const COLOR4D &color)=0
Container for project specific data.
Definition project.h:66
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition property.h:349
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
Holds all the data relating to one schematic.
Definition schematic.h:89
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
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:104
wxString GetCurrentVariant() const
Return the current variant being edited.
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
void GetContextualTextVars(wxArrayString *aVars) const
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:188
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
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:123
FIELD_T GetId() const
Definition sch_field.h:127
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition sch_item.cpp:82
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:730
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:269
AUTOPLACE_ALGO m_fieldsAutoplaced
Definition sch_item.h:785
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:56
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:378
wxString GetClass() const override
Return the class name.
Definition sch_item.h:178
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition sch_item.cpp:789
SCH_LAYER_ID m_layer
Definition sch_item.h:781
const wxString & GetFileName() const
Definition sch_screen.h:154
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:582
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition sch_sheet.h:149
friend class SCH_SHEET_PIN
Definition sch_sheet.h:654
VECTOR2I m_size
Definition sch_sheet.h:671
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:377
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:371
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 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.
wxString GetClass() const override
Return the class name.
Definition sch_sheet.h:69
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:468
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:670
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the sheet's fields.
Definition sch_sheet.h:88
KIGFX::COLOR4D m_borderColor
Definition sch_sheet.h:673
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
bool m_excludedFromBOM
Definition sch_sheet.h:666
wxString GetName() const
Definition sch_sheet.h:137
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...
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)
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:676
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
bool m_excludedFromSim
Definition sch_sheet.h:665
void SetPosition(const VECTOR2I &aPosition) override
wxString GetFieldText(const wxString &aFieldName, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString) const
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition sch_sheet.h:152
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:658
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:663
void RenameVariant(const KIID_PATH &aPath, const wxString &aOldName, const wxString &aNewName)
KIGFX::COLOR4D m_backgroundColor
Definition sch_sheet.h:674
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)))
Definition sch_sheet.cpp:56
void SetName(const wxString &aName)
Definition sch_sheet.h:138
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.
void SetExcludedFromSimProp(bool aEnable)
VECTOR2I GetPosition() const override
Definition sch_sheet.h:491
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.
void SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
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.
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:667
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:148
std::vector< SCH_SHEET_PIN * > m_pins
Definition sch_sheet.h:662
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:146
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a @aField to the list of fields.
void setPageNumber(const KIID_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
bool IsVirtualRootSheet() const
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
int GetMinHeight(bool aFromTop) const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flags.
bool GetExcludedFromSimProp() const
void SetExcludedFromBoardProp(bool aExclude)
Definition sch_sheet.h:469
int m_borderWidth
Definition sch_sheet.h:672
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:462
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:145
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:668
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:506
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:151
Schematic symbol object.
Definition sch_symbol.h:76
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
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:408
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:407
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
RECURSE_MODE
Definition eda_item.h:52
INSPECT_RESULT
Definition eda_item.h:46
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:93
@ NO_FILL
Definition eda_shape.h:59
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:60
a few functions useful in geometry calculations.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
KIID niluuid(0)
@ LAYER_DANGLING
Definition layer_ids.h:479
@ LAYER_SHEETNAME
Definition layer_ids.h:474
@ LAYER_SHEET_BACKGROUND
Definition layer_ids.h:487
@ LAYER_HIERLABEL
Definition layer_ids.h:459
@ LAYER_SHEETFIELDS
Definition layer_ids.h:476
@ LAYER_SHEET
Definition layer_ids.h:473
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:497
@ LAYER_SHEETFILENAME
Definition layer_ids.h:475
@ LAYER_DNP_MARKER
Definition layer_ids.h:480
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:45
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:100
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define _HKI(x)
Definition page_info.cpp:44
see class PGM_BASE
#define TYPE_HASH(x)
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
Definition sch_field.h:372
int NextFieldOrdinal(const std::vector< SCH_FIELD > &aFields)
Definition sch_field.h:361
AUTOPLACE_ALGO
Definition sch_item.h:69
@ AUTOPLACE_MANUAL
Definition sch_item.h:72
@ AUTOPLACE_AUTO
Definition sch_item.h:71
int bumpToNextGrid(const int aVal, const int aDirection)
static struct SCH_SHEET_DESC _SCH_SHEET_DESC
#define MIN_SHEET_HEIGHT
Definition sch_sheet.h:41
#define MIN_SHEET_WIDTH
Definition sch_sheet.h:40
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
std::vector< FAB_LAYER_COLOR > dummy
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
bool m_PDFPropertyPopups
Definition sch_plotter.h:64
bool m_PDFHierarchicalLinks
Definition sch_plotter.h:65
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, bool aTranslateForHI)
Return a default symbol field name for a mandatory field type.
#define DO_TRANSLATE
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".
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:229
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:75
@ SCH_NO_CONNECT_T
Definition typeinfo.h:161
@ SCH_SYMBOL_T
Definition typeinfo.h:173
@ SCH_FIELD_T
Definition typeinfo.h:151
@ SCH_LOCATE_ANY_T
Definition typeinfo.h:200
@ SCH_SHEET_T
Definition typeinfo.h:176
@ SCH_HIER_LABEL_T
Definition typeinfo.h:170
@ SCH_SHEET_PIN_T
Definition typeinfo.h:175
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:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686