KiCad PCB EDA Suite
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) 1992-2023 Kicad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <cstdlib>
26#include <climits>
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 <string_utils.h>
36#include <widgets/msgpanel.h>
37#include <math/util.h> // for KiROUND
38#include <sch_sheet.h>
39#include <sch_sheet_path.h>
40#include <sch_sheet_pin.h>
41#include <sch_symbol.h>
42#include <sch_painter.h>
43#include <schematic.h>
45#include <trace_helpers.h>
46#include <pgm_base.h>
47#include <wx/log.h>
48
49// N.B. Do not change these values without transitioning the file format
50#define SHEET_NAME_CANONICAL "Sheetname"
51#define SHEET_FILE_CANONICAL "Sheetfile"
52#define USER_FIELD_CANONICAL "Field%d"
53
54
55const wxString SCH_SHEET::GetDefaultFieldName( int aFieldNdx, bool aTranslated )
56{
57 if( !aTranslated )
58 {
59 switch( aFieldNdx )
60 {
63 default: return wxString::Format( USER_FIELD_CANONICAL, aFieldNdx );
64 }
65 }
66
67 // Fixed values for the mandatory fields
68 switch( aFieldNdx )
69 {
70 case SHEETNAME: return _( SHEET_NAME_CANONICAL );
71 case SHEETFILENAME: return _( SHEET_FILE_CANONICAL );
72 default: return wxString::Format( _( USER_FIELD_CANONICAL ), aFieldNdx );
73 }
74}
75
76
77SCH_SHEET::SCH_SHEET( EDA_ITEM* aParent, const VECTOR2I& aPos, wxSize aSize,
78 FIELDS_AUTOPLACED aAutoplaceFields ) :
79 SCH_ITEM( aParent, SCH_SHEET_T )
80{
82 m_pos = aPos;
83 m_size = aSize;
84 m_screen = nullptr;
85
86 for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
87 {
88 m_fields.emplace_back( aPos, i, this, GetDefaultFieldName( i ) );
89 m_fields.back().SetVisible( true );
90
91 if( i == SHEETNAME )
92 m_fields.back().SetLayer( LAYER_SHEETNAME );
93 else if( i == SHEETFILENAME )
94 m_fields.back().SetLayer( LAYER_SHEETFILENAME );
95 else
96 m_fields.back().SetLayer( LAYER_SHEETFIELDS );
97 }
98
99 m_fieldsAutoplaced = aAutoplaceFields;
100 AutoAutoplaceFields( nullptr );
101
102 m_borderWidth = 0;
103 m_borderColor = COLOR4D::UNSPECIFIED;
104 m_backgroundColor = COLOR4D::UNSPECIFIED;
105}
106
107
109 SCH_ITEM( aSheet )
110{
111 m_pos = aSheet.m_pos;
112 m_size = aSheet.m_size;
113 m_layer = aSheet.m_layer;
114 const_cast<KIID&>( m_Uuid ) = aSheet.m_Uuid;
115 m_fields = aSheet.m_fields;
117 m_screen = aSheet.m_screen;
118
119 for( SCH_SHEET_PIN* pin : aSheet.m_pins )
120 {
121 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
122 m_pins.back()->SetParent( this );
123 }
124
125 for( SCH_FIELD& field : m_fields )
126 field.SetParent( this );
127
131 m_instances = aSheet.m_instances;
132
133 if( m_screen )
135}
136
137
139{
140 // also, look at the associated sheet & its reference count
141 // perhaps it should be deleted also.
142 if( m_screen )
143 {
145
146 if( m_screen->GetRefCount() == 0 )
147 delete m_screen;
148 }
149
150 // We own our pins; delete them
151 for( SCH_SHEET_PIN* pin : m_pins )
152 delete pin;
153}
154
155
157{
158 return new SCH_SHEET( *this );
159}
160
161
163{
164 if( aScreen == m_screen )
165 return;
166
167 if( m_screen != nullptr )
168 {
170
171 if( m_screen->GetRefCount() == 0 )
172 {
173 delete m_screen;
174 m_screen = nullptr;
175 }
176 }
177
178 m_screen = aScreen;
179
180 if( m_screen )
182}
183
184
186{
187 if( m_screen == nullptr )
188 return 0;
189
190 return m_screen->GetRefCount();
191}
192
193
195{
196 wxCHECK_MSG( Schematic(), false, "Can't call IsRootSheet without setting a schematic" );
197
198 return &Schematic()->Root() == this;
199}
200
201
202void SCH_SHEET::GetContextualTextVars( wxArrayString* aVars ) const
203{
204 auto add =
205 [&]( const wxString& aVar )
206 {
207 if( !alg::contains( *aVars, aVar ) )
208 aVars->push_back( aVar );
209 };
210
211 for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
212 add( m_fields[i].GetCanonicalName().Upper() );
213
214 for( size_t i = SHEET_MANDATORY_FIELDS; i < m_fields.size(); ++i )
215 add( m_fields[i].GetName() );
216
217 SCH_SHEET_PATH sheetPath = findSelf();
218
219 if( sheetPath.size() >= 2 )
220 {
221 sheetPath.pop_back();
222 sheetPath.Last()->GetContextualTextVars( aVars );
223 }
224 else if( Schematic() )
225 {
227 }
228
229 add( wxT( "#" ) );
230 add( wxT( "##" ) );
231 add( wxT( "SHEETPATH" ) );
232
234}
235
236
237bool SCH_SHEET::ResolveTextVar( wxString* token, int aDepth ) const
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( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
249 {
250 if( token->IsSameAs( m_fields[i].GetCanonicalName().Upper() ) )
251 {
252 *token = m_fields[i].GetShownText( aDepth + 1 );
253 return true;
254 }
255 }
256
257 for( size_t i = SHEET_MANDATORY_FIELDS; i < m_fields.size(); ++i )
258 {
259 if( token->IsSameAs( m_fields[i].GetName() ) )
260 {
261 *token = m_fields[i].GetShownText( aDepth + 1 );
262 return true;
263 }
264 }
265
266 PROJECT *project = &Schematic()->Prj();
267
268 // We cannot resolve text variables initially on load as we need to first load the screen and
269 // then parse the hierarchy. So skip the resolution if the screen isn't set yet
271 {
272 return true;
273 }
274
275 if( token->IsSameAs( wxT( "#" ) ) )
276 {
277 *token = wxString::Format( "%s", findSelf().GetPageNumber() );
278 return true;
279 }
280 else if( token->IsSameAs( wxT( "##" ) ) )
281 {
282 SCH_SHEET_LIST sheetList = Schematic()->GetSheets();
283 *token = wxString::Format( wxT( "%d" ), (int) sheetList.size() );
284 return true;
285 }
286 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
287 {
288 *token = findSelf().PathHumanReadable();
289 return true;
290 }
291
292 // See if parent can resolve it (these will recurse to ancestors)
293
294 SCH_SHEET_PATH sheetPath = findSelf();
295
296 if( sheetPath.size() >= 2 )
297 {
298 sheetPath.pop_back();
299
300 if( sheetPath.Last()->ResolveTextVar( token, aDepth + 1 ) )
301 return true;
302 }
303 else
304 {
305 if( Schematic()->ResolveTextVar( token, aDepth + 1 ) )
306 return true;
307 }
308
309 return false;
310}
311
312
314{
315 wxCHECK_RET( aItem->Type() == SCH_SHEET_T,
316 wxString::Format( wxT( "SCH_SHEET object cannot swap data with %s object." ),
317 aItem->GetClass() ) );
318
319 SCH_SHEET* sheet = ( SCH_SHEET* ) aItem;
320
321 std::swap( m_pos, sheet->m_pos );
322 std::swap( m_size, sheet->m_size );
323 m_fields.swap( sheet->m_fields );
324 std::swap( m_fieldsAutoplaced, sheet->m_fieldsAutoplaced );
325 m_pins.swap( sheet->m_pins );
326
327 // Update parent pointers after swapping.
328 for( SCH_SHEET_PIN* sheetPin : m_pins )
329 sheetPin->SetParent( this );
330
331 for( SCH_SHEET_PIN* sheetPin : sheet->m_pins )
332 sheetPin->SetParent( sheet );
333
334 for( SCH_FIELD& field : m_fields )
335 field.SetParent( this );
336
337 for( SCH_FIELD& field : sheet->m_fields )
338 field.SetParent( sheet );
339
340 std::swap( m_borderWidth, sheet->m_borderWidth );
341 std::swap( m_borderColor, sheet->m_borderColor );
342 std::swap( m_backgroundColor, sheet->m_backgroundColor );
343 std::swap( m_instances, sheet->m_instances );
344}
345
346
347void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
348{
349 m_fields = aFields;
350 int next_id = SHEET_MANDATORY_FIELDS;
351
352 for( int ii = 0; ii < int( m_fields.size() ); )
353 {
354 if( m_fields[ii].GetId() < 0 || m_fields[ii].GetId() >= ssize_t( m_fields.size() ) )
355 m_fields[ii].SetId( next_id++ );
356
357 if( m_fields[ii].GetId() != ii )
358 std::swap( m_fields[ii], m_fields[m_fields[ii].GetId()]);
359
360 if( m_fields[ii].GetId() == ii )
361 ++ii;
362 }
363
364 // Make sure that we get the UNIX variant of the file path
366}
367
368
370{
371 wxASSERT( aSheetPin != nullptr );
372 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
373
374 aSheetPin->SetParent( this );
375 m_pins.push_back( aSheetPin );
376 renumberPins();
377}
378
379
380void SCH_SHEET::RemovePin( const SCH_SHEET_PIN* aSheetPin )
381{
382 wxASSERT( aSheetPin != nullptr );
383 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
384
385 for( auto i = m_pins.begin(); i < m_pins.end(); ++i )
386 {
387 if( *i == aSheetPin )
388 {
389 m_pins.erase( i );
390 renumberPins();
391 return;
392 }
393 }
394}
395
396
397bool SCH_SHEET::HasPin( const wxString& aName ) const
398{
399 for( SCH_SHEET_PIN* pin : m_pins )
400 {
401 if( pin->GetText().CmpNoCase( aName ) == 0 )
402 return true;
403 }
404
405 return false;
406}
407
408
409bool SCH_SHEET::doIsConnected( const VECTOR2I& aPosition ) const
410{
411 for( SCH_SHEET_PIN* sheetPin : m_pins )
412 {
413 if( sheetPin->GetPosition() == aPosition )
414 return true;
415 }
416
417 return false;
418}
419
420
422{
423 int leftRight = 0;
424 int topBottom = 0;
425
426 for( SCH_SHEET_PIN* pin : m_pins )
427 {
428 switch( pin->GetSide() )
429 {
430 case SHEET_SIDE::LEFT: leftRight++; break;
431 case SHEET_SIDE::RIGHT: leftRight++; break;
432 case SHEET_SIDE::TOP: topBottom++; break;
433 case SHEET_SIDE::BOTTOM: topBottom++; break;
434 default: break;
435 }
436 }
437
438 return topBottom > 0 && leftRight == 0;
439}
440
441
443{
444 for( SCH_SHEET_PIN* pin : m_pins )
445 {
446 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
447 const SCH_HIERLABEL* HLabel = nullptr;
448
449 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
450 {
451 if( !pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
452 {
453 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
454 break;
455 }
456 }
457
458 if( HLabel == nullptr ) // Corresponding hierarchical label not found.
459 return true;
460 }
461
462 return false;
463}
464
465
466int bumpToNextGrid( const int aVal, const int aDirection )
467{
468 constexpr int gridSize = schIUScale.MilsToIU( 50 );
469
470 int base = aVal / gridSize;
471 int excess = abs( aVal % gridSize );
472
473 if( aDirection > 0 )
474 {
475 return ( base + 1 ) * gridSize;
476 }
477 else if( excess > 0 )
478 {
479 return ( base ) * gridSize;
480 }
481 else
482 {
483 return ( base - 1 ) * gridSize;
484 }
485}
486
487
488int SCH_SHEET::GetMinWidth( bool aFromLeft ) const
489{
490 int pinsLeft = m_pos.x + m_size.x;
491 int pinsRight = m_pos.x;
492
493 for( size_t i = 0; i < m_pins.size(); i++ )
494 {
495 SHEET_SIDE edge = m_pins[i]->GetSide();
496
497 if( edge == SHEET_SIDE::TOP || edge == SHEET_SIDE::BOTTOM )
498 {
499 BOX2I pinRect = m_pins[i]->GetBoundingBox();
500
501 pinsLeft = std::min( pinsLeft, pinRect.GetLeft() );
502 pinsRight = std::max( pinsRight, pinRect.GetRight() );
503 }
504 }
505
506 pinsLeft = bumpToNextGrid( pinsLeft, -1 );
507 pinsRight = bumpToNextGrid( pinsRight, 1 );
508
509 int pinMinWidth;
510
511 if( pinsLeft >= pinsRight )
512 pinMinWidth = 0;
513 else if( aFromLeft )
514 pinMinWidth = pinsRight - m_pos.x;
515 else
516 pinMinWidth = m_pos.x + m_size.x - pinsLeft;
517
518 return std::max( pinMinWidth, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
519}
520
521
522int SCH_SHEET::GetMinHeight( bool aFromTop ) const
523{
524 int pinsTop = m_pos.y + m_size.y;
525 int pinsBottom = m_pos.y;
526
527 for( size_t i = 0; i < m_pins.size(); i++ )
528 {
529 SHEET_SIDE edge = m_pins[i]->GetSide();
530
531 if( edge == SHEET_SIDE::RIGHT || edge == SHEET_SIDE::LEFT )
532 {
533 BOX2I pinRect = m_pins[i]->GetBoundingBox();
534
535 pinsTop = std::min( pinsTop, pinRect.GetTop() );
536 pinsBottom = std::max( pinsBottom, pinRect.GetBottom() );
537 }
538 }
539
540 pinsTop = bumpToNextGrid( pinsTop, -1 );
541 pinsBottom = bumpToNextGrid( pinsBottom, 1 );
542
543 int pinMinHeight;
544
545 if( pinsTop >= pinsBottom )
546 pinMinHeight = 0;
547 else if( aFromTop )
548 pinMinHeight = pinsBottom - m_pos.y;
549 else
550 pinMinHeight = m_pos.y + m_size.y - pinsTop;
551
552 return std::max( pinMinHeight, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
553}
554
555
557{
558 std::vector<SCH_SHEET_PIN*> pins = m_pins;
559
560 m_pins.clear();
561
562 for( SCH_SHEET_PIN* pin : pins )
563 {
564 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
565 const SCH_HIERLABEL* HLabel = nullptr;
566
567 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
568 {
569 if( pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) == 0 )
570 {
571 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
572 break;
573 }
574 }
575
576 if( HLabel )
577 m_pins.push_back( pin );
578 }
579}
580
581
583{
584 for( SCH_SHEET_PIN* pin : m_pins )
585 {
586 if( pin->HitTest( aPosition ) )
587 return pin;
588 }
589
590 return nullptr;
591}
592
593
595{
596 if( GetBorderWidth() > 0 )
597 return GetBorderWidth();
598
599 if( Schematic() )
601
603}
604
605
606void SCH_SHEET::AutoplaceFields( SCH_SCREEN* aScreen, bool /* aManual */ )
607{
608 VECTOR2I textSize = m_fields[SHEETNAME].GetTextSize();
609 int borderMargin = KiROUND( GetPenWidth() / 2.0 ) + 4;
610 int margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.5 );
611
613 {
614 m_fields[SHEETNAME].SetTextPos( m_pos + VECTOR2I( -margin, m_size.y ) );
615 m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
616 m_fields[ SHEETNAME ].SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
617 m_fields[ SHEETNAME ].SetTextAngle( ANGLE_VERTICAL );
618 }
619 else
620 {
621 m_fields[SHEETNAME].SetTextPos( m_pos + VECTOR2I( 0, -margin ) );
622 m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
623 m_fields[ SHEETNAME ].SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
624 m_fields[ SHEETNAME ].SetTextAngle( ANGLE_HORIZONTAL );
625 }
626
627 textSize = m_fields[ SHEETFILENAME ].GetTextSize();
628 margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.4 );
629
631 {
632 m_fields[SHEETFILENAME].SetTextPos( m_pos + VECTOR2I( m_size.x + margin, m_size.y ) );
633 m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
634 m_fields[ SHEETFILENAME ].SetVertJustify( GR_TEXT_V_ALIGN_TOP );
635 m_fields[ SHEETFILENAME ].SetTextAngle( ANGLE_VERTICAL );
636 }
637 else
638 {
639 m_fields[SHEETFILENAME].SetTextPos( m_pos + VECTOR2I( 0, m_size.y + margin ) );
640 m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
641 m_fields[ SHEETFILENAME ].SetVertJustify( GR_TEXT_V_ALIGN_TOP );
642 m_fields[ SHEETFILENAME ].SetTextAngle( ANGLE_HORIZONTAL );
643 }
644
646}
647
648
649void SCH_SHEET::ViewGetLayers( int aLayers[], int& aCount ) const
650{
651 aCount = 7;
652 aLayers[0] = LAYER_HIERLABEL;
653 aLayers[1] = LAYER_SHEETNAME;
654 aLayers[2] = LAYER_SHEETFILENAME;
655 aLayers[3] = LAYER_SHEETFIELDS;
656 aLayers[4] = LAYER_SHEET;
657 aLayers[5] = LAYER_SHEET_BACKGROUND;
658 aLayers[6] = LAYER_SELECTION_SHADOWS;
659}
660
661
663{
664 VECTOR2I end;
665 BOX2I box( m_pos, m_size );
666 int lineWidth = GetPenWidth();
667 int textLength = 0;
668
669 // Calculate bounding box X size:
670 end.x = std::max( m_size.x, textLength );
671
672 // Calculate bounding box pos:
673 end.y = m_size.y;
674 end += m_pos;
675
676 box.SetEnd( end );
677 box.Inflate( lineWidth / 2 );
678
679 return box;
680}
681
682
684{
685 BOX2I bbox = GetBodyBoundingBox();
686
687 for( const SCH_FIELD& field : m_fields )
688 bbox.Merge( field.GetBoundingBox() );
689
690 return bbox;
691}
692
693
695{
696 BOX2I box( m_pos, m_size );
697 return box.GetCenter();
698}
699
700
702{
703 int n = 0;
704
705 if( m_screen )
706 {
707 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SYMBOL_T ) )
708 {
709 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
710
711 if( symbol->GetField( VALUE_FIELD )->GetText().GetChar( 0 ) != '#' )
712 n++;
713 }
714
715 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
716 n += static_cast<const SCH_SHEET*>( aItem )->SymbolCount();
717 }
718
719 return n;
720}
721
722
723bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
724{
725 if( m_screen )
726 {
727 // Only check the root sheet once and don't recurse.
728 if( !GetParent() )
729 {
730 if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
731 {
732 *aScreen = m_screen;
733 return true;
734 }
735 }
736
737 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
738 {
739 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
740 SCH_SCREEN* screen = sheet->m_screen;
741
742 // Must use the screen's path (which is always absolute) rather than the
743 // sheet's (which could be relative).
744 if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
745 {
746 *aScreen = screen;
747 return true;
748 }
749
750 if( sheet->SearchHierarchy( aFilename, aScreen ) )
751 return true;
752 }
753 }
754
755 return false;
756}
757
758
760{
761 if( m_screen )
762 {
763 aList->push_back( this );
764
765 if( m_screen == aScreen )
766 return true;
767
768 for( EDA_ITEM* item : m_screen->Items().OfType( SCH_SHEET_T ) )
769 {
770 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
771
772 if( sheet->LocatePathOfScreen( aScreen, aList ) )
773 return true;
774 }
775
776 aList->pop_back();
777 }
778
779 return false;
780}
781
782
784{
785 int count = 1; //1 = this!!
786
787 if( m_screen )
788 {
789 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
790 count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
791 }
792
793 return count;
794}
795
796
797void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
798{
799 aList.emplace_back( _( "Sheet Name" ), m_fields[ SHEETNAME ].GetText() );
800
801 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
802 {
803 SCH_SHEET_PATH path = schframe->GetCurrentSheet();
804 path.push_back( this );
805
806 aList.emplace_back( _( "Hierarchical Path" ), path.PathHumanReadable( false, true ) );
807 }
808
809 aList.emplace_back( _( "File Name" ), m_fields[ SHEETFILENAME ].GetText() );
810}
811
812
813void SCH_SHEET::Move( const VECTOR2I& aMoveVector )
814{
815 m_pos += aMoveVector;
816
817 for( SCH_SHEET_PIN* pin : m_pins )
818 pin->Move( aMoveVector );
819
820 for( SCH_FIELD& field : m_fields )
821 field.Move( aMoveVector );
822}
823
824
825void SCH_SHEET::Rotate( const VECTOR2I& aCenter )
826{
827 VECTOR2I prev = m_pos;
828
829 RotatePoint( m_pos, aCenter, ANGLE_90 );
831
832 if( m_size.x < 0 )
833 {
834 m_pos.x += m_size.x;
835 m_size.x = -m_size.x;
836 }
837
838 if( m_size.y < 0 )
839 {
840 m_pos.y += m_size.y;
841 m_size.y = -m_size.y;
842 }
843
844 // Pins must be rotated first as that's how we determine vertical vs horizontal
845 // orientation for auto-placement
846 for( SCH_SHEET_PIN* sheetPin : m_pins )
847 sheetPin->Rotate( aCenter );
848
850 {
851 AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
852 }
853 else
854 {
855 // Move the fields to the new position because the parent itself has moved.
856 for( SCH_FIELD& field : m_fields )
857 {
858 VECTOR2I pos = field.GetTextPos();
859 pos.x -= prev.x - m_pos.x;
860 pos.y -= prev.y - m_pos.y;
861 field.SetTextPos( pos );
862 }
863 }
864}
865
866
868{
869 int dy = m_pos.y;
870
871 MIRROR( m_pos.y, aCenter );
872 m_pos.y -= m_size.y;
873 dy -= m_pos.y; // 0,dy is the move vector for this transform
874
875 for( SCH_SHEET_PIN* sheetPin : m_pins )
876 sheetPin->MirrorVertically( aCenter );
877
878 for( SCH_FIELD& field : m_fields )
879 {
880 VECTOR2I pos = field.GetTextPos();
881 pos.y -= dy;
882 field.SetTextPos( pos );
883 }
884}
885
886
888{
889 int dx = m_pos.x;
890
891 MIRROR( m_pos.x, aCenter );
892 m_pos.x -= m_size.x;
893 dx -= m_pos.x; // dx,0 is the move vector for this transform
894
895 for( SCH_SHEET_PIN* sheetPin : m_pins )
896 sheetPin->MirrorHorizontally( aCenter );
897
898 for( SCH_FIELD& field : m_fields )
899 {
900 VECTOR2I pos = field.GetTextPos();
901 pos.x -= dx;
902 field.SetTextPos( pos );
903 }
904}
905
906
907void SCH_SHEET::SetPosition( const VECTOR2I& aPosition )
908{
909 // Remember the sheet and all pin sheet positions must be
910 // modified. So use Move function to do that.
911 Move( aPosition - m_pos );
912}
913
914
915void SCH_SHEET::Resize( const wxSize& aSize )
916{
917 if( aSize == m_size )
918 return;
919
920 m_size = aSize;
921
922 // Move the fields if we're in autoplace mode
924 AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
925
926 // Move the sheet labels according to the new sheet size.
927 for( SCH_SHEET_PIN* sheetPin : m_pins )
928 sheetPin->ConstrainOnEdge( sheetPin->GetPosition() );
929}
930
931
932bool SCH_SHEET::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
933{
934 // Sheets are searchable via the child field and pin item text.
935 return false;
936}
937
938
940{
941 int id = 2;
942
943 for( SCH_SHEET_PIN* pin : m_pins )
944 {
945 pin->SetNumber( id );
946 id++;
947 }
948}
949
950
952{
953 wxCHECK_MSG( Schematic(), SCH_SHEET_PATH(), "Can't call findSelf without a schematic" );
954
955 SCH_SHEET_PATH sheetPath = Schematic()->CurrentSheet();
956
957 while( !sheetPath.empty() && sheetPath.Last() != this )
958 sheetPath.pop_back();
959
960 if( sheetPath.empty() )
961 {
962 // If we weren't in the hierarchy, then we must be a child of the current sheet.
963 sheetPath = Schematic()->CurrentSheet();
964 sheetPath.push_back( const_cast<SCH_SHEET*>( this ) );
965 }
966
967 return sheetPath;
968}
969
970
971void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
972{
973 for( SCH_SHEET_PIN* sheetPin : m_pins )
974 {
975 wxCHECK2_MSG( sheetPin->Type() == SCH_SHEET_PIN_T, continue,
976 wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) );
977
978 sheetPin->GetEndPoints( aItemList );
979 }
980}
981
982
983bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
984 const SCH_SHEET_PATH* aPath )
985{
986 bool changed = false;
987
988 for( SCH_SHEET_PIN* sheetPin : m_pins )
989 changed |= sheetPin->UpdateDanglingState( aItemList );
990
991 return changed;
992}
993
994
995std::vector<VECTOR2I> SCH_SHEET::GetConnectionPoints() const
996{
997 std::vector<VECTOR2I> retval;
998
999 for( SCH_SHEET_PIN* sheetPin : m_pins )
1000 retval.push_back( sheetPin->GetPosition() );
1001
1002 return retval;
1003}
1004
1005
1006INSPECT_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData,
1007 const std::vector<KICAD_T>& aScanTypes )
1008{
1009 for( KICAD_T scanType : aScanTypes )
1010 {
1011 // If caller wants to inspect my type
1012 if( scanType == SCH_LOCATE_ANY_T || scanType == Type() )
1013 {
1014 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1015 return INSPECT_RESULT::QUIT;
1016 }
1017
1018 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1019 {
1020 // Test the sheet fields.
1021 for( SCH_FIELD& field : m_fields )
1022 {
1023 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1024 return INSPECT_RESULT::QUIT;
1025 }
1026 }
1027
1028 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_SHEET_PIN_T )
1029 {
1030 // Test the sheet labels.
1031 for( SCH_SHEET_PIN* sheetPin : m_pins )
1032 {
1033 if( INSPECT_RESULT::QUIT == aInspector( sheetPin, this ) )
1034 return INSPECT_RESULT::QUIT;
1035 }
1036 }
1037 }
1038
1040}
1041
1042
1043void SCH_SHEET::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
1044{
1045 for( SCH_FIELD& field : m_fields )
1046 aFunction( &field );
1047
1048 for( SCH_SHEET_PIN* pin : m_pins )
1049 aFunction( pin );
1050}
1051
1052
1053wxString SCH_SHEET::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
1054{
1055 return wxString::Format( _( "Hierarchical Sheet %s" ),
1056 m_fields[ SHEETNAME ].GetText() );
1057}
1058
1059
1061{
1063}
1064
1065
1066bool SCH_SHEET::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1067{
1068 BOX2I rect = GetBodyBoundingBox();
1069
1070 rect.Inflate( aAccuracy );
1071
1072 return rect.Contains( aPosition );
1073}
1074
1075
1076bool SCH_SHEET::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1077{
1078 BOX2I rect = aRect;
1079
1080 rect.Inflate( aAccuracy );
1081
1082 if( aContained )
1083 return rect.Contains( GetBodyBoundingBox() );
1084
1085 return rect.Intersects( GetBodyBoundingBox() );
1086}
1087
1088
1089void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground ) const
1090{
1091 if( aBackground && !aPlotter->GetColorMode() )
1092 return;
1093
1094 auto* settings = dynamic_cast<KIGFX::SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
1095 bool override = settings ? settings->m_OverrideItemColors : false;
1096 COLOR4D borderColor = GetBorderColor();
1097 COLOR4D backgroundColor = GetBackgroundColor();
1098
1099 if( override || borderColor == COLOR4D::UNSPECIFIED )
1100 borderColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET );
1101
1102 if( override || backgroundColor == COLOR4D::UNSPECIFIED )
1103 backgroundColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET_BACKGROUND );
1104
1105 if( aBackground )
1106 {
1107 aPlotter->SetColor( backgroundColor );
1108 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::FILLED_SHAPE, 1 );
1109 }
1110 else
1111 {
1112 aPlotter->SetColor( borderColor );
1113
1114 int penWidth = std::max( GetPenWidth(), aPlotter->RenderSettings()->GetMinPenWidth() );
1115 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::NO_FILL, penWidth );
1116 }
1117
1118 // Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
1119 std::vector<wxString> properties;
1120
1121 properties.emplace_back( EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1122
1123 for( const SCH_FIELD& field : GetFields() )
1124 {
1125 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1126 field.GetName(),
1127 field.GetShownText() ) );
1128 }
1129
1130 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
1131
1132 // Plot sheet pins
1133 for( SCH_SHEET_PIN* sheetPin : m_pins )
1134 sheetPin->Plot( aPlotter, aBackground );
1135
1136 // Plot the fields
1137 for( const SCH_FIELD& field : m_fields )
1138 field.Plot( aPlotter, aBackground );
1139}
1140
1141
1142void SCH_SHEET::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
1143{
1144 wxDC* DC = aSettings->GetPrintDC();
1145 VECTOR2I pos = m_pos + aOffset;
1146 int lineWidth = std::max( GetPenWidth(), aSettings->GetDefaultPenWidth() );
1147 const auto* settings = dynamic_cast<const KIGFX::SCH_RENDER_SETTINGS*>( aSettings );
1148 bool override = settings && settings->m_OverrideItemColors;
1149 COLOR4D border = GetBorderColor();
1150 COLOR4D background = GetBackgroundColor();
1151
1152 if( override || border == COLOR4D::UNSPECIFIED )
1153 border = aSettings->GetLayerColor( LAYER_SHEET );
1154
1155 if( override || background == COLOR4D::UNSPECIFIED )
1156 background = aSettings->GetLayerColor( LAYER_SHEET_BACKGROUND );
1157
1158 if( GetGRForceBlackPenState() ) // printing in black & white
1159 background = COLOR4D::UNSPECIFIED;
1160
1161 if( background != COLOR4D::UNSPECIFIED )
1162 GRFilledRect( DC, pos, pos + m_size, 0, background, background );
1163
1164 GRRect( DC, pos, pos + m_size, lineWidth, border );
1165
1166 for( SCH_FIELD& field : m_fields )
1167 field.Print( aSettings, aOffset );
1168
1169 for( SCH_SHEET_PIN* sheetPin : m_pins )
1170 sheetPin->Print( aSettings, aOffset );
1171}
1172
1173
1175{
1176 wxCHECK_MSG( Type() == aItem.Type(), *this,
1177 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
1178 GetClass() );
1179
1180 if( &aItem != this )
1181 {
1182 SCH_ITEM::operator=( aItem );
1183
1184 SCH_SHEET* sheet = (SCH_SHEET*) &aItem;
1185
1186 m_pos = sheet->m_pos;
1187 m_size = sheet->m_size;
1188 m_fields = sheet->m_fields;
1189
1190 for( SCH_SHEET_PIN* pin : sheet->m_pins )
1191 {
1192 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
1193 m_pins.back()->SetParent( this );
1194 }
1195
1196 for( const SCH_SHEET_INSTANCE& instance : sheet->m_instances )
1197 m_instances.emplace_back( instance );
1198 }
1199
1200 return *this;
1201}
1202
1203
1204bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
1205{
1206 if( Type() != aItem.Type() )
1207 return Type() < aItem.Type();
1208
1209 auto sheet = static_cast<const SCH_SHEET*>( &aItem );
1210
1211 if (m_fields[ SHEETNAME ].GetText() != sheet->m_fields[ SHEETNAME ].GetText() )
1212 return m_fields[ SHEETNAME ].GetText() < sheet->m_fields[ SHEETNAME ].GetText();
1213
1214 if (m_fields[ SHEETFILENAME ].GetText() != sheet->m_fields[ SHEETFILENAME ].GetText() )
1215 return m_fields[ SHEETFILENAME ].GetText() < sheet->m_fields[ SHEETFILENAME ].GetText();
1216
1217 return false;
1218}
1219
1220
1222{
1223 wxCHECK( aSheetPath.IsFullPath(), false );
1224 wxCHECK( !aSheetPath.Last() || ( aSheetPath.Last()->m_Uuid != m_Uuid ), false );
1225
1226 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1227 {
1228 // if aSheetPath is found, nothing to do:
1229 if( instance.m_Path == aSheetPath.Path() )
1230 return false;
1231 }
1232
1233 wxLogTrace( traceSchSheetPaths, wxT( "Adding instance `%s` to sheet `%s`." ),
1234 aSheetPath.Path().AsString(),
1235 ( GetName().IsEmpty() ) ? wxT( "root" ) : GetName() );
1236
1237 SCH_SHEET_INSTANCE instance;
1238
1239 instance.m_Path = aSheetPath.Path();
1240
1241 // This entry does not exist: add it with an empty page number.
1242 m_instances.emplace_back( instance );
1243 return true;
1244}
1245
1246
1247bool SCH_SHEET::getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
1248 bool aTestFromEnd ) const
1249{
1250 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1251 {
1252 if( !aTestFromEnd )
1253 {
1254 if( instance.m_Path == aSheetPath )
1255 {
1256 aInstance = instance;
1257 return true;
1258 }
1259 }
1260 else if( instance.m_Path.EndsWith( aSheetPath ) )
1261 {
1262 aInstance = instance;
1263 return true;
1264 }
1265 }
1266
1267 return false;
1268}
1269
1270
1272{
1273 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1274 {
1275 if( instance.m_Path.size() == 0 )
1276 return true;
1277 }
1278
1279 return false;
1280}
1281
1282
1284{
1285 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1286 {
1287 if( instance.m_Path.size() == 0 )
1288 return instance;
1289 }
1290
1291 wxFAIL;
1292
1294
1295 return dummy;
1296}
1297
1298
1299wxString SCH_SHEET::getPageNumber( const SCH_SHEET_PATH& aSheetPath ) const
1300{
1301 wxCHECK( aSheetPath.IsFullPath(), wxEmptyString );
1302 wxCHECK( !aSheetPath.Last() || ( aSheetPath.Last()->m_Uuid != m_Uuid ), wxEmptyString );
1303
1304 wxString pageNumber;
1305 KIID_PATH path = aSheetPath.Path();
1306
1307 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1308 {
1309 if( instance.m_Path == path )
1310 {
1311 pageNumber = instance.m_PageNumber;
1312 break;
1313 }
1314 }
1315
1316 return pageNumber;
1317}
1318
1319
1320void SCH_SHEET::setPageNumber( const SCH_SHEET_PATH& aSheetPath, const wxString& aPageNumber )
1321{
1322 wxCHECK( aSheetPath.IsFullPath(), /* void */ );
1323 wxCHECK( !aSheetPath.Last() || ( aSheetPath.Last()->m_Uuid != m_Uuid ), /* void */ );
1324
1325 KIID_PATH path = aSheetPath.Path();
1326
1327 for( SCH_SHEET_INSTANCE& instance : m_instances )
1328 {
1329 if( instance.m_Path == path )
1330 {
1331 instance.m_PageNumber = aPageNumber;
1332 break;
1333 }
1334 }
1335}
1336
1337
1338int SCH_SHEET::ComparePageNum( const wxString& aPageNumberA, const wxString& aPageNumberB )
1339{
1340 if( aPageNumberA == aPageNumberB )
1341 return 0; // A == B
1342
1343 // First sort numerically if the page numbers are integers
1344 long pageA, pageB;
1345 bool isIntegerPageA = aPageNumberA.ToLong( &pageA );
1346 bool isIntegerPageB = aPageNumberB.ToLong( &pageB );
1347
1348 if( isIntegerPageA && isIntegerPageB )
1349 {
1350 if( pageA < pageB )
1351 return -1; //A < B
1352 else
1353 return 1; // A > B
1354 }
1355
1356 // Numerical page numbers always before strings
1357 if( isIntegerPageA )
1358 return -1; //A < B
1359 else if( isIntegerPageB )
1360 return 1; // A > B
1361
1362 // If not numeric, then sort as strings using natural sort
1363 int result = StrNumCmp( aPageNumberA, aPageNumberB );
1364
1365 // Divide by zero bad.
1366 wxCHECK( result != 0, 0 );
1367
1368 result = result / std::abs( result );
1369
1370 return result;
1371}
1372
1373
1374#if defined(DEBUG)
1375
1376void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
1377{
1378 // XML output:
1379 wxString s = GetClass();
1380
1381 NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">" << " sheet_name=\""
1382 << TO_UTF8( m_fields[ SHEETNAME ].GetText() ) << '"' << ">\n";
1383
1384 // show all the pins, and check the linked list integrity
1385 for( SCH_SHEET_PIN* sheetPin : m_pins )
1386 sheetPin->Show( nestLevel + 1, os );
1387
1388 NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n" << std::flush;
1389}
1390
1391#endif
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
@ add_hierarchical_subsheet
const Vec GetCenter() const
Definition: box2.h:195
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
coord_type GetTop() const
Definition: box2.h:194
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
coord_type GetRight() const
Definition: box2.h:189
coord_type GetLeft() const
Definition: box2.h:193
coord_type GetBottom() const
Definition: box2.h:190
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:255
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
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:85
const KIID m_Uuid
Definition: eda_item.h:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
static wxString GotoPageHref(const wxString &aDestination)
Generate a href to a page in the current schematic.
Definition: eda_text.cpp:1004
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
int GetDefaultPenWidth() const
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxDC * GetPrintDC() const
Store schematic specific render settings.
Definition: sch_painter.h:71
wxString AsString() const
Definition: kiid.cpp:359
Definition: kiid.h:48
Base plotter engine class.
Definition: plotter.h:110
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:141
bool GetColorMode() const
Definition: plotter.h:138
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:446
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
virtual void SetColor(const COLOR4D &color)=0
Container for project specific data.
Definition: project.h:64
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:122
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:203
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:86
void GetContextualTextVars(wxArrayString *aVars) const
Definition: schematic.cpp:126
SCH_SHEET & Root() const
Definition: schematic.h:91
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:76
Schematic editor (Eeschema) main window.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition: sch_item.cpp:70
virtual wxString GetClass() const override
Return the class name.
Definition: sch_item.h:157
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:112
FIELDS_AUTOPLACED m_fieldsAutoplaced
Definition: sch_item.h:493
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
Definition: sch_item.h:436
SCH_LAYER_ID m_layer
Definition: sch_item.h:491
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
const wxString & GetFileName() const
Definition: sch_screen.h:144
void DecRefCount()
Definition: sch_screen.cpp:124
void IncRefCount()
Definition: sch_screen.cpp:118
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:155
int GetRefCount() const
Definition: sch_screen.h:161
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool empty() const
Forwarded method from std::vector.
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
bool IsFullPath() 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.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
Definition: sch_sheet.cpp:971
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars & fields for this sheet.
Definition: sch_sheet.cpp:202
friend SCH_SHEET_PATH
Definition: sch_sheet.h:418
void Rotate(const VECTOR2I &aCenter) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_sheet.cpp:825
friend class SCH_SHEET_PIN
Definition: sch_sheet.h:489
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:308
bool IsRootSheet() const
Definition: sch_sheet.cpp:194
bool getInstance(SCH_SHEET_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
Definition: sch_sheet.cpp:1247
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: sch_sheet.cpp:1060
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList, const SCH_SHEET_PATH *aPath=nullptr) override
Test the schematic item to aItemList to check if it's dangling state has changed.
Definition: sch_sheet.cpp:983
void setPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1320
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
Definition: sch_sheet.cpp:55
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:369
bool HasRootInstance() const
Check to see if this sheet has a root sheet instance.
Definition: sch_sheet.cpp:1271
wxString GetClass() const override
Return the class name.
Definition: sch_sheet.h:77
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction) override
Definition: sch_sheet.cpp:1043
int GetPenWidth() const override
Definition: sch_sheet.cpp:594
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:156
SCH_SHEET_PATH findSelf() const
Get the sheetpath of this sheet.
Definition: sch_sheet.cpp:951
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:932
VECTOR2I m_pos
Definition: sch_sheet.h:500
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:93
KIGFX::COLOR4D m_borderColor
Definition: sch_sheet.h:503
wxString GetName() const
Definition: sch_sheet.h:103
void renumberPins()
Renumber the sheet pins in the sheet.
Definition: sch_sheet.cpp:939
VECTOR2I GetRotationCenter() const
Rotating around the boundingBox's center can cause walking when the sheetname or filename is longer t...
Definition: sch_sheet.cpp:694
SCH_SHEET(EDA_ITEM *aParent=nullptr, const VECTOR2I &aPos=VECTOR2I(0, 0), wxSize aSize=wxSize(schIUScale.MilsToIU(MIN_SHEET_WIDTH), schIUScale.MilsToIU(MIN_SHEET_HEIGHT)), FIELDS_AUTOPLACED aAutoplaceFields=FIELDS_AUTOPLACED_AUTO)
Definition: sch_sheet.cpp:77
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:582
bool operator<(const SCH_ITEM &aItem) const override
Definition: sch_sheet.cpp:1204
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
Definition: sch_sheet.cpp:556
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:380
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:723
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: sch_sheet.cpp:1053
bool LocatePathOfScreen(SCH_SCREEN *aScreen, SCH_SHEET_PATH *aList)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:759
std::vector< SCH_SHEET_INSTANCE > m_instances
Definition: sch_sheet.h:506
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
Definition: sch_sheet.cpp:442
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_sheet.cpp:907
int SymbolCount() const
Count our own symbols, without the power symbols.
Definition: sch_sheet.cpp:701
int GetMinWidth(bool aFromLeft) const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:488
SCH_SCREEN * m_screen
Definition: sch_sheet.h:493
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition: sch_sheet.cpp:649
std::vector< SCH_FIELD > m_fields
Definition: sch_sheet.h:498
KIGFX::COLOR4D m_backgroundColor
Definition: sch_sheet.h:504
int CountSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
Definition: sch_sheet.cpp:783
const BOX2I GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
Definition: sch_sheet.cpp:662
bool HasPin(const wxString &aName) const
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:397
static int ComparePageNum(const wxString &aPageNumberA, const wxString &aPageNumberB)
Compares page numbers of schematic sheets.
Definition: sch_sheet.cpp:1338
void Resize(const wxSize &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:915
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition: sch_sheet.cpp:887
void Plot(PLOTTER *aPlotter, bool aBackground) const override
Plot the schematic item to aPlotter.
Definition: sch_sheet.cpp:1089
wxString getPageNumber(const SCH_SHEET_PATH &aInstance) const
Return the sheet page number for aInstance.
Definition: sch_sheet.cpp:1299
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.cpp:347
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
Definition: sch_sheet.cpp:185
wxSize m_size
Definition: sch_sheet.h:501
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:162
SCH_SHEET & operator=(const SCH_ITEM &aSheet)
Definition: sch_sheet.cpp:1174
const SCH_SHEET_INSTANCE & GetRootInstance() const
Return the root sheet instance data.
Definition: sch_sheet.cpp:1283
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
Definition: sch_sheet.cpp:409
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:606
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:683
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Definition: sch_sheet.cpp:995
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:114
std::vector< SCH_SHEET_PIN * > m_pins
Definition: sch_sheet.h:497
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...
Definition: sch_sheet.cpp:1006
bool addInstance(const SCH_SHEET_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1221
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition: sch_sheet.cpp:867
void SwapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition: sch_sheet.cpp:313
int GetMinHeight(bool aFromTop) const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:522
int m_borderWidth
Definition: sch_sheet.h:502
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition: sch_sheet.cpp:813
int GetBorderWidth() const
Definition: sch_sheet.h:111
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.
Definition: sch_sheet.cpp:797
bool IsVerticalOrientation() const
Definition: sch_sheet.cpp:421
void Print(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset) override
Print a schematic item.
Definition: sch_sheet.cpp:1142
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
Definition: sch_sheet.cpp:237
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_sheet.cpp:1066
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:117
Schematic symbol object.
Definition: sch_symbol.h:81
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:843
bool TextVarResolver(wxString *aToken, const PROJECT *aProject) const
Definition: title_block.cpp:96
static void GetContextualTextVars(wxArrayString *aVars)
Definition: title_block.cpp:74
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:419
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:420
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:425
INSPECT_RESULT
Definition: eda_item.h:42
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:78
@ FILLED_SHAPE
void GRRect(wxDC *DC, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, const COLOR4D &aColor)
Definition: gr_basic.cpp:387
void GRFilledRect(wxDC *DC, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, const COLOR4D &aColor, const COLOR4D &aBgColor)
Definition: gr_basic.cpp:394
bool GetGRForceBlackPenState(void)
Definition: gr_basic.cpp:156
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
@ LAYER_SHEETNAME
Definition: layer_ids.h:363
@ LAYER_SHEET_BACKGROUND
Definition: layer_ids.h:373
@ LAYER_HIERLABEL
Definition: layer_ids.h:349
@ LAYER_SHEETFIELDS
Definition: layer_ids.h:365
@ LAYER_SHEET
Definition: layer_ids.h:362
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:381
@ LAYER_SHEETFILENAME
Definition: layer_ids.h:364
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
Message panel definition file.
wxString GetText(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:98
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:412
see class PGM_BASE
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
FIELDS_AUTOPLACED
Definition: sch_item.h:55
@ FIELDS_AUTOPLACED_AUTO
Definition: sch_item.h:57
#define USER_FIELD_CANONICAL
Definition: sch_sheet.cpp:52
#define SHEET_NAME_CANONICAL
Definition: sch_sheet.cpp:50
int bumpToNextGrid(const int aVal, const int aDirection)
Definition: sch_sheet.cpp:466
#define SHEET_FILE_CANONICAL
Definition: sch_sheet.cpp:51
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
Definition: sch_sheet.h:49
@ SHEETNAME
Definition: sch_sheet.h:45
@ SHEETFILENAME
Definition: sch_sheet.h:46
#define MIN_SHEET_HEIGHT
Definition: sch_sheet.h:40
#define MIN_SHEET_WIDTH
Definition: sch_sheet.h:39
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.
Definition: sch_sheet_pin.h:46
std::vector< FAB_LAYER_COLOR > dummy
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
A simple container for sheet instance information.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ 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)
Definition: trigo.cpp:183
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:183
@ SCH_SHEET_T
Definition: typeinfo.h:158
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:157
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618