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-2020 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 <fctsys.h>
26 #include <sch_draw_panel.h>
27 #include <gr_text.h>
28 #include <trigo.h>
29 #include <sch_edit_frame.h>
30 #include <plotter.h>
31 #include <kicad_string.h>
32 #include <msgpanel.h>
33 #include <math/util.h> // for KiROUND
34 #include <sch_sheet.h>
35 #include <sch_sheet_path.h>
36 #include <sch_component.h>
38 #include <netlist_object.h>
39 #include <trace_helpers.h>
40 #include <pgm_base.h>
41 
42 
43 const wxString SCH_SHEET::GetDefaultFieldName( int aFieldNdx )
44 {
45  static void* locale = nullptr;
46  static wxString sheetnameDefault;
47  static wxString sheetfilenameDefault;
48  static wxString fieldDefault;
49 
50  // Fetching translations can take a surprising amount of time when loading libraries,
51  // so only do it when necessary.
52  if( Pgm().GetLocale() != locale )
53  {
54  sheetnameDefault = _( "Sheet name" );
55  sheetfilenameDefault = _( "Sheet file" );
56  fieldDefault = _( "Field%d" );
57  locale = Pgm().GetLocale();
58  }
59 
60  // Fixed values for the mandatory fields
61  switch( aFieldNdx )
62  {
63  case SHEETNAME: return sheetnameDefault;
64  case SHEETFILENAME: return sheetfilenameDefault;
65  default: return wxString::Format( fieldDefault, aFieldNdx );
66  }
67 }
68 
69 
72 {
74  m_pos = pos;
75  m_size = wxSize( Mils2iu( MIN_SHEET_WIDTH ), Mils2iu( MIN_SHEET_HEIGHT ) );
76  m_screen = NULL;
77 
78  for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
79  {
80  m_fields.emplace_back( pos, i, this, GetDefaultFieldName( i ) );
81  m_fields.back().SetVisible( true );
82 
83  if( i == SHEETNAME )
84  m_fields.back().SetLayer( LAYER_SHEETNAME );
85  else if( i == SHEETFILENAME )
86  m_fields.back().SetLayer( LAYER_SHEETFILENAME );
87  else
88  m_fields.back().SetLayer( LAYER_SHEETFIELDS );
89  }
90 
92 
96 }
97 
98 
99 SCH_SHEET::SCH_SHEET( const SCH_SHEET& aSheet ) :
100  SCH_ITEM( aSheet )
101 {
102  m_pos = aSheet.m_pos;
103  m_size = aSheet.m_size;
104  m_Layer = aSheet.m_Layer;
105  const_cast<KIID&>( m_Uuid ) = aSheet.m_Uuid;
106  m_fields = aSheet.m_fields;
108  m_screen = aSheet.m_screen;
109 
110  for( SCH_SHEET_PIN* pin : aSheet.m_pins )
111  {
112  m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
113  m_pins.back()->SetParent( this );
114  }
115 
116  m_borderWidth = aSheet.m_borderWidth;
117  m_borderColor = aSheet.m_borderColor;
119 
120  if( m_screen )
122 }
123 
124 
126 {
127  // also, look at the associated sheet & its reference count
128  // perhaps it should be deleted also.
129  if( m_screen )
130  {
132 
133  if( m_screen->GetRefCount() == 0 )
134  delete m_screen;
135  }
136 
137  // We own our pins; delete them
138  for( SCH_SHEET_PIN* pin : m_pins )
139  delete pin;
140 }
141 
142 
144 {
145  return new SCH_SHEET( *this );
146 }
147 
148 
150 {
151  if( aScreen == m_screen )
152  return;
153 
154  if( m_screen != NULL )
155  {
157 
158  if( m_screen->GetRefCount() == 0 )
159  {
160  delete m_screen;
161  m_screen = NULL;
162  }
163  }
164 
165  m_screen = aScreen;
166 
167  if( m_screen )
169 }
170 
171 
173 {
174  if( m_screen == NULL )
175  return 0;
176 
177  return m_screen->GetRefCount();
178 }
179 
180 
182 {
183  SCH_SHEET* sheet = dynamic_cast< SCH_SHEET* >( GetParent() );
184 
185  if( sheet == NULL )
186  return this;
187 
188  // Recurse until a sheet is found with no parent which is the root sheet.
189  return sheet->GetRootSheet();
190 }
191 
192 
194 {
196  && ( m_borderColor == COLOR4D::UNSPECIFIED ) )
197  return true;
198 
199  return false;
200 }
201 
202 
204 {
205  wxCHECK_RET( aItem->Type() == SCH_SHEET_T,
206  wxString::Format( wxT( "SCH_SHEET object cannot swap data with %s object." ),
207  GetChars( aItem->GetClass() ) ) );
208 
209  SCH_SHEET* sheet = ( SCH_SHEET* ) aItem;
210 
211  std::swap( m_pos, sheet->m_pos );
212  std::swap( m_size, sheet->m_size );
213  m_fields.swap( sheet->m_fields );
214  std::swap( m_fieldsAutoplaced, sheet->m_fieldsAutoplaced );
215  m_pins.swap( sheet->m_pins );
216 
217  // Update parent pointers after swapping.
218  for( SCH_SHEET_PIN* sheetPin : m_pins )
219  sheetPin->SetParent( this );
220 
221  for( SCH_SHEET_PIN* sheetPin : sheet->m_pins )
222  sheetPin->SetParent( sheet );
223 
224  std::swap( m_borderWidth, sheet->m_borderWidth );
225  std::swap( m_borderColor, sheet->m_borderColor );
226  std::swap( m_backgroundColor, sheet->m_backgroundColor );
227 }
228 
229 
231 {
232  wxASSERT( aSheetPin != NULL );
233  wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
234 
235  m_pins.push_back( aSheetPin );
236  renumberPins();
237 }
238 
239 
241 {
242  wxASSERT( aSheetPin != NULL );
243  wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
244 
245  for( auto i = m_pins.begin(); i < m_pins.end(); ++i )
246  {
247  if( *i == aSheetPin )
248  {
249  m_pins.erase( i );
250  renumberPins();
251  return;
252  }
253  }
254 
255  wxLogDebug( wxT( "Fix me: attempt to remove label %s which is not in sheet %s." ),
256  aSheetPin->GetShownText(), m_fields[ SHEETNAME ].GetText() );
257 }
258 
259 
260 bool SCH_SHEET::HasPin( const wxString& aName )
261 {
262  for( SCH_SHEET_PIN* pin : m_pins )
263  {
264  if( pin->GetText().CmpNoCase( aName ) == 0 )
265  return true;
266  }
267 
268  return false;
269 }
270 
271 
272 bool SCH_SHEET::doIsConnected( const wxPoint& aPosition ) const
273 {
274  for( SCH_SHEET_PIN* sheetPin : m_pins )
275  {
276  if( sheetPin->GetPosition() == aPosition )
277  return true;
278  }
279 
280  return false;
281 }
282 
283 
285 {
286  int leftRight = 0;
287  int topBottom = 0;
288 
289  for( SCH_SHEET_PIN* pin : m_pins )
290  {
291  switch( pin->GetEdge() )
292  {
293  case SHEET_LEFT_SIDE: leftRight++; break;
294  case SHEET_RIGHT_SIDE: leftRight++; break;
295  case SHEET_TOP_SIDE: topBottom++; break;
296  case SHEET_BOTTOM_SIDE: topBottom++; break;
297  default: break;
298  }
299  }
300 
301  return topBottom > 0 && leftRight == 0;
302 }
303 
304 
306 {
307  for( SCH_SHEET_PIN* pin : m_pins )
308  {
309  /* Search the schematic for a hierarchical label corresponding to this sheet label. */
310  const SCH_HIERLABEL* HLabel = nullptr;
311  for( auto aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
312  {
313  if( !pin->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
314  {
315  HLabel = static_cast<SCH_HIERLABEL*>( aItem );
316  break;
317  }
318  }
319 
320  if( HLabel == nullptr ) // Corresponding hierarchical label not found.
321  return true;
322  }
323 
324  return false;
325 }
326 
327 
329 {
330  int width = Mils2iu( MIN_SHEET_WIDTH );
331 
332  for( size_t i = 0; i < m_pins.size(); i++ )
333  {
334  int edge = m_pins[i]->GetEdge();
335  EDA_RECT pinRect = m_pins[i]->GetBoundingBox();
336 
337  wxASSERT( edge != SHEET_UNDEFINED_SIDE );
338 
339  if( edge == SHEET_TOP_SIDE || edge == SHEET_BOTTOM_SIDE )
340  {
341  if( width < pinRect.GetRight() - m_pos.x )
342  width = pinRect.GetRight() - m_pos.x;
343  }
344  else
345  {
346  if( width < pinRect.GetWidth() )
347  width = pinRect.GetWidth();
348 
349  for( size_t j = 0; j < m_pins.size(); j++ )
350  {
351  // Check for pin directly across from the current pin.
352  if( (i == j) || (m_pins[i]->GetPosition().y != m_pins[j]->GetPosition().y) )
353  continue;
354 
355  if( width < pinRect.GetWidth() + m_pins[j]->GetBoundingBox().GetWidth() )
356  {
357  width = pinRect.GetWidth() + m_pins[j]->GetBoundingBox().GetWidth();
358  break;
359  }
360  }
361  }
362  }
363 
364  return width;
365 }
366 
367 
369 {
370  int height = Mils2iu( MIN_SHEET_HEIGHT );
371 
372  for( size_t i = 0; i < m_pins.size(); i++ )
373  {
374  int edge = m_pins[i]->GetEdge();
375  EDA_RECT pinRect = m_pins[i]->GetBoundingBox();
376 
377  // Make sure pin is on top or bottom side of sheet.
378  if( edge == SHEET_RIGHT_SIDE || edge == SHEET_LEFT_SIDE )
379  {
380  if( height < pinRect.GetBottom() - m_pos.y )
381  height = pinRect.GetBottom() - m_pos.y;
382  }
383  else
384  {
385  if( height < pinRect.GetHeight() )
386  height = pinRect.GetHeight();
387 
388  for( size_t j = 0; j < m_pins.size(); j++ )
389  {
390  // Check for pin directly above or below the current pin.
391  if( (i == j) || (m_pins[i]->GetPosition().x != m_pins[j]->GetPosition().x) )
392  continue;
393 
394  if( height < pinRect.GetHeight() + m_pins[j]->GetBoundingBox().GetHeight() )
395  {
396  height = pinRect.GetHeight() + m_pins[j]->GetBoundingBox().GetHeight();
397  break;
398  }
399  }
400  }
401  }
402 
403  return height;
404 }
405 
406 
408 {
409  auto i = m_pins.begin();
410 
411  while( i != m_pins.end() )
412  {
413  /* Search the schematic for a hierarchical label corresponding to this sheet label. */
414  const SCH_HIERLABEL* HLabel = NULL;
415 
416  for( SCH_ITEM* aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
417  {
418  if( (*i)->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) == 0 )
419  {
420  HLabel = static_cast<SCH_HIERLABEL*>( aItem );
421  break;
422  }
423  }
424 
425  if( HLabel == NULL ) // Hlabel not found: delete sheet label.
426  i = m_pins.erase( i );
427  else
428  ++i;
429  }
430 }
431 
432 
434 {
435  for( SCH_SHEET_PIN* pin : m_pins )
436  {
437  if( pin->HitTest( aPosition ) )
438  return pin;
439  }
440 
441  return NULL;
442 }
443 
444 
446 {
447  return GetBorderWidth();
448 }
449 
450 
451 void SCH_SHEET::AutoplaceFields( SCH_SCREEN* aScreen, bool aManual )
452 {
453  wxASSERT_MSG( !aManual, "manual autoplacement not currently supported for sheets" );
454 
455  wxSize textSize = m_fields[ SHEETNAME ].GetTextSize();
456  int margin = KiROUND( GetPenSize() / 2.0 + 4 + std::max( textSize.x, textSize.y ) * 0.5 );
457 
458  if( IsVerticalOrientation() )
459  {
460  m_fields[ SHEETNAME ].SetTextPos( m_pos + wxPoint( -margin, m_size.y ) );
461  m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
462  m_fields[ SHEETNAME ].SetVertJustify(GR_TEXT_VJUSTIFY_BOTTOM );
463  m_fields[ SHEETNAME ].SetTextAngle( TEXT_ANGLE_VERT );
464  }
465  else
466  {
467  m_fields[ SHEETNAME ].SetTextPos( m_pos + wxPoint( 0, -margin ) );
468  m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
469  m_fields[ SHEETNAME ].SetVertJustify(GR_TEXT_VJUSTIFY_BOTTOM );
470  m_fields[ SHEETNAME ].SetTextAngle( TEXT_ANGLE_HORIZ );
471  }
472 
473  textSize = m_fields[ SHEETFILENAME ].GetTextSize();
474  margin = KiROUND( GetPenSize() / 2.0 + 4 + std::max( textSize.x, textSize.y ) * 0.4 );
475 
476  if( IsVerticalOrientation() )
477  {
478  m_fields[ SHEETFILENAME ].SetTextPos( m_pos + wxPoint( m_size.x + margin, m_size.y ) );
479  m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
480  m_fields[ SHEETFILENAME ].SetVertJustify(GR_TEXT_VJUSTIFY_TOP );
481  m_fields[ SHEETFILENAME ].SetTextAngle( TEXT_ANGLE_VERT );
482  }
483  else
484  {
485  m_fields[ SHEETFILENAME ].SetTextPos( m_pos + wxPoint( 0, m_size.y + margin ) );
486  m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
487  m_fields[ SHEETFILENAME ].SetVertJustify(GR_TEXT_VJUSTIFY_TOP );
488  m_fields[ SHEETFILENAME ].SetTextAngle( TEXT_ANGLE_HORIZ );
489  }
490 
492 }
493 
494 
495 void SCH_SHEET::ViewGetLayers( int aLayers[], int& aCount ) const
496 {
497  aCount = 4;
498  aLayers[0] = LAYER_HIERLABEL;
499  aLayers[1] = LAYER_SHEET;
500  aLayers[2] = LAYER_SHEET_BACKGROUND;
501  aLayers[3] = LAYER_SELECTION_SHADOWS;
502 }
503 
504 
505 void SCH_SHEET::Print( wxDC* aDC, const wxPoint& aOffset )
506 {
507  wxString Text;
508  wxPoint pos = m_pos + aOffset;
509  int lineWidth = GetPenSize();
511 
512  GRRect( nullptr, aDC, pos.x, pos.y, pos.x + m_size.x, pos.y + m_size.y, lineWidth, color );
513 
514  for( SCH_FIELD& field : m_fields )
515  field.Print( aDC, aOffset );
516 
517  /* Draw text : SheetLabel */
518  for( SCH_SHEET_PIN* sheetPin : m_pins )
519  sheetPin->Print( aDC, aOffset );
520 }
521 
522 
524 {
525  wxPoint end;
526  EDA_RECT box( m_pos, m_size );
527  int lineWidth = GetPenSize();
528  int textLength = 0;
529 
530  // Calculate bounding box X size:
531  end.x = std::max( m_size.x, textLength );
532 
533  // Calculate bounding box pos:
534  end.y = m_size.y;
535  end += m_pos;
536 
537  box.SetEnd( end );
538  box.Inflate( lineWidth / 2 );
539 
540  return box;
541 }
542 
543 
545 {
547 
548  for( const SCH_FIELD& field : m_fields )
549  box.Merge( field.GetBoundingBox() );
550 
551  return box;
552 }
553 
554 
556 {
557  EDA_RECT box( m_pos, m_size );
558  return box.GetCenter();
559 }
560 
561 
563 {
564  int n = 0;
565 
566  if( m_screen )
567  {
568  for( auto aItem : m_screen->Items().OfType( SCH_COMPONENT_T ) )
569  {
570  SCH_COMPONENT* Cmp = (SCH_COMPONENT*) aItem;
571 
572  if( Cmp->GetField( VALUE )->GetText().GetChar( 0 ) != '#' )
573  n++;
574  }
575 
576  for( auto aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
577  n += static_cast<const SCH_SHEET*>( aItem )->ComponentCount();
578  }
579 
580  return n;
581 }
582 
583 
584 bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
585 {
586  if( m_screen )
587  {
588  // Only check the root sheet once and don't recurse.
589  if( !GetParent() )
590  {
591  if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
592  {
593  *aScreen = m_screen;
594  return true;
595  }
596  }
597 
598  for( auto aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
599  {
600  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
601  SCH_SCREEN* screen = sheet->m_screen;
602 
603  // Must use the screen's path (which is always absolute) rather than the
604  // sheet's (which could be relative).
605  if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
606  {
607  *aScreen = screen;
608  return true;
609  }
610 
611  if( sheet->SearchHierarchy( aFilename, aScreen ) )
612  return true;
613  }
614  }
615 
616  return false;
617 }
618 
619 
621 {
622  if( m_screen )
623  {
624  aList->push_back( this );
625 
626  if( m_screen == aScreen )
627  return true;
628 
629  for( auto item : m_screen->Items().OfType( SCH_SHEET_T ) )
630  {
631  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
632 
633  if( sheet->LocatePathOfScreen( aScreen, aList ) )
634  {
635  return true;
636  }
637  }
638 
639  aList->pop_back();
640  }
641 
642  return false;
643 }
644 
645 
647 {
648  int count = 1; //1 = this!!
649 
650  if( m_screen )
651  {
652  for( auto aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
653  count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
654  }
655 
656  return count;
657 }
658 
659 
661 {
662  aList.emplace_back( _( "Sheet Name" ), m_fields[ SHEETNAME ].GetText(), CYAN );
663  aList.emplace_back( _( "File Name" ), m_fields[ SHEETFILENAME ].GetText(), BROWN );
664 
665 #if 1 // Set to 1 to display the sheet UUID and hierarchical path
666  wxString msgU, msgL;
667  msgU << _( "UUID" ) << ": " << m_Uuid.AsString();
668  msgL << _( "Path" ) << ": " <<g_CurrentSheet->PathHumanReadable();
669 
670  aList.push_back( MSG_PANEL_ITEM( msgU, msgL, BLUE ) );
671 #endif
672 }
673 
674 
675 void SCH_SHEET::Rotate(wxPoint aPosition)
676 {
677  wxPoint prev = m_pos;
678 
679  RotatePoint( &m_pos, aPosition, 900 );
680  RotatePoint( &m_size.x, &m_size.y, 900 );
681 
682  if( m_size.x < 0 )
683  {
684  m_pos.x += m_size.x;
685  m_size.x = -m_size.x;
686  }
687 
688  if( m_size.y < 0 )
689  {
690  m_pos.y += m_size.y;
691  m_size.y = -m_size.y;
692  }
693 
694  // Pins must be rotated first as that's how we determine vertical vs horizontal
695  // orientation for auto-placement
696  for( SCH_SHEET_PIN* sheetPin : m_pins )
697  sheetPin->Rotate( aPosition );
698 
700  {
701  AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
702  }
703  else
704  {
705  // Move the fields to the new position because the component itself has moved.
706  for( SCH_FIELD& field : m_fields )
707  {
708  wxPoint pos = field.GetTextPos();
709  pos.x -= prev.x - m_pos.x;
710  pos.y -= prev.y - m_pos.y;
711  field.SetTextPos( pos );
712  }
713  }
714 }
715 
716 
717 void SCH_SHEET::MirrorX( int aXaxis_position )
718 {
719  MIRROR( m_pos.y, aXaxis_position );
720  m_pos.y -= m_size.y;
721 
722  for( SCH_SHEET_PIN* sheetPin : m_pins )
723  sheetPin->MirrorX( aXaxis_position );
724 }
725 
726 
727 void SCH_SHEET::MirrorY( int aYaxis_position )
728 {
729  MIRROR( m_pos.x, aYaxis_position );
730  m_pos.x -= m_size.x;
731 
732  for( SCH_SHEET_PIN* sheetPin : m_pins )
733  sheetPin->MirrorY( aYaxis_position );
734 }
735 
736 
737 void SCH_SHEET::SetPosition( const wxPoint& aPosition )
738 {
739  // Remember the sheet and all pin sheet positions must be
740  // modified. So use Move function to do that.
741  Move( aPosition - m_pos );
742 }
743 
744 
745 void SCH_SHEET::Resize( const wxSize& aSize )
746 {
747  if( aSize == m_size )
748  return;
749 
750  m_size = aSize;
751 
752  // Move the fields if we're in autoplace mode
754  AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
755 
756  // Move the sheet labels according to the new sheet size.
757  for( SCH_SHEET_PIN* sheetPin : m_pins )
758  sheetPin->ConstrainOnEdge( sheetPin->GetPosition() );
759 }
760 
761 
762 bool SCH_SHEET::Matches( wxFindReplaceData& aSearchData, void* aAuxData )
763 {
764  wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText( EDA_UNITS::MILLIMETRES ) );
765 
766  // Sheets are searchable via the child field and pin item text.
767  return false;
768 }
769 
770 
772 {
773  int id = 2;
774 
775  for( SCH_SHEET_PIN* pin : m_pins )
776  {
777  pin->SetNumber( id );
778  id++;
779  }
780 }
781 
782 
783 void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
784 {
785  for( SCH_SHEET_PIN* sheetPin : m_pins )
786  {
787  wxCHECK2_MSG( sheetPin->Type() == SCH_SHEET_PIN_T, continue,
788  wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) );
789 
790  sheetPin->GetEndPoints( aItemList );
791  }
792 }
793 
794 
795 bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
796  const SCH_SHEET_PATH* aPath )
797 {
798  bool changed = false;
799 
800  for( SCH_SHEET_PIN* sheetPin : m_pins )
801  changed |= sheetPin->UpdateDanglingState( aItemList );
802 
803  return changed;
804 }
805 
806 
807 void SCH_SHEET::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
808 {
809  for( SCH_SHEET_PIN* sheetPin : m_pins )
810  aPoints.push_back( sheetPin->GetPosition() );
811 }
812 
813 
814 SEARCH_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData, const KICAD_T aFilterTypes[] )
815 {
816  KICAD_T stype;
817 
818  for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p )
819  {
820  // If caller wants to inspect my type
821  if( stype == SCH_LOCATE_ANY_T || stype == Type() )
822  {
823  if( SEARCH_RESULT::QUIT == aInspector( this, NULL ) )
824  return SEARCH_RESULT::QUIT;
825  }
826 
827  if( stype == SCH_LOCATE_ANY_T || stype == SCH_FIELD_T )
828  {
829  // Test the sheet fields.
830  for( SCH_FIELD& field : m_fields )
831  {
832  if( SEARCH_RESULT::QUIT == aInspector( &field, this ) )
833  return SEARCH_RESULT::QUIT;
834  }
835  }
836 
837  if( stype == SCH_LOCATE_ANY_T || stype == SCH_SHEET_PIN_T )
838  {
839  // Test the sheet labels.
840  for( SCH_SHEET_PIN* sheetPin : m_pins )
841  {
842  if( SEARCH_RESULT::QUIT == aInspector( sheetPin, this ) )
843  return SEARCH_RESULT::QUIT;
844  }
845  }
846  }
847 
849 }
850 
851 
852 wxString SCH_SHEET::GetSelectMenuText( EDA_UNITS aUnits ) const
853 {
854  return wxString::Format( _( "Hierarchical Sheet %s" ), m_fields[ SHEETNAME ].GetText() );
855 }
856 
857 
859 {
861 }
862 
863 
864 bool SCH_SHEET::HitTest( const wxPoint& aPosition, int aAccuracy ) const
865 {
866  EDA_RECT rect = GetBodyBoundingBox();
867 
868  rect.Inflate( aAccuracy );
869 
870  return rect.Contains( aPosition );
871 }
872 
873 
874 bool SCH_SHEET::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
875 {
876  EDA_RECT rect = aRect;
877 
878  rect.Inflate( aAccuracy );
879 
880  if( aContained )
881  return rect.Contains( GetBodyBoundingBox() );
882 
883  return rect.Intersects( GetBodyBoundingBox() );
884 }
885 
886 
888 {
889  SCH_SHEET_PATH sheetPath = *aSheetPath;
890  sheetPath.push_back( this );
891 
892  for( SCH_SHEET_PIN* sheetPin : m_pins )
893  {
894  NETLIST_OBJECT* item = new NETLIST_OBJECT();
895  item->m_SheetPathInclude = sheetPath;
896  item->m_SheetPath = *aSheetPath;
897  item->m_Comp = sheetPin;
898  item->m_Link = this;
900  item->m_Label = sheetPin->GetText();
901  item->m_Start = item->m_End = sheetPin->GetPosition();
902  aNetListItems.push_back( item );
903 
904  SCH_CONNECTION conn;
905  if( conn.IsBusLabel( sheetPin->GetText() ) )
906  item->ConvertBusToNetListItems( aNetListItems );
907  }
908 }
909 
910 
911 void SCH_SHEET::Plot( PLOTTER* aPlotter )
912 {
913  wxString Text;
914  wxPoint pos;
915 
916  aPlotter->SetColor( aPlotter->ColorSettings()->GetColor( GetLayer() ) );
917 
918  int thickness = GetPenSize();
919  aPlotter->SetCurrentLineWidth( thickness );
920 
921  aPlotter->MoveTo( m_pos );
922  pos = m_pos;
923  pos.x += m_size.x;
924 
925  aPlotter->LineTo( pos );
926  pos.y += m_size.y;
927 
928  aPlotter->LineTo( pos );
929  pos = m_pos;
930  pos.y += m_size.y;
931 
932  aPlotter->LineTo( pos );
933  aPlotter->FinishTo( m_pos );
934 
935  for( SCH_FIELD field : m_fields )
936  field.Plot( aPlotter );
937 
938  aPlotter->SetColor( aPlotter->ColorSettings()->GetColor( GetLayer() ) );
939 
940  /* Draw texts : SheetLabel */
941  for( SCH_SHEET_PIN* sheetPin : m_pins )
942  sheetPin->Plot( aPlotter );
943 }
944 
945 
947 {
948  wxLogDebug( wxT( "Sheet assignment operator." ) );
949 
950  wxCHECK_MSG( Type() == aItem.Type(), *this,
951  wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " ) +
952  GetClass() );
953 
954  if( &aItem != this )
955  {
956  SCH_ITEM::operator=( aItem );
957 
958  SCH_SHEET* sheet = (SCH_SHEET*) &aItem;
959 
960  m_pos = sheet->m_pos;
961  m_size = sheet->m_size;
962  m_fields = sheet->m_fields;
963 
964  for( SCH_SHEET_PIN* pin : sheet->m_pins )
965  {
966  m_pins.emplace_back( new SCH_SHEET_PIN( *pin ) );
967  m_pins.back()->SetParent( this );
968  }
969  }
970 
971  return *this;
972 }
973 
974 
975 bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
976 {
977  if( Type() != aItem.Type() )
978  return Type() < aItem.Type();
979 
980  auto sheet = static_cast<const SCH_SHEET*>( &aItem );
981 
982  if (m_fields[ SHEETNAME ].GetText() != sheet->m_fields[ SHEETNAME ].GetText())
983  return m_fields[ SHEETNAME ].GetText() < sheet->m_fields[ SHEETNAME ].GetText();
984 
985  if (m_fields[ SHEETFILENAME ].GetText() != sheet->m_fields[ SHEETFILENAME ].GetText())
986  return m_fields[ SHEETFILENAME ].GetText() < sheet->m_fields[ SHEETFILENAME ].GetText();
987 
988  return false;
989 }
990 
991 
992 #if defined(DEBUG)
993 
994 void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
995 {
996  // XML output:
997  wxString s = GetClass();
998 
999  NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << ">" << " sheet_name=\""
1000  << TO_UTF8( m_fields[ SHEETNAME ].GetText() ) << '"' << ">\n";
1001 
1002  // show all the pins, and check the linked list integrity
1003  for( SCH_SHEET_PIN* sheetPin : m_pins )
1004  sheetPin->Show( nestLevel + 1, os );
1005 
1006  NestedSpace( nestLevel, os ) << "</" << s.Lower().mb_str() << ">\n" << std::flush;
1007 }
1008 
1009 #endif
Definition: colors.h:57
#define TEXT_ANGLE_HORIZ
void FinishTo(const wxPoint &pos)
Definition: plotter.h:283
EDA_UNITS
Definition: common.h:184
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
SCH_LAYER_ID m_Layer
Definition: sch_item.h:152
const wxString & GetFileName() const
Definition: sch_screen.h:157
void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers returns the layers the item is drawn on (which may be more than its "home" lay...
Definition: sch_sheet.cpp:495
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:584
SCH_SHEET_PIN * GetPin(const wxPoint &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:433
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:103
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
PNG memory record (file in memory).
Definition: bitmap_def.h:29
KIGFX::COLOR4D m_borderColor
Definition: sch_sheet.h:233
#define TEXT_ANGLE_VERT
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
Definition: sch_sheet.h:70
SCH_SHEET_PATH m_SheetPathInclude
virtual void SetColor(COLOR4D color)=0
static bool IsBusLabel(const wxString &aLabel)
Test if aLabel has a bus notation.
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Function GetEndPoints adds the schematic item end points to aItemList if the item has end points.
Definition: sch_sheet.cpp:783
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData) override
Function Matches compares the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:762
int CountSheets()
Count the number of sheets found in "this" sheet includeing all of the subsheets.
Definition: sch_sheet.cpp:646
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
friend class SCH_SHEET_PIN
Definition: sch_sheet.h:217
int color
Definition: DXF_plotter.cpp:61
int GetDefaultLineThickness()
Default line thickness used to draw/plot items having a default thickness line value (i....
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:149
EE_TYPE OfType(KICAD_T aType)
Definition: sch_rtree.h:219
int GetWidth() const
Definition: eda_rect.h:119
wxSize m_size
Definition: sch_sheet.h:230
SCH_SHEET * GetRootSheet()
Return the root sheet of this SCH_SHEET object.
Definition: sch_sheet.cpp:181
bool doIsConnected(const wxPoint &aPosition) const override
Function doIsConnected provides the object specific test to see if it is connected to aPosition.
Definition: sch_sheet.cpp:272
wxString AsString() const
Definition: common.cpp:170
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:290
bool UsesDefaultStroke() const
Test this sheet to see if the default stroke is used to draw the outline.
Definition: sch_sheet.cpp:193
SCH_SHEET_PATH m_SheetPath
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: sch_sheet.cpp:852
void Print(wxDC *aDC, const wxPoint &aOffset) override
Function Print Print a schematic item.
Definition: sch_sheet.cpp:505
bool operator<(const SCH_ITEM &aItem) const override
Definition: sch_sheet.cpp:975
int GetPenSize() const override
Function GetPenSize virtual pure.
Definition: sch_sheet.cpp:445
wxPoint m_pos
Definition: sch_sheet.h:229
EDA_ITEM * m_Comp
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:230
bool Contains(const wxPoint &aPoint) const
Function Contains.
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
#define MIN_SHEET_WIDTH
Definition: sch_sheet.h:42
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:308
int GetBottom() const
Definition: eda_rect.h:124
void pop_back()
Forwarded method from std::vector.
NETLIST_OBJECT_LIST is a container holding and owning NETLIST_OBJECTs, which are connected items in a...
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:108
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
Definition: sch_sheet.cpp:172
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:123
void LineTo(const wxPoint &pos)
Definition: plotter.h:278
void renumberPins()
Renumber the sheet pins in the sheet.
Definition: sch_sheet.cpp:771
#define VALUE
wxString GetClass() const override
Function GetClass returns the class name.
Definition: sch_sheet.h:252
void RemovePin(SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:240
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:844
int GetBorderWidth() const
Definition: sch_sheet.h:287
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: sch_sheet.cpp:544
#define NULL
SCH_SHEET_PATH * g_CurrentSheet
With the new connectivity algorithm, many more places than before want to know what the current sheet...
void MirrorX(int aXaxis_position) override
Function MirrorX mirrors item relative to the X axis about aXaxis_position.
Definition: sch_sheet.cpp:717
const BITMAP_OPAQUE add_hierarchical_subsheet_xpm[1]
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:218
COLOR_SETTINGS * ColorSettings()
Definition: plotter.h:145
int m_borderWidth
Definition: sch_sheet.h:232
void SetEnd(int x, int y)
Definition: eda_rect.h:192
std::vector< SCH_SHEET_PIN * > m_pins
The list of sheet connection points.
Definition: sch_sheet.h:224
wxString GetText(GRAPHIC_PINSHAPE aShape)
Definition: pin_shape.cpp:58
int GetRight() const
Definition: eda_rect.h:121
Definition: colors.h:59
int GetMinHeight() const
Return the minimum height that the sheet can be resized based on the sheet pin positions.
Definition: sch_sheet.cpp:368
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
Definition: sch_sheet.cpp:814
EDA_ITEM * GetParent() const
Definition: base_struct.h:217
const EDA_RECT GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
Definition: sch_sheet.cpp:523
wxLogTrace helper definitions.
static const wxString GetDefaultFieldName(int aFieldNdx)
Definition: sch_sheet.cpp:43
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:84
SCH_SHEET_PATH.
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
Definition: sch_sheet.cpp:407
void Rotate(wxPoint aPosition) override
Function Rotate rotates the item around aPosition 90 degrees in the clockwise direction.
Definition: sch_sheet.cpp:675
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
int GetHeight() const
Definition: eda_rect.h:120
int ComponentCount() const
Count our own components, without the power components.
Definition: sch_sheet.cpp:562
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:215
const KIID m_Uuid
Definition: base_struct.h:169
SCH_LAYER_ID GetLayer() const
Function GetLayer returns the layer this item is on.
Definition: sch_item.h:224
void MoveTo(const wxPoint &pos)
Definition: plotter.h:273
SCH_SHEET(const wxPoint &pos=wxPoint(0, 0))
Definition: sch_sheet.cpp:70
std::vector< SCH_FIELD > m_fields
Definition: sch_sheet.h:226
void GetConnectionPoints(std::vector< wxPoint > &aPoints) const override
Function GetConnectionPoints add all the connection points for this item to aPoints.
Definition: sch_sheet.cpp:807
bool HasUndefinedPins()
Check all sheet labels against schematic for undefined hierarchical labels.
Definition: sch_sheet.cpp:305
int GetMinWidth() const
Return the minimum width of the sheet based on the widths of the sheet pin text.
Definition: sch_sheet.cpp:328
void DecRefCount()
Definition: sch_screen.cpp:167
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:620
Base plotter engine class.
Definition: plotter.h:104
COLOR4D GetColor(int aLayer) const
void GetMsgPanelInfo(EDA_UNITS aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
Definition: sch_sheet.cpp:660
void SwapData(SCH_ITEM *aItem) override
Function SwapData swap the internal data structures aItem with the schematic item.
Definition: sch_sheet.cpp:203
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:101
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:143
see class PGM_BASE
void Plot(PLOTTER *aPlotter) override
Function Plot plots the schematic item to aPlotter.
Definition: sch_sheet.cpp:911
const wxChar *const traceFindItem
Flag to enable find debug tracing.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList, const SCH_SHEET_PATH *aPath=nullptr) override
Function IsDanglingStateChanged tests the schematic item to aItemList to check if it's dangling state...
Definition: sch_sheet.cpp:795
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
#define _(s)
Definition: 3d_actions.cpp:33
bool IsVerticalOrientation() const
Definition: sch_sheet.cpp:284
void MirrorY(int aYaxis_position) override
Function MirrorY mirrors item relative to the Y axis about aYaxis_position.
Definition: sch_sheet.cpp:727
void SetPosition(const wxPoint &aPosition) override
Function SetPosition set the schematic item position to aPosition.
Definition: sch_sheet.cpp:737
EE_RTREE & Items()
Definition: sch_screen.h:127
KIGFX::COLOR4D m_backgroundColor
Definition: sch_sheet.h:234
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:99
SCH_SCREEN * m_screen
Screen that contains the physical data for the sheet.
Definition: sch_sheet.h:221
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:61
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
#define MIN_SHEET_HEIGHT
Definition: sch_sheet.h:43
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
virtual wxString GetClass() const override
Function GetClass returns the class name.
Definition: sch_item.h:174
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Definition: sch_sheet.cpp:858
bool HasPin(const wxString &aName)
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:260
wxPoint GetRotationCenter() const
Rotating around the boundingBox's center can cause walking when the sheetname or filename is longer t...
Definition: sch_sheet.cpp:555
virtual wxString GetShownText() const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:129
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:451
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
SEARCH_RESULT
Definition: base_struct.h:54
const wxPoint GetCenter() const
Definition: eda_rect.h:117
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
Definition of the NETLIST_OBJECT class.
Message panel definition file.
NETLIST_ITEM m_Type
SCH_ITEM * m_Link
SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
void Move(const wxPoint &aMoveVector) override
Function Move moves the item by aMoveVector to a new position.
Definition: sch_sheet.h:506
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:123
SCH_SHEET & operator=(const SCH_ITEM &aSheet)
Definition: sch_sheet.cpp:946
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
void IncRefCount()
Definition: sch_screen.cpp:161
void ConvertBusToNetListItems(NETLIST_OBJECT_LIST &aNetListItems)
Function ConvertBusToNetListItems breaks the text of a bus label type net list object into as many me...
int GetRefCount() const
Definition: sch_screen.h:170
FIELDS_AUTOPLACED m_fieldsAutoplaced
Definition: sch_sheet.h:227
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
void Resize(const wxSize &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:745
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:40
bool HitTest(const wxPoint &aPosition, int aAccuracy) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: sch_sheet.cpp:864
void GetNetListItem(NETLIST_OBJECT_LIST &aNetListItems, SCH_SHEET_PATH *aSheetPath) override
Function GetNetListItem creates a new NETLIST_OBJECT for the schematic object and adds it to aNetList...
Definition: sch_sheet.cpp:887
Definition: colors.h:62