KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_sheet.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2023 CERN
6 * Copyright (C) 1992-2024 Kicad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <cstdlib>
27
28#include <bitmaps.h>
29#include <core/mirror.h>
30#include <core/kicad_algo.h>
31#include <sch_draw_panel.h>
32#include <trigo.h>
33#include <sch_edit_frame.h>
34#include <plotters/plotter.h>
35#include <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, VECTOR2I 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 m_borderWidth = 0;
87 m_borderColor = COLOR4D::UNSPECIFIED;
88 m_backgroundColor = COLOR4D::UNSPECIFIED;
89 m_fieldsAutoplaced = aAutoplaceFields;
90
91 for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
92 {
93 m_fields.emplace_back( aPos, i, this, GetDefaultFieldName( i ) );
94 m_fields.back().SetVisible( true );
95
96 if( i == SHEETNAME )
97 m_fields.back().SetLayer( LAYER_SHEETNAME );
98 else if( i == SHEETFILENAME )
99 m_fields.back().SetLayer( LAYER_SHEETFILENAME );
100 else
101 m_fields.back().SetLayer( LAYER_SHEETFIELDS );
102 }
103
104 AutoAutoplaceFields( nullptr );
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
122 m_instances = aSheet.m_instances;
123
124 for( SCH_SHEET_PIN* pin : aSheet.m_pins )
125 {
126 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
127 m_pins.back()->SetParent( this );
128 }
129
130 for( SCH_FIELD& field : m_fields )
131 field.SetParent( this );
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( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const
238{
239 wxCHECK( aPath, false );
240
241 SCHEMATIC* schematic = Schematic();
242
243 if( !schematic )
244 return false;
245
246 if( token->Contains( ':' ) )
247 {
248 if( schematic->ResolveCrossReference( token, aDepth + 1 ) )
249 return true;
250 }
251
252 for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
253 {
254 if( token->IsSameAs( m_fields[i].GetCanonicalName().Upper() ) )
255 {
256 *token = m_fields[i].GetShownText( aPath, false, aDepth + 1 );
257 return true;
258 }
259 }
260
261 for( size_t i = SHEET_MANDATORY_FIELDS; i < m_fields.size(); ++i )
262 {
263 if( token->IsSameAs( m_fields[i].GetName() ) )
264 {
265 *token = m_fields[i].GetShownText( aPath, false, aDepth + 1 );
266 return true;
267 }
268 }
269
270 PROJECT* project = &schematic->Prj();
271
272 // We cannot resolve text variables initially on load as we need to first load the screen and
273 // then parse the hierarchy. So skip the resolution if the screen isn't set yet
275 {
276 return true;
277 }
278
279 if( token->IsSameAs( wxT( "#" ) ) )
280 {
281 *token = wxString::Format( "%s", aPath->GetPageNumber() );
282 return true;
283 }
284 else if( token->IsSameAs( wxT( "##" ) ) )
285 {
286 SCH_SHEET_LIST sheetList = schematic->GetSheets();
287 *token = wxString::Format( wxT( "%d" ), (int) sheetList.size() );
288 return true;
289 }
290 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
291 {
292 *token = aPath->PathHumanReadable();
293 return true;
294 }
295
296 // See if parent can resolve it (these will recurse to ancestors)
297
298 if( aPath->size() >= 2 )
299 {
300 SCH_SHEET_PATH path = *aPath;
301 path.pop_back();
302
303 if( path.Last()->ResolveTextVar( &path, token, aDepth + 1 ) )
304 return true;
305 }
306 else
307 {
308 if( schematic->ResolveTextVar( aPath, token, aDepth + 1 ) )
309 return true;
310 }
311
312 return false;
313}
314
315
317{
318 SCH_ITEM::SwapFlags( aItem );
319
320 wxCHECK_RET( aItem->Type() == SCH_SHEET_T,
321 wxString::Format( wxT( "SCH_SHEET object cannot swap data with %s object." ),
322 aItem->GetClass() ) );
323
324 SCH_SHEET* sheet = ( SCH_SHEET* ) aItem;
325
326 std::swap( m_pos, sheet->m_pos );
327 std::swap( m_size, sheet->m_size );
328 m_fields.swap( sheet->m_fields );
329 std::swap( m_fieldsAutoplaced, sheet->m_fieldsAutoplaced );
330 m_pins.swap( sheet->m_pins );
331
332 // Update parent pointers after swapping.
333 for( SCH_SHEET_PIN* sheetPin : m_pins )
334 sheetPin->SetParent( this );
335
336 for( SCH_SHEET_PIN* sheetPin : sheet->m_pins )
337 sheetPin->SetParent( sheet );
338
339 for( SCH_FIELD& field : m_fields )
340 field.SetParent( this );
341
342 for( SCH_FIELD& field : sheet->m_fields )
343 field.SetParent( sheet );
344
345 std::swap( m_borderWidth, sheet->m_borderWidth );
346 std::swap( m_borderColor, sheet->m_borderColor );
347 std::swap( m_backgroundColor, sheet->m_backgroundColor );
348 std::swap( m_instances, sheet->m_instances );
349}
350
351
352void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
353{
354 m_fields = aFields;
355
356 // Ensure that mandatory fields are at the beginning
357 std::sort( m_fields.begin(), m_fields.end(),
358 []( const SCH_FIELD& a, const SCH_FIELD& b )
359 {
360 return a.GetId() < b.GetId();
361 } );
362
363 // After mandatory fields, the rest should be sequential user fields
364 for( int ii = SHEET_MANDATORY_FIELDS; ii < static_cast<int>( m_fields.size() ); ++ii )
365 m_fields[ii].SetId( ii );
366
367 // Make sure that we get the UNIX variant of the file path
368 SetFileName( m_fields[SHEETFILENAME].GetText() );
369}
370
371
373{
374 wxASSERT( aSheetPin != nullptr );
375 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
376
377 aSheetPin->SetParent( this );
378 m_pins.push_back( aSheetPin );
379 renumberPins();
380}
381
382
383void SCH_SHEET::RemovePin( const SCH_SHEET_PIN* aSheetPin )
384{
385 wxASSERT( aSheetPin != nullptr );
386 wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
387
388 for( auto i = m_pins.begin(); i < m_pins.end(); ++i )
389 {
390 if( *i == aSheetPin )
391 {
392 m_pins.erase( i );
393 renumberPins();
394 return;
395 }
396 }
397}
398
399
400bool SCH_SHEET::HasPin( const wxString& aName ) const
401{
402 for( SCH_SHEET_PIN* pin : m_pins )
403 {
404 if( pin->GetText().Cmp( aName ) == 0 )
405 return true;
406 }
407
408 return false;
409}
410
411
412bool SCH_SHEET::doIsConnected( const VECTOR2I& aPosition ) const
413{
414 for( SCH_SHEET_PIN* sheetPin : m_pins )
415 {
416 if( sheetPin->GetPosition() == aPosition )
417 return true;
418 }
419
420 return false;
421}
422
423
425{
426 int leftRight = 0;
427 int topBottom = 0;
428
429 for( SCH_SHEET_PIN* pin : m_pins )
430 {
431 switch( pin->GetSide() )
432 {
433 case SHEET_SIDE::LEFT: leftRight++; break;
434 case SHEET_SIDE::RIGHT: leftRight++; break;
435 case SHEET_SIDE::TOP: topBottom++; break;
436 case SHEET_SIDE::BOTTOM: topBottom++; break;
437 default: break;
438 }
439 }
440
441 return topBottom > 0 && leftRight == 0;
442}
443
444
446{
447 for( SCH_SHEET_PIN* pin : m_pins )
448 {
449 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
450 const SCH_HIERLABEL* HLabel = nullptr;
451
452 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
453 {
454 if( !pin->GetText().Cmp( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
455 {
456 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
457 break;
458 }
459 }
460
461 if( HLabel == nullptr ) // Corresponding hierarchical label not found.
462 return true;
463 }
464
465 return false;
466}
467
468
469int bumpToNextGrid( const int aVal, const int aDirection )
470{
471 constexpr int gridSize = schIUScale.MilsToIU( 50 );
472
473 int base = aVal / gridSize;
474 int excess = abs( aVal % gridSize );
475
476 if( aDirection > 0 )
477 {
478 return ( base + 1 ) * gridSize;
479 }
480 else if( excess > 0 )
481 {
482 return ( base ) * gridSize;
483 }
484 else
485 {
486 return ( base - 1 ) * gridSize;
487 }
488}
489
490
491int SCH_SHEET::GetMinWidth( bool aFromLeft ) const
492{
493 int pinsLeft = m_pos.x + m_size.x;
494 int pinsRight = m_pos.x;
495
496 for( size_t i = 0; i < m_pins.size(); i++ )
497 {
498 SHEET_SIDE edge = m_pins[i]->GetSide();
499
500 if( edge == SHEET_SIDE::TOP || edge == SHEET_SIDE::BOTTOM )
501 {
502 BOX2I pinRect = m_pins[i]->GetBoundingBox();
503
504 pinsLeft = std::min( pinsLeft, pinRect.GetLeft() );
505 pinsRight = std::max( pinsRight, pinRect.GetRight() );
506 }
507 }
508
509 pinsLeft = bumpToNextGrid( pinsLeft, -1 );
510 pinsRight = bumpToNextGrid( pinsRight, 1 );
511
512 int pinMinWidth;
513
514 if( pinsLeft >= pinsRight )
515 pinMinWidth = 0;
516 else if( aFromLeft )
517 pinMinWidth = pinsRight - m_pos.x;
518 else
519 pinMinWidth = m_pos.x + m_size.x - pinsLeft;
520
521 return std::max( pinMinWidth, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
522}
523
524
525int SCH_SHEET::GetMinHeight( bool aFromTop ) const
526{
527 int pinsTop = m_pos.y + m_size.y;
528 int pinsBottom = m_pos.y;
529
530 for( size_t i = 0; i < m_pins.size(); i++ )
531 {
532 SHEET_SIDE edge = m_pins[i]->GetSide();
533
534 if( edge == SHEET_SIDE::RIGHT || edge == SHEET_SIDE::LEFT )
535 {
536 BOX2I pinRect = m_pins[i]->GetBoundingBox();
537
538 pinsTop = std::min( pinsTop, pinRect.GetTop() );
539 pinsBottom = std::max( pinsBottom, pinRect.GetBottom() );
540 }
541 }
542
543 pinsTop = bumpToNextGrid( pinsTop, -1 );
544 pinsBottom = bumpToNextGrid( pinsBottom, 1 );
545
546 int pinMinHeight;
547
548 if( pinsTop >= pinsBottom )
549 pinMinHeight = 0;
550 else if( aFromTop )
551 pinMinHeight = pinsBottom - m_pos.y;
552 else
553 pinMinHeight = m_pos.y + m_size.y - pinsTop;
554
555 return std::max( pinMinHeight, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
556}
557
558
560{
561 std::vector<SCH_SHEET_PIN*> pins = m_pins;
562
563 m_pins.clear();
564
565 for( SCH_SHEET_PIN* pin : pins )
566 {
567 /* Search the schematic for a hierarchical label corresponding to this sheet label. */
568 const SCH_HIERLABEL* HLabel = nullptr;
569
570 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
571 {
572 if( pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) == 0 )
573 {
574 HLabel = static_cast<SCH_HIERLABEL*>( aItem );
575 break;
576 }
577 }
578
579 if( HLabel )
580 m_pins.push_back( pin );
581 }
582}
583
584
586{
587 for( SCH_SHEET_PIN* pin : m_pins )
588 {
589 if( pin->HitTest( aPosition ) )
590 return pin;
591 }
592
593 return nullptr;
594}
595
596
598{
599 if( GetBorderWidth() > 0 )
600 return GetBorderWidth();
601
602 if( Schematic() )
604
606}
607
608
609void SCH_SHEET::AutoplaceFields( SCH_SCREEN* aScreen, bool /* aManual */ )
610{
611 VECTOR2I textSize = m_fields[SHEETNAME].GetTextSize();
612 int borderMargin = KiROUND( GetPenWidth() / 2.0 ) + 4;
613 int margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.5 );
614
616 {
617 m_fields[SHEETNAME].SetTextPos( m_pos + VECTOR2I( -margin, m_size.y ) );
618 m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
619 m_fields[ SHEETNAME ].SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
620 m_fields[ SHEETNAME ].SetTextAngle( ANGLE_VERTICAL );
621 }
622 else
623 {
624 m_fields[SHEETNAME].SetTextPos( m_pos + VECTOR2I( 0, -margin ) );
625 m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
626 m_fields[ SHEETNAME ].SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
627 m_fields[ SHEETNAME ].SetTextAngle( ANGLE_HORIZONTAL );
628 }
629
630 textSize = m_fields[ SHEETFILENAME ].GetTextSize();
631 margin = borderMargin + KiROUND( std::max( textSize.x, textSize.y ) * 0.4 );
632
634 {
635 m_fields[SHEETFILENAME].SetTextPos( m_pos + VECTOR2I( m_size.x + margin, m_size.y ) );
636 m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
637 m_fields[ SHEETFILENAME ].SetVertJustify( GR_TEXT_V_ALIGN_TOP );
638 m_fields[ SHEETFILENAME ].SetTextAngle( ANGLE_VERTICAL );
639 }
640 else
641 {
642 m_fields[SHEETFILENAME].SetTextPos( m_pos + VECTOR2I( 0, m_size.y + margin ) );
643 m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
644 m_fields[ SHEETFILENAME ].SetVertJustify( GR_TEXT_V_ALIGN_TOP );
645 m_fields[ SHEETFILENAME ].SetTextAngle( ANGLE_HORIZONTAL );
646 }
647
649}
650
651
652void SCH_SHEET::ViewGetLayers( int aLayers[], int& aCount ) const
653{
654 aCount = 8;
655 aLayers[0] = LAYER_DANGLING; // Sheet pins are drawn by their parent sheet, so the
656 // parent needs to draw to LAYER_DANGLING
657 aLayers[1] = LAYER_HIERLABEL;
658 aLayers[2] = LAYER_SHEETNAME;
659 aLayers[3] = LAYER_SHEETFILENAME;
660 aLayers[4] = LAYER_SHEETFIELDS;
661 aLayers[5] = LAYER_SHEET;
662 aLayers[6] = LAYER_SHEET_BACKGROUND;
663 aLayers[7] = LAYER_SELECTION_SHADOWS;
664}
665
666
668{
669 VECTOR2I end;
670 BOX2I box( m_pos, m_size );
671 int lineWidth = GetPenWidth();
672 int textLength = 0;
673
674 // Calculate bounding box X size:
675 end.x = std::max( m_size.x, textLength );
676
677 // Calculate bounding box pos:
678 end.y = m_size.y;
679 end += m_pos;
680
681 box.SetEnd( end );
682 box.Inflate( lineWidth / 2 );
683
684 return box;
685}
686
687
689{
690 BOX2I bbox = GetBodyBoundingBox();
691
692 for( const SCH_FIELD& field : m_fields )
693 bbox.Merge( field.GetBoundingBox() );
694
695 return bbox;
696}
697
698
700{
701 BOX2I box( m_pos, m_size );
702 return box.GetCenter();
703}
704
705
707{
708 int n = 0;
709
710 if( m_screen )
711 {
712 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SYMBOL_T ) )
713 {
714 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
715
716 if( symbol->GetField( VALUE_FIELD )->GetText().GetChar( 0 ) != '#' )
717 n++;
718 }
719
720 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
721 n += static_cast<const SCH_SHEET*>( aItem )->SymbolCount();
722 }
723
724 return n;
725}
726
727
728bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
729{
730 if( m_screen )
731 {
732 // Only check the root sheet once and don't recurse.
733 if( !GetParent() )
734 {
735 if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
736 {
737 *aScreen = m_screen;
738 return true;
739 }
740 }
741
742 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
743 {
744 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
745 SCH_SCREEN* screen = sheet->m_screen;
746
747 // Must use the screen's path (which is always absolute) rather than the
748 // sheet's (which could be relative).
749 if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
750 {
751 *aScreen = screen;
752 return true;
753 }
754
755 if( sheet->SearchHierarchy( aFilename, aScreen ) )
756 return true;
757 }
758 }
759
760 return false;
761}
762
763
765{
766 if( m_screen )
767 {
768 aList->push_back( this );
769
770 if( m_screen == aScreen )
771 return true;
772
773 for( EDA_ITEM* item : m_screen->Items().OfType( SCH_SHEET_T ) )
774 {
775 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
776
777 if( sheet->LocatePathOfScreen( aScreen, aList ) )
778 return true;
779 }
780
781 aList->pop_back();
782 }
783
784 return false;
785}
786
787
789{
790 int count = 1; //1 = this!!
791
792 if( m_screen )
793 {
794 for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
795 count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
796 }
797
798 return count;
799}
800
801
802void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
803{
804 // Don't use GetShownText(); we want to see the variable references here
805 aList.emplace_back( _( "Sheet Name" ),
806 KIUI::EllipsizeStatusText( aFrame, m_fields[ SHEETNAME ].GetText() ) );
807
808 if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
809 {
810 SCH_SHEET_PATH path = schframe->GetCurrentSheet();
811 path.push_back( this );
812
813 aList.emplace_back( _( "Hierarchical Path" ), path.PathHumanReadable( false, true ) );
814 }
815
816 // Don't use GetShownText(); we want to see the variable references here
817 aList.emplace_back( _( "File Name" ),
818 KIUI::EllipsizeStatusText( aFrame, m_fields[ SHEETFILENAME ].GetText() ) );
819}
820
821
823{
824 VECTOR2I delta = aPosition - m_pos;
825
826 m_pos = aPosition;
827
828 for( SCH_FIELD& field : m_fields )
829 field.Move( delta );
830}
831
832
833void SCH_SHEET::Move( const VECTOR2I& aMoveVector )
834{
835 m_pos += aMoveVector;
836
837 for( SCH_SHEET_PIN* pin : m_pins )
838 pin->Move( aMoveVector );
839
840 for( SCH_FIELD& field : m_fields )
841 field.Move( aMoveVector );
842}
843
844
845void SCH_SHEET::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
846{
847 VECTOR2I prev = m_pos;
848
849 RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_270 : ANGLE_90 );
850 RotatePoint( &m_size.x, &m_size.y, aRotateCCW ? ANGLE_270 : ANGLE_90 );
851
852 if( m_size.x < 0 )
853 {
854 m_pos.x += m_size.x;
855 m_size.x = -m_size.x;
856 }
857
858 if( m_size.y < 0 )
859 {
860 m_pos.y += m_size.y;
861 m_size.y = -m_size.y;
862 }
863
864 // Pins must be rotated first as that's how we determine vertical vs horizontal
865 // orientation for auto-placement
866 for( SCH_SHEET_PIN* sheetPin : m_pins )
867 sheetPin->Rotate( aCenter, aRotateCCW );
868
870 {
871 AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
872 }
873 else
874 {
875 // Move the fields to the new position because the parent itself has moved.
876 for( SCH_FIELD& field : m_fields )
877 {
878 VECTOR2I pos = field.GetTextPos();
879 pos.x -= prev.x - m_pos.x;
880 pos.y -= prev.y - m_pos.y;
881 field.SetTextPos( pos );
882 }
883 }
884}
885
886
888{
889 int dy = m_pos.y;
890
891 MIRROR( m_pos.y, aCenter );
892 m_pos.y -= m_size.y;
893 dy -= m_pos.y; // 0,dy is the move vector for this transform
894
895 for( SCH_SHEET_PIN* sheetPin : m_pins )
896 sheetPin->MirrorVertically( aCenter );
897
898 for( SCH_FIELD& field : m_fields )
899 {
900 VECTOR2I pos = field.GetTextPos();
901 pos.y -= dy;
902 field.SetTextPos( pos );
903 }
904}
905
906
908{
909 int dx = m_pos.x;
910
911 MIRROR( m_pos.x, aCenter );
912 m_pos.x -= m_size.x;
913 dx -= m_pos.x; // dx,0 is the move vector for this transform
914
915 for( SCH_SHEET_PIN* sheetPin : m_pins )
916 sheetPin->MirrorHorizontally( aCenter );
917
918 for( SCH_FIELD& field : m_fields )
919 {
920 VECTOR2I pos = field.GetTextPos();
921 pos.x -= dx;
922 field.SetTextPos( pos );
923 }
924}
925
926
927void SCH_SHEET::SetPosition( const VECTOR2I& aPosition )
928{
929 // Remember the sheet and all pin sheet positions must be
930 // modified. So use Move function to do that.
931 Move( aPosition - m_pos );
932}
933
934
935void SCH_SHEET::Resize( const VECTOR2I& aSize )
936{
937 if( aSize == m_size )
938 return;
939
940 m_size = aSize;
941
942 // Move the fields if we're in autoplace mode
944 AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
945
946 // Move the sheet labels according to the new sheet size.
947 for( SCH_SHEET_PIN* sheetPin : m_pins )
948 sheetPin->ConstrainOnEdge( sheetPin->GetPosition(), false );
949}
950
951
952bool SCH_SHEET::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
953{
954 // Sheets are searchable via the child field and pin item text.
955 return false;
956}
957
958
960{
961 int id = 2;
962
963 for( SCH_SHEET_PIN* pin : m_pins )
964 {
965 pin->SetNumber( id );
966 id++;
967 }
968}
969
970
972{
973 wxCHECK_MSG( Schematic(), SCH_SHEET_PATH(), "Can't call findSelf without a schematic" );
974
975 SCH_SHEET_PATH sheetPath = Schematic()->CurrentSheet();
976
977 while( !sheetPath.empty() && sheetPath.Last() != this )
978 sheetPath.pop_back();
979
980 if( sheetPath.empty() )
981 {
982 // If we weren't in the hierarchy, then we must be a child of the current sheet.
983 sheetPath = Schematic()->CurrentSheet();
984 sheetPath.push_back( const_cast<SCH_SHEET*>( this ) );
985 }
986
987 return sheetPath;
988}
989
990
991void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
992{
993 for( SCH_SHEET_PIN* sheetPin : m_pins )
994 {
995 wxCHECK2_MSG( sheetPin->Type() == SCH_SHEET_PIN_T, continue,
996 wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) );
997
998 sheetPin->GetEndPoints( aItemList );
999 }
1000}
1001
1002
1003bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
1004 std::vector<DANGLING_END_ITEM>& aItemListByPos,
1005 const SCH_SHEET_PATH* aPath )
1006{
1007 bool changed = false;
1008
1009 for( SCH_SHEET_PIN* sheetPin : m_pins )
1010 changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
1011
1012 return changed;
1013}
1014
1015
1017 const SCH_SHEET_PATH* aInstance ) const
1018{
1019 // Do not compare to ourself.
1020 if( aItem == this )
1021 return false;
1022
1023 const SCH_SHEET* sheet = dynamic_cast<const SCH_SHEET*>( aItem );
1024
1025 // Don't compare against a different SCH_ITEM.
1026 wxCHECK( sheet, false );
1027
1028 if( GetPosition() != sheet->GetPosition() )
1029 return true;
1030
1031 // Technically this cannot happen because undo/redo does not support reloading sheet
1032 // file association changes. This was just added so that it doesn't get missed should
1033 // we ever fix the undo/redo issue.
1034 if( ( GetFileName() != sheet->GetFileName() ) || ( GetName() != sheet->GetName() ) )
1035 return true;
1036
1037 if( m_pins.size() != sheet->m_pins.size() )
1038 return true;
1039
1040 for( size_t i = 0; i < m_pins.size(); i++ )
1041 {
1042 if( m_pins[i]->HasConnectivityChanges( sheet->m_pins[i] ) )
1043 return true;
1044 }
1045
1046 return false;
1047}
1048
1049
1050std::vector<VECTOR2I> SCH_SHEET::GetConnectionPoints() const
1051{
1052 std::vector<VECTOR2I> retval;
1053
1054 for( SCH_SHEET_PIN* sheetPin : m_pins )
1055 retval.push_back( sheetPin->GetPosition() );
1056
1057 return retval;
1058}
1059
1060
1061INSPECT_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData,
1062 const std::vector<KICAD_T>& aScanTypes )
1063{
1064 for( KICAD_T scanType : aScanTypes )
1065 {
1066 // If caller wants to inspect my type
1067 if( scanType == SCH_LOCATE_ANY_T || scanType == Type() )
1068 {
1069 if( INSPECT_RESULT::QUIT == aInspector( this, nullptr ) )
1070 return INSPECT_RESULT::QUIT;
1071 }
1072
1073 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_FIELD_T )
1074 {
1075 // Test the sheet fields.
1076 for( SCH_FIELD& field : m_fields )
1077 {
1078 if( INSPECT_RESULT::QUIT == aInspector( &field, this ) )
1079 return INSPECT_RESULT::QUIT;
1080 }
1081 }
1082
1083 if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_SHEET_PIN_T )
1084 {
1085 // Test the sheet labels.
1086 for( SCH_SHEET_PIN* sheetPin : m_pins )
1087 {
1088 if( INSPECT_RESULT::QUIT == aInspector( sheetPin, this ) )
1089 return INSPECT_RESULT::QUIT;
1090 }
1091 }
1092 }
1093
1094 return INSPECT_RESULT::CONTINUE;
1095}
1096
1097
1098void SCH_SHEET::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
1099{
1100 for( SCH_FIELD& field : m_fields )
1101 aFunction( &field );
1102
1103 for( SCH_SHEET_PIN* pin : m_pins )
1104 aFunction( pin );
1105}
1106
1107
1108wxString SCH_SHEET::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
1109{
1110 return wxString::Format( _( "Hierarchical Sheet %s" ),
1111 KIUI::EllipsizeMenuText( m_fields[ SHEETNAME ].GetText() ) );
1112}
1113
1114
1116{
1117 return BITMAPS::add_hierarchical_subsheet;
1118}
1119
1120
1121bool SCH_SHEET::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1122{
1123 BOX2I rect = GetBodyBoundingBox();
1124
1125 rect.Inflate( aAccuracy );
1126
1127 return rect.Contains( aPosition );
1128}
1129
1130
1131bool SCH_SHEET::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1132{
1133 BOX2I rect = aRect;
1134
1135 rect.Inflate( aAccuracy );
1136
1137 if( aContained )
1138 return rect.Contains( GetBodyBoundingBox() );
1139
1140 return rect.Intersects( GetBodyBoundingBox() );
1141}
1142
1143
1144void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1145 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1146{
1147 if( aBackground && !aPlotter->GetColorMode() )
1148 return;
1149
1150 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1151 COLOR4D borderColor = GetBorderColor();
1152 COLOR4D backgroundColor = GetBackgroundColor();
1153
1154 if( renderSettings->m_OverrideItemColors || borderColor == COLOR4D::UNSPECIFIED )
1155 borderColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET );
1156
1157 if( renderSettings->m_OverrideItemColors || backgroundColor == COLOR4D::UNSPECIFIED )
1158 backgroundColor = aPlotter->RenderSettings()->GetLayerColor( LAYER_SHEET_BACKGROUND );
1159
1160 if( aBackground && backgroundColor.a > 0.0 )
1161 {
1162 aPlotter->SetColor( backgroundColor );
1163 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::FILLED_SHAPE, 1 );
1164 }
1165 else
1166 {
1167 aPlotter->SetColor( borderColor );
1168
1169 int penWidth = GetEffectivePenWidth( getRenderSettings( aPlotter ) );
1170 aPlotter->Rect( m_pos, m_pos + m_size, FILL_T::NO_FILL, penWidth );
1171 }
1172
1173 // Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
1174 std::vector<wxString> properties;
1175
1176 properties.emplace_back( EDA_TEXT::GotoPageHref( findSelf().GetPageNumber() ) );
1177
1178 for( const SCH_FIELD& field : GetFields() )
1179 {
1180 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1181 field.GetName(),
1182 field.GetShownText( false ) ) );
1183 }
1184
1185 aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
1186
1187 // Plot sheet pins
1188 for( SCH_SHEET_PIN* sheetPin : m_pins )
1189 sheetPin->Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1190
1191 // Plot the fields
1192 for( SCH_FIELD& field : m_fields )
1193 field.Plot( aPlotter, aBackground, aPlotOpts, aUnit, aBodyStyle, aOffset, aDimmed );
1194}
1195
1196
1197void SCH_SHEET::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle,
1198 const VECTOR2I& aOffset, bool aForceNoFill, bool aDimmed )
1199{
1200 wxDC* DC = aSettings->GetPrintDC();
1201 VECTOR2I pos = m_pos + aOffset;
1202 int lineWidth = GetEffectivePenWidth( aSettings );
1203 COLOR4D border = GetBorderColor();
1204 COLOR4D background = GetBackgroundColor();
1205
1206 if( aSettings->m_OverrideItemColors || border == COLOR4D::UNSPECIFIED )
1207 border = aSettings->GetLayerColor( LAYER_SHEET );
1208
1209 if( aSettings->m_OverrideItemColors || background == COLOR4D::UNSPECIFIED )
1210 background = aSettings->GetLayerColor( LAYER_SHEET_BACKGROUND );
1211
1212 if( GetGRForceBlackPenState() ) // printing in black & white
1213 background = COLOR4D::UNSPECIFIED;
1214
1215 if( background.a > 0.0 )
1216 GRFilledRect( DC, pos, pos + m_size, 0, background, background );
1217
1218 GRRect( DC, pos, pos + m_size, lineWidth, border );
1219
1220 for( SCH_FIELD& field : m_fields )
1221 field.Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
1222
1223 for( SCH_SHEET_PIN* sheetPin : m_pins )
1224 sheetPin->Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
1225}
1226
1227
1229{
1230 wxCHECK_MSG( Type() == aItem.Type(), *this,
1231 wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
1232 GetClass() );
1233
1234 if( &aItem != this )
1235 {
1236 SCH_ITEM::operator=( aItem );
1237
1238 SCH_SHEET* sheet = (SCH_SHEET*) &aItem;
1239
1240 m_pos = sheet->m_pos;
1241 m_size = sheet->m_size;
1242 m_fields = sheet->m_fields;
1243
1244 for( SCH_SHEET_PIN* pin : sheet->m_pins )
1245 {
1246 m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
1247 m_pins.back()->SetParent( this );
1248 }
1249
1250 for( const SCH_SHEET_INSTANCE& instance : sheet->m_instances )
1251 m_instances.emplace_back( instance );
1252 }
1253
1254 return *this;
1255}
1256
1257
1258bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
1259{
1260 if( Type() != aItem.Type() )
1261 return Type() < aItem.Type();
1262
1263 auto sheet = static_cast<const SCH_SHEET*>( &aItem );
1264
1265 if (m_fields[ SHEETNAME ].GetText() != sheet->m_fields[ SHEETNAME ].GetText() )
1266 return m_fields[ SHEETNAME ].GetText() < sheet->m_fields[ SHEETNAME ].GetText();
1267
1268 if (m_fields[ SHEETFILENAME ].GetText() != sheet->m_fields[ SHEETFILENAME ].GetText() )
1269 return m_fields[ SHEETFILENAME ].GetText() < sheet->m_fields[ SHEETFILENAME ].GetText();
1270
1271 return false;
1272}
1273
1274
1275void SCH_SHEET::RemoveInstance( const KIID_PATH& aInstancePath )
1276{
1277 // Search for an existing path and remove it if found (should not occur)
1278 for( unsigned ii = 0; ii < m_instances.size(); ii++ )
1279 {
1280 if( m_instances[ii].m_Path == aInstancePath )
1281 {
1282 wxLogTrace( traceSchSheetPaths, "Removing sheet instance:\n"
1283 " sheet path %s\n"
1284 " page %s, from project %s.",
1285 aInstancePath.AsString(),
1286 m_instances[ii].m_PageNumber,
1287 m_instances[ii].m_ProjectName );
1288
1289 m_instances.erase( m_instances.begin() + ii );
1290 ii--;
1291 }
1292 }
1293}
1294
1295
1297{
1298 SCH_SHEET_INSTANCE oldInstance;
1299
1300 if( getInstance( oldInstance, aInstance.m_Path ) )
1301 RemoveInstance( aInstance.m_Path );
1302
1303 m_instances.emplace_back( aInstance );
1304
1305}
1306
1307
1309{
1310 wxCHECK( aSheetPath.IsFullPath(), false );
1311 wxCHECK( !aSheetPath.Last() || ( aSheetPath.Last()->m_Uuid != m_Uuid ), false );
1312
1313 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1314 {
1315 // if aSheetPath is found, nothing to do:
1316 if( instance.m_Path == aSheetPath.Path() )
1317 return false;
1318 }
1319
1320 wxLogTrace( traceSchSheetPaths, wxT( "Adding instance `%s` to sheet `%s`." ),
1321 aSheetPath.Path().AsString(),
1322 ( GetName().IsEmpty() ) ? wxString( wxT( "root" ) ) : GetName() );
1323
1324 SCH_SHEET_INSTANCE instance;
1325
1326 instance.m_Path = aSheetPath.Path();
1327
1328 // This entry does not exist: add it with an empty page number.
1329 m_instances.emplace_back( instance );
1330 return true;
1331}
1332
1333
1334bool SCH_SHEET::getInstance( SCH_SHEET_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
1335 bool aTestFromEnd ) const
1336{
1337 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1338 {
1339 if( !aTestFromEnd )
1340 {
1341 if( instance.m_Path == aSheetPath )
1342 {
1343 aInstance = instance;
1344 return true;
1345 }
1346 }
1347 else if( instance.m_Path.EndsWith( aSheetPath ) )
1348 {
1349 aInstance = instance;
1350 return true;
1351 }
1352 }
1353
1354 return false;
1355}
1356
1357
1359{
1360 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1361 {
1362 if( instance.m_Path.size() == 0 )
1363 return true;
1364 }
1365
1366 return false;
1367}
1368
1369
1371{
1372 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1373 {
1374 if( instance.m_Path.size() == 0 )
1375 return instance;
1376 }
1377
1378 wxFAIL;
1379
1381
1382 return dummy;
1383}
1384
1385
1386wxString SCH_SHEET::getPageNumber( const SCH_SHEET_PATH& aSheetPath ) const
1387{
1388 wxCHECK( aSheetPath.IsFullPath(), wxEmptyString );
1389 wxCHECK( !aSheetPath.Last() || ( aSheetPath.Last()->m_Uuid != m_Uuid ), wxEmptyString );
1390
1391 wxString pageNumber;
1392 KIID_PATH path = aSheetPath.Path();
1393
1394 for( const SCH_SHEET_INSTANCE& instance : m_instances )
1395 {
1396 if( instance.m_Path == path )
1397 {
1398 pageNumber = instance.m_PageNumber;
1399 break;
1400 }
1401 }
1402
1403 return pageNumber;
1404}
1405
1406
1407void SCH_SHEET::setPageNumber( const SCH_SHEET_PATH& aSheetPath, const wxString& aPageNumber )
1408{
1409 wxCHECK( aSheetPath.IsFullPath(), /* void */ );
1410 wxCHECK( !aSheetPath.Last() || ( aSheetPath.Last()->m_Uuid != m_Uuid ), /* void */ );
1411
1412 KIID_PATH path = aSheetPath.Path();
1413
1414 for( SCH_SHEET_INSTANCE& instance : m_instances )
1415 {
1416 if( instance.m_Path == path )
1417 {
1418 instance.m_PageNumber = aPageNumber;
1419 break;
1420 }
1421 }
1422}
1423
1424
1425int SCH_SHEET::ComparePageNum( const wxString& aPageNumberA, const wxString& aPageNumberB )
1426{
1427 if( aPageNumberA == aPageNumberB )
1428 return 0; // A == B
1429
1430 // First sort numerically if the page numbers are integers
1431 long pageA, pageB;
1432 bool isIntegerPageA = aPageNumberA.ToLong( &pageA );
1433 bool isIntegerPageB = aPageNumberB.ToLong( &pageB );
1434
1435 if( isIntegerPageA && isIntegerPageB )
1436 {
1437 if( pageA < pageB )
1438 return -1; //A < B
1439 else
1440 return 1; // A > B
1441 }
1442
1443 // Numerical page numbers always before strings
1444 if( isIntegerPageA )
1445 return -1; //A < B
1446 else if( isIntegerPageB )
1447 return 1; // A > B
1448
1449 // If not numeric, then sort as strings using natural sort
1450 int result = StrNumCmp( aPageNumberA, aPageNumberB );
1451
1452 // Divide by zero bad.
1453 wxCHECK( result != 0, 0 );
1454
1455 result = result / std::abs( result );
1456
1457 return result;
1458}
1459
1460
1461bool SCH_SHEET::operator==( const SCH_ITEM& aOther ) const
1462{
1463 if( Type() != aOther.Type() )
1464 return false;
1465
1466 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
1467
1468 if( m_pos != other->m_pos )
1469 return false;
1470
1471 if( m_size != other->m_size )
1472 return false;
1473
1474 if( GetBorderColor() != other->GetBorderColor() )
1475 return false;
1476
1477 if( GetBackgroundColor() != other->GetBackgroundColor() )
1478 return false;
1479
1480 if( GetBorderWidth() != other->GetBorderWidth() )
1481 return false;
1482
1483 if( GetFields().size() != other->GetFields().size() )
1484 return false;
1485
1486 for( size_t i = 0; i < GetFields().size(); ++i )
1487 {
1488 if( !( GetFields()[i] == other->GetFields()[i] ) )
1489 return false;
1490 }
1491
1492 return true;
1493}
1494
1495
1496double SCH_SHEET::Similarity( const SCH_ITEM& aOther ) const
1497{
1498 if( Type() != aOther.Type() )
1499 return 0.0;
1500
1501 const SCH_SHEET* other = static_cast<const SCH_SHEET*>( &aOther );
1502
1503 if( m_screen->GetFileName() == other->m_screen->GetFileName() )
1504 return 1.0;
1505
1506 return 0.0;
1507}
1508
1509
1510#if defined(DEBUG)
1511
1512void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
1513{
1514 // XML output:
1515 wxString s = GetClass();
1516
1517 NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">" << " sheet_name=\""
1518 << TO_UTF8( m_fields[ SHEETNAME ].GetText() ) << '"' << ">\n";
1519
1520 // show all the pins, and check the linked list integrity
1521 for( SCH_SHEET_PIN* sheetPin : m_pins )
1522 sheetPin->Show( nestLevel + 1, os );
1523
1524 NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n" << std::flush;
1525}
1526
1527#endif
1528
1529static struct SCH_SHEET_DESC
1530{
1532 {
1536
1537 propMgr.AddProperty( new PROPERTY<SCH_SHEET, wxString>( _HKI( "Sheet Name" ),
1539
1540 propMgr.AddProperty( new PROPERTY<SCH_SHEET, int>( _HKI( "Border Width" ),
1542 PROPERTY_DISPLAY::PT_SIZE ) );
1543
1544 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Border Color" ),
1546
1547 propMgr.AddProperty( new PROPERTY<SCH_SHEET, COLOR4D>( _HKI( "Background Color" ),
1549 }
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
const Vec GetCenter() const
Definition: box2.h:220
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:294
coord_type GetTop() const
Definition: box2.h:219
bool Contains(const Vec &aPoint) const
Definition: box2.h:158
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:541
coord_type GetRight() const
Definition: box2.h:207
coord_type GetLeft() const
Definition: box2.h:218
coord_type GetBottom() const
Definition: box2.h:212
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:280
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:623
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:88
const KIID m_Uuid
Definition: eda_item.h:485
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:103
EDA_ITEM * GetParent() const
Definition: eda_item.h:102
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
static wxString GotoPageHref(const wxString &aDestination)
Generate a href to a page in the current schematic.
Definition: eda_text.cpp:1173
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
double a
Alpha component.
Definition: color4d.h:395
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
wxDC * GetPrintDC() const
wxString AsString() const
Definition: kiid.cpp:368
Definition: kiid.h:49
Base plotter engine class.
Definition: plotter.h:104
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:135
bool GetColorMode() const
Definition: plotter.h:132
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:464
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:62
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:287
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:100
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
Definition: schematic.cpp:228
void GetContextualTextVars(wxArrayString *aVars) const
Definition: schematic.cpp:203
SCH_SHEET & Root() const
Definition: schematic.h:105
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:90
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Definition: schematic.cpp:411
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:174
SCH_ITEM & operator=(const SCH_ITEM &aPin)
Definition: sch_item.cpp:100
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition: sch_item.h:678
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:139
FIELDS_AUTOPLACED m_fieldsAutoplaced
Definition: sch_item.h:735
void SwapFlags(SCH_ITEM *aItem)
Swap the non-temp and non-edit flags.
Definition: sch_item.cpp:343
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:184
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition: sch_item.cpp:464
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
Definition: sch_item.h:568
SCH_LAYER_ID m_layer
Definition: sch_item.h:731
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:129
void IncRefCount()
Definition: sch_screen.cpp:123
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
wxString GetPageNumber() 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:991
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:438
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:119
friend class SCH_SHEET_PIN
Definition: sch_sheet.h:509
VECTOR2I m_size
Definition: sch_sheet.h:521
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:312
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
Definition: sch_sheet.cpp:1016
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:306
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:1334
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: sch_sheet.cpp:1115
void setPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1407
void RemoveInstance(const KIID_PATH &aInstancePath)
Definition: sch_sheet.cpp:1275
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:372
bool HasRootInstance() const
Check to see if this sheet has a root sheet instance.
Definition: sch_sheet.cpp:1358
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:1098
int GetPenWidth() const override
Definition: sch_sheet.cpp:597
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:971
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:952
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
Definition: sch_sheet.cpp:1496
VECTOR2I m_pos
Definition: sch_sheet.h:520
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:93
KIGFX::COLOR4D m_borderColor
Definition: sch_sheet.h:523
wxString GetName() const
Definition: sch_sheet.h:107
void renumberPins()
Renumber the sheet pins in the sheet.
Definition: sch_sheet.cpp:959
VECTOR2I GetRotationCenter() const
Rotating around the boundingBox's center can cause walking when the sheetname or filename is longer t...
Definition: sch_sheet.cpp:699
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:585
bool operator<(const SCH_ITEM &aItem) const override
Definition: sch_sheet.cpp:1258
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
Definition: sch_sheet.cpp:559
void Print(const SCH_RENDER_SETTINGS *aSettings, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aForceNoFill, bool aDimmed) override
Print an item.
Definition: sch_sheet.cpp:1197
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:383
void SetPositionIgnoringPins(const VECTOR2I &aPosition)
Definition: sch_sheet.cpp:822
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:728
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: sch_sheet.cpp:1108
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:764
std::vector< SCH_SHEET_INSTANCE > m_instances
Definition: sch_sheet.h:526
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
Definition: sch_sheet.cpp:445
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_sheet.cpp:927
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:122
int SymbolCount() const
Count our own symbols, without the power symbols.
Definition: sch_sheet.cpp:706
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
Definition: sch_sheet.cpp:1144
void AddInstance(const SCH_SHEET_INSTANCE &aInstance)
Definition: sch_sheet.cpp:1296
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:491
bool operator==(const SCH_ITEM &aOther) const override
Definition: sch_sheet.cpp:1461
SCH_SCREEN * m_screen
Definition: sch_sheet.h:513
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:652
std::vector< SCH_FIELD > m_fields
Definition: sch_sheet.h:518
KIGFX::COLOR4D m_backgroundColor
Definition: sch_sheet.h:524
void SetName(const wxString &aName)
Definition: sch_sheet.h:108
int CountSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
Definition: sch_sheet.cpp:788
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:376
const BOX2I GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
Definition: sch_sheet.cpp:667
bool HasPin(const wxString &aName) const
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:400
static int ComparePageNum(const wxString &aPageNumberA, const wxString &aPageNumberB)
Compares page numbers of schematic sheets.
Definition: sch_sheet.cpp:1425
SCH_SHEET(EDA_ITEM *aParent=nullptr, const VECTOR2I &aPos=VECTOR2I(0, 0), VECTOR2I aSize=VECTOR2I(schIUScale.MilsToIU(MIN_SHEET_WIDTH), schIUScale.MilsToIU(MIN_SHEET_HEIGHT)), FIELDS_AUTOPLACED aAutoplaceFields=FIELDS_AUTOPLACED_AUTO)
Definition: sch_sheet.cpp:77
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition: sch_sheet.cpp:907
wxString getPageNumber(const SCH_SHEET_PATH &aInstance) const
Return the sheet page number for aInstance.
Definition: sch_sheet.cpp:1386
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.cpp:352
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
Definition: sch_sheet.cpp:185
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:1228
const SCH_SHEET_INSTANCE & GetRootInstance() const
Return the root sheet instance data.
Definition: sch_sheet.cpp:1370
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
Definition: sch_sheet.cpp:412
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:609
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:688
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Definition: sch_sheet.cpp:1050
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:118
std::vector< SCH_SHEET_PIN * > m_pins
Definition: sch_sheet.h:517
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:1061
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:116
bool addInstance(const SCH_SHEET_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1308
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition: sch_sheet.cpp:887
void SwapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition: sch_sheet.cpp:316
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:525
int m_borderWidth
Definition: sch_sheet.h:522
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos, const SCH_SHEET_PATH *aPath=nullptr) override
Test the schematic item to aItemList to check if it's dangling state has changed.
Definition: sch_sheet.cpp:1003
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:935
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition: sch_sheet.cpp:833
int GetBorderWidth() const
Definition: sch_sheet.h:115
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:802
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_sheet.cpp:845
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
Definition: sch_sheet.cpp:237
bool IsVerticalOrientation() const
Definition: sch_sheet.cpp:424
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:1121
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:121
Schematic symbol object.
Definition: sch_symbol.h:108
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:910
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 _HKI(x)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:437
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:432
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:431
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:440
INSPECT_RESULT
Definition: eda_item.h:43
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:81
void GRRect(wxDC *DC, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, const COLOR4D &aColor)
Definition: gr_basic.cpp:396
void GRFilledRect(wxDC *DC, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, const COLOR4D &aColor, const COLOR4D &aBgColor)
Definition: gr_basic.cpp:403
bool GetGRForceBlackPenState(void)
Definition: gr_basic.cpp:165
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
@ LAYER_DANGLING
Definition: layer_ids.h:381
@ LAYER_SHEETNAME
Definition: layer_ids.h:376
@ LAYER_SHEET_BACKGROUND
Definition: layer_ids.h:387
@ LAYER_HIERLABEL
Definition: layer_ids.h:361
@ LAYER_SHEETFIELDS
Definition: layer_ids.h:378
@ LAYER_SHEET
Definition: layer_ids.h:375
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:395
@ LAYER_SHEETFILENAME
Definition: layer_ids.h:377
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.
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
Definition: ui_common.cpp:210
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
Definition: ui_common.cpp:192
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:424
see class PGM_BASE
#define TYPE_HASH(x)
Definition: property.h:71
#define REGISTER_TYPE(x)
Definition: property_mgr.h:366
FIELDS_AUTOPLACED
Definition: sch_item.h:68
@ FIELDS_AUTOPLACED_AUTO
Definition: sch_item.h:70
#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:469
static struct SCH_SHEET_DESC _SCH_SHEET_DESC
#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.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:391
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
A simple container for sheet instance information.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
constexpr int delta
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_TOP
wxLogTrace helper definitions.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:228
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:198
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
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:118
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588