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