KiCad PCB EDA Suite
sch_screen.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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6  * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
7  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
32 #include <wx/filefn.h>
33 
34 #include <eda_item.h>
35 #include <eda_rect.h>
36 #include <id.h>
37 #include <string_utils.h>
38 #include <kiway.h>
39 #include <plotters/plotter.h>
40 #include <project.h>
41 #include <reporter.h>
42 #include <sch_draw_panel.h>
43 #include <sch_edit_frame.h>
44 #include <sch_item.h>
45 
46 #include <symbol_library.h>
47 #include <connection_graph.h>
48 #include <lib_pin.h>
49 #include <sch_symbol.h>
50 #include <sch_junction.h>
51 #include <sch_line.h>
52 #include <sch_marker.h>
53 #include <sch_sheet.h>
54 #include <sch_sheet_pin.h>
55 #include <sch_text.h>
56 #include <schematic.h>
57 #include <symbol_lib_table.h>
58 #include <tool/common_tools.h>
59 
60 #include <algorithm>
61 
62 // TODO(JE) Debugging only
63 #include <profile.h>
64 #include "sch_bus_entry.h"
65 
67  BASE_SCREEN( aParent, SCH_SCREEN_T ),
68  m_fileFormatVersionAtLoad( 0 ),
69  m_paper( wxT( "A4" ) ),
70  m_isReadOnly( false ),
71  m_fileExists( false )
72 {
74  m_refCount = 0;
75  m_zoomInitialized = false;
76  m_LastZoomLevel = 1.0;
77 
78  // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
79  m_Center = false;
80 
81  InitDataPoints( m_paper.GetSizeIU() );
82 }
83 
84 
86 {
88  FreeDrawList();
89 }
90 
91 
93 {
94  wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
95  wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
96 
97  return static_cast<SCHEMATIC*>( GetParent() );
98 }
99 
100 
102 {
103  for( auto libSymbol : m_libSymbols )
104  delete libSymbol.second;
105 
106  m_libSymbols.clear();
107 }
108 
109 
110 void SCH_SCREEN::SetFileName( const wxString& aFileName )
111 {
112  wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
113 
114  m_fileName = aFileName;
115 }
116 
117 
119 {
120  m_refCount++;
121 }
122 
123 
125 {
126  wxCHECK_RET( m_refCount != 0,
127  wxT( "Screen reference count already zero. Bad programmer!" ) );
128  m_refCount--;
129 }
130 
131 
132 bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
133 {
134  EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
135 
136  return sheets.begin() != sheets.end();
137 }
138 
139 
140 bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
141 {
142  return aItem && SCH_SCREEN_T == aItem->Type();
143 }
144 
145 
147 {
148  if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
149  {
150  // Ensure the item can reach the SCHEMATIC through this screen
151  aItem->SetParent( this );
152 
153  if( aItem->Type() == SCH_SYMBOL_T )
154  {
155  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
156 
157  if( symbol->GetLibSymbolRef() )
158  {
159  symbol->GetLibSymbolRef()->GetDrawItems().sort();
160 
161  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
162 
163  if( it == m_libSymbols.end() || !it->second )
164  {
166  new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
167  }
168  else
169  {
170  // The original library symbol may have changed since the last time
171  // it was added to the schematic. If it has changed, then a new name
172  // must be created for the library symbol list to prevent all of the
173  // other schematic symbols referencing that library symbol from changing.
174  LIB_SYMBOL* foundSymbol = it->second;
175 
176  foundSymbol->GetDrawItems().sort();
177 
178  if( *foundSymbol != *symbol->GetLibSymbolRef() )
179  {
180  int cnt = 1;
181  wxString newName;
182 
183  newName.Printf( wxT( "%s_%d" ), symbol->GetLibId().GetUniStringLibItemName(),
184  cnt );
185 
186  while( m_libSymbols.find( newName ) != m_libSymbols.end() )
187  {
188  cnt += 1;
189  newName.Printf( wxT( "%s_%d" ), symbol->GetLibId().GetUniStringLibItemName(),
190  cnt );
191  }
192 
193  // Update the schematic symbol library link as this symbol only exists
194  // in the schematic.
195  symbol->SetSchSymbolLibraryName( newName );
196 
197  LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
198  LIB_ID newLibId( wxEmptyString, newName );
199 
200  newLibSymbol->SetLibId( newLibId );
201  newLibSymbol->SetName( newName );
202  symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
203  m_libSymbols[newName] = newLibSymbol;
204  }
205  }
206  }
207  }
208 
209  m_rtree.insert( aItem );
211  }
212 }
213 
214 
216 {
217  wxCHECK_RET( aScreen, wxT( "Invalid screen object." ) );
218 
219  // No need to descend the hierarchy. Once the top level screen is copied, all of its
220  // children are copied as well.
221  for( SCH_ITEM* aItem : aScreen->m_rtree )
222  Append( aItem );
223 
224  aScreen->Clear( false );
225 }
226 
227 
228 void SCH_SCREEN::Clear( bool aFree )
229 {
230  if( aFree )
231  {
232  FreeDrawList();
233  clearLibSymbols();
234  }
235  else
236  {
237  m_rtree.clear();
238  }
239 
240  // Clear the project settings
242 
243  m_titles.Clear();
244 }
245 
246 
248 {
249  // We don't know which order we will encounter dependent items (e.g. pins or fields), so
250  // we store the items to be deleted until we've fully cleared the tree before deleting
251  std::vector<SCH_ITEM*> delete_list;
252 
253  std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
254  []( SCH_ITEM* aItem )
255  {
256  return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
257  } );
258 
259  m_rtree.clear();
260 
261  for( SCH_ITEM* item : delete_list )
262  delete item;
263 }
264 
265 
267 {
268  if( Remove( aItem ) )
269  Append( aItem );
270 }
271 
272 
274 {
275  bool retv = m_rtree.remove( aItem );
276 
277  // Check if the library symbol for the removed schematic symbol is still required.
278  if( retv && aItem->Type() == SCH_SYMBOL_T )
279  {
280  SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
281 
282  bool removeUnusedLibSymbol = true;
283 
284  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
285  {
286  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
287 
288  if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
289  {
290  removeUnusedLibSymbol = false;
291  break;
292  }
293  }
294 
295  if( removeUnusedLibSymbol )
296  {
297  auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
298 
299  if( it != m_libSymbols.end() )
300  {
301  delete it->second;
302  m_libSymbols.erase( it );
303  }
304  }
305  }
306 
307  return retv;
308 }
309 
310 
312 {
313  wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
314 
315  // Markers are not saved in the file, no need to flag as modified.
316  // TODO: Maybe we should have a listing somewhere of items that aren't saved?
317  if( aItem->Type() != SCH_MARKER_T )
319 
320  Remove( aItem );
321 
322  if( aItem->Type() == SCH_SHEET_PIN_T )
323  {
324  // This structure is attached to a sheet, get the parent sheet object.
325  SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
326  SCH_SHEET* sheet = sheetPin->GetParent();
327  wxCHECK_RET( sheet, wxT( "Sheet pin parent not properly set, bad programmer!" ) );
328  sheet->RemovePin( sheetPin );
329  return;
330  }
331 
332  delete aItem;
333 }
334 
335 
336 bool SCH_SCREEN::CheckIfOnDrawList( const SCH_ITEM* aItem ) const
337 {
338  return m_rtree.contains( aItem, true );
339 }
340 
341 
342 SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType ) const
343 {
344  EDA_RECT bbox;
345  bbox.SetOrigin( aPosition );
346  bbox.Inflate( aAccuracy );
347 
348  for( SCH_ITEM* item : Items().Overlapping( aType, bbox ) )
349  {
350  if( item->HitTest( aPosition, aAccuracy ) )
351  return item;
352  }
353 
354  return nullptr;
355 }
356 
357 
358 std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
359 {
360  std::set<SCH_ITEM*> retval;
361  std::stack<SCH_LINE*> to_search;
362 
363  wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
364 
365  to_search.push( aSegment );
366 
367  while( !to_search.empty() )
368  {
369  SCH_LINE* test_item = to_search.top();
370  to_search.pop();
371 
372  for( SCH_ITEM* item : Items().Overlapping( SCH_JUNCTION_T, test_item->GetBoundingBox() ) )
373  {
374  if( test_item->IsEndPoint( item->GetPosition() ) )
375  retval.insert( item );
376  }
377 
378  for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, test_item->GetBoundingBox() ) )
379  {
380  // Skip connecting lines on different layers (e.g. buses)
381  if( test_item->GetLayer() != item->GetLayer() )
382  continue;
383 
384  SCH_LINE* line = static_cast<SCH_LINE*>( item );
385 
386  if( ( test_item->IsEndPoint( line->GetStartPoint() )
387  && !GetPin( line->GetStartPoint(), nullptr, true ) )
388  || ( test_item->IsEndPoint( line->GetEndPoint() )
389  && !GetPin( line->GetEndPoint(), nullptr, true ) ) )
390  {
391  auto result = retval.insert( line );
392 
393  if( result.second )
394  to_search.push( line );
395  }
396  }
397  }
398 
399  return retval;
400 }
401 
402 
403 bool SCH_SCREEN::IsJunction( const wxPoint& aPosition ) const
404 {
405  bool hasExplicitJunction;
406  bool hasBusEntry;
407  bool isJunction = doIsJunction( aPosition, false, &hasExplicitJunction, &hasBusEntry );
408 
409  return isJunction;
410 }
411 
412 
413 bool SCH_SCREEN::IsExplicitJunction( const wxPoint& aPosition ) const
414 {
415  bool hasExplicitJunction;
416  bool hasBusEntry;
417  bool isJunction = doIsJunction( aPosition, false, &hasExplicitJunction, &hasBusEntry );
418 
419  return isJunction && !hasBusEntry;
420 }
421 
422 
423 bool SCH_SCREEN::IsExplicitJunctionNeeded( const wxPoint& aPosition ) const
424 {
425  bool hasExplicitJunction;
426  bool hasBusEntry;
427  bool isJunction = doIsJunction( aPosition, false, &hasExplicitJunction, &hasBusEntry );
428 
429  return isJunction && !hasBusEntry && !hasExplicitJunction;
430 }
431 
432 
433 bool SCH_SCREEN::IsExplicitJunctionAllowed( const wxPoint& aPosition ) const
434 {
435  bool hasExplicitJunction;
436  bool hasBusEntry;
437  bool isJunction = doIsJunction( aPosition, true, &hasExplicitJunction, &hasBusEntry );
438 
439  return isJunction && !hasBusEntry;
440 }
441 
442 
443 
444 bool SCH_SCREEN::doIsJunction( const wxPoint& aPosition, bool aBreakCrossings,
445  bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const
446 {
447  enum layers { WIRES = 0, BUSES };
448 
449  *aHasExplicitJunctionDot = false;
450  *aHasBusEntry = false;
451 
452  bool breakLines[ 2 ] = { false };
453  std::unordered_set<int> exitAngles[ 2 ];
454  std::vector<const SCH_LINE*> midPointLines[ 2 ];
455 
456  // A pin at 90º still shouldn't match a line at 90º so just give pins unique numbers
457  int uniqueAngle = 10000;
458 
459  for( const SCH_ITEM* item : Items().Overlapping( aPosition ) )
460  {
461  if( item->GetEditFlags() & STRUCT_DELETED )
462  continue;
463 
464  switch( item->Type() )
465  {
466  case SCH_JUNCTION_T:
467  if( item->HitTest( aPosition, -1 ) )
468  *aHasExplicitJunctionDot = true;
469 
470  break;
471 
472  case SCH_LINE_T:
473  {
474  const SCH_LINE* line = static_cast<const SCH_LINE*>( item );
475  int layer;
476 
477  if( line->GetStartPoint() == line->GetEndPoint() )
478  break;
479  else if( line->GetLayer() == LAYER_WIRE )
480  layer = WIRES;
481  else if( line->GetLayer() == LAYER_BUS )
482  layer = BUSES;
483  else
484  break;
485 
486  if( line->IsConnected( aPosition ) )
487  {
488  breakLines[ layer ] = true;
489  exitAngles[ layer ].insert( line->GetAngleFrom( aPosition ) );
490  }
491  else if( line->HitTest( aPosition, -1 ) )
492  {
493  if( aBreakCrossings )
494  breakLines[ layer ] = true;
495 
496  // Defer any line midpoints until we know whether or not we're breaking them
497  midPointLines[ layer ].push_back( line );
498  }
499  }
500  break;
501 
503  if( item->IsConnected( aPosition ) )
504  {
505  breakLines[ BUSES ] = true;
506  exitAngles[ BUSES ].insert( uniqueAngle++ );
507  breakLines[ WIRES ] = true;
508  exitAngles[ WIRES ].insert( uniqueAngle++ );
509  *aHasBusEntry = true;
510  }
511 
512  break;
513 
514  case SCH_SYMBOL_T:
515  case SCH_SHEET_T:
516  if( item->IsConnected( aPosition ) )
517  {
518  breakLines[ WIRES ] = true;
519  exitAngles[ WIRES ].insert( uniqueAngle++ );
520  }
521 
522  break;
523 
524  default:
525  break;
526  }
527  }
528 
529  for( int layer : { WIRES, BUSES } )
530  {
531  if( breakLines[ layer ] )
532  {
533  for( const SCH_LINE* line : midPointLines[ layer ] )
534  {
535  exitAngles[ layer ].insert( line->GetAngleFrom( aPosition ) );
536  exitAngles[ layer ].insert( line->GetReverseAngleFrom( aPosition ) );
537  }
538  }
539  }
540 
541  return exitAngles[ WIRES ].size() >= 3 || exitAngles[ BUSES ].size() >= 3;
542 }
543 
544 
545 bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer ) const
546 {
547  wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
548  wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
549 
550  switch( aLayer )
551  {
552  case LAYER_BUS:
553  {
554  if( GetBus( aPosition ) )
555  return true;
556 
557  SCH_SHEET_PIN* sheetPin = GetSheetPin( aPosition );
558 
559  if( sheetPin && sheetPin->IsConnected( aPosition ) )
560  return true;
561 
562  SCH_TEXT* label = GetLabel( aPosition );
563 
564  if( label && label->IsConnected( aPosition ) )
565  return true;
566  }
567  break;
568 
569  case LAYER_NOTES:
570  {
571  if( GetLine( aPosition ) )
572  return true;
573  }
574  break;
575 
576  case LAYER_WIRE:
577  {
578  if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T) )
579  return true;
580 
581  if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
582  return true;
583 
584  if( GetPin( aPosition, nullptr, true ) )
585  return true;
586 
587  if( GetWire( aPosition ) )
588  return true;
589 
590  SCH_TEXT* label = GetLabel( aPosition, 1 );
591 
592  if( label && label->IsConnected( aPosition ) )
593  return true;
594 
595  SCH_SHEET_PIN* sheetPin = GetSheetPin( aPosition );
596 
597  if( sheetPin && sheetPin->IsConnected( aPosition ) )
598  return true;
599  }
600  break;
601 
602  default:
603  break;
604  }
605 
606  return false;
607 }
608 
609 
611 {
612  wxCHECK_RET( Schematic(), wxT( "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" ) );
613 
614  wxString msg;
615  std::unique_ptr< LIB_SYMBOL > libSymbol;
616  std::vector<SCH_SYMBOL*> symbols;
617  SYMBOL_LIB_TABLE* libs = Schematic()->Prj().SchSymbolLibTable();
618 
619  // This will be a nullptr if an s-expression schematic is loaded.
620  SYMBOL_LIBS* legacyLibs = Schematic()->Prj().SchLibs();
621 
622  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
623  symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
624 
625  // Remove them from the R tree. There bounding box size may change.
626  for( SCH_SYMBOL* symbol : symbols )
627  Remove( symbol );
628 
629  // Clear all existing symbol links.
630  clearLibSymbols();
631 
632  for( SCH_SYMBOL* symbol : symbols )
633  {
634  LIB_SYMBOL* tmp = nullptr;
635  libSymbol.reset();
636 
637  // If the symbol is already in the internal library, map the symbol to it.
638  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
639 
640  if( ( it != m_libSymbols.end() ) )
641  {
642  if( aReporter )
643  {
644  msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
645  symbol->GetField( REFERENCE_FIELD )->GetText(),
646  symbol->GetField( VALUE_FIELD )->GetText(),
647  UnescapeString( symbol->GetLibId().Format() ) );
648  aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
649  }
650 
651  // Internal library symbols are already flattened so just make a copy.
652  symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
653  continue;
654  }
655 
656  if( !symbol->GetLibId().IsValid() )
657  {
658  if( aReporter )
659  {
660  msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
661  "Unable to link library symbol." ),
662  UnescapeString( symbol->GetLibId().Format() ) );
663  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
664  }
665 
666  continue;
667  }
668 
669  // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
670  // is not found in the table so check if the library still exists in the table
671  // before attempting to load the symbol.
672  if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
673  {
674  if( aReporter )
675  {
676  msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
677  "available. Unable to link library symbol." ),
678  symbol->GetLibId().GetLibNickname().wx_str() );
679  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
680  }
681 
682  continue;
683  }
684 
685  if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
686  {
687  try
688  {
689  tmp = libs->LoadSymbol( symbol->GetLibId() );
690  }
691  catch( const IO_ERROR& ioe )
692  {
693  if( aReporter )
694  {
695  msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
696  UnescapeString( symbol->GetLibId().Format() ) );
697  aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
698  }
699  }
700  }
701 
702  if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
703  {
704  SYMBOL_LIB& legacyCacheLib = legacyLibs->at( 0 );
705 
706  // It better be the cache library.
707  wxCHECK2( legacyCacheLib.IsCache(), continue );
708 
709  wxString id = symbol->GetLibId().Format();
710 
711  id.Replace( ':', '_' );
712 
713  if( aReporter )
714  {
715  msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
716  symbol->GetField( REFERENCE_FIELD )->GetText(),
717  symbol->GetField( VALUE_FIELD )->GetText(),
718  UnescapeString( id ) );
719  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
720  }
721 
722  tmp = legacyCacheLib.FindSymbol( id );
723  }
724 
725  if( tmp )
726  {
727  // We want a full symbol not just the top level child symbol.
728  libSymbol = tmp->Flatten();
729  libSymbol->SetParent();
730 
731  m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
732  new LIB_SYMBOL( *libSymbol.get() ) } );
733 
734  if( aReporter )
735  {
736  msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
737  symbol->GetField( REFERENCE_FIELD )->GetText(),
738  symbol->GetField( VALUE_FIELD )->GetText(),
739  UnescapeString( symbol->GetLibId().Format() ) );
740  aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
741  }
742  }
743  else
744  {
745  if( aReporter )
746  {
747  msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
748  symbol->GetField( REFERENCE_FIELD )->GetText(),
749  symbol->GetField( VALUE_FIELD )->GetText() );
750  aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
751  }
752  }
753 
754  symbol->SetLibSymbol( libSymbol.release() );
755  }
756 
757  // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
758  // item with the new bbox
759  for( SCH_SYMBOL* symbol : symbols )
760  Append( symbol );
761 }
762 
763 
765 {
766  std::vector<SCH_SYMBOL*> symbols;
767 
768  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
769  symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
770 
771  for( SCH_SYMBOL* symbol : symbols )
772  {
773  // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
774  m_rtree.remove( symbol );
775 
776  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
777 
778  LIB_SYMBOL* libSymbol = nullptr;
779 
780  if( it != m_libSymbols.end() )
781  libSymbol = new LIB_SYMBOL( *it->second );
782 
783  symbol->SetLibSymbol( libSymbol );
784 
785  m_rtree.insert( symbol );
786  }
787 }
788 
789 
791 {
792  for( SCH_ITEM* item : Items() )
793  item->SetConnectivityDirty( true );
794 }
795 
796 
797 void SCH_SCREEN::Print( const RENDER_SETTINGS* aSettings )
798 {
799  // Ensure links are up to date, even if a library was reloaded for some reason:
800  std::vector<SCH_ITEM*> junctions;
801  std::vector<SCH_ITEM*> bitmaps;
802  std::vector<SCH_ITEM*> other;
803 
804  for( SCH_ITEM* item : Items() )
805  {
806  if( item->IsMoving() || item->IsResized() )
807  continue;
808 
809  if( item->Type() == SCH_JUNCTION_T )
810  junctions.push_back( item );
811  else if( item->Type() == SCH_BITMAP_T )
812  bitmaps.push_back( item );
813  else
814  other.push_back( item );
815  }
816 
818  std::sort( other.begin(), other.end(),
819  []( const SCH_ITEM* a, const SCH_ITEM* b )
820  {
821  if( a->Type() == b->Type() )
822  return a->GetLayer() > b->GetLayer();
823 
824  return a->Type() > b->Type();
825  } );
826 
827  for( SCH_ITEM* item : bitmaps )
828  item->Print( aSettings, wxPoint( 0, 0 ) );
829 
830  for( SCH_ITEM* item : other )
831  item->Print( aSettings, wxPoint( 0, 0 ) );
832 
833  for( SCH_ITEM* item : junctions )
834  item->Print( aSettings, wxPoint( 0, 0 ) );
835 }
836 
837 
838 void SCH_SCREEN::Plot( PLOTTER* aPlotter ) const
839 {
840  // Ensure links are up to date, even if a library was reloaded for some reason:
841  std::vector< SCH_ITEM* > junctions;
842  std::vector< SCH_ITEM* > bitmaps;
843  std::vector< SCH_ITEM* > other;
844 
845  for( SCH_ITEM* item : Items() )
846  {
847  if( item->IsMoving() || item->IsResized() )
848  continue;
849 
850  if( item->Type() == SCH_JUNCTION_T )
851  junctions.push_back( item );
852  else if( item->Type() == SCH_BITMAP_T )
853  bitmaps.push_back( item );
854  else
855  other.push_back( item );
856  }
857 
859  std::sort( other.begin(), other.end(),
860  []( const SCH_ITEM* a, const SCH_ITEM* b )
861  {
862  if( a->Type() == b->Type() )
863  return a->GetLayer() > b->GetLayer();
864 
865  return a->Type() > b->Type();
866  } );
867 
868  int defaultPenWidth = aPlotter->RenderSettings()->GetDefaultPenWidth();
869 
870  // Bitmaps are drawn first to ensure they are in the background
871  // This is particularly important for the wxPostscriptDC (used in *nix printers) as
872  // the bitmap PS command clears the screen
873  for( const SCH_ITEM* item : bitmaps )
874  {
875  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
876  item->Plot( aPlotter );
877  }
878 
879  for( const SCH_ITEM* item : other )
880  {
881  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
882  item->Plot( aPlotter );
883  }
884 
885  for( const SCH_ITEM* item : junctions )
886  {
887  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
888  item->Plot( aPlotter );
889  }
890 }
891 
892 
894 {
895  for( SCH_ITEM* item : Items() )
896  item->ClearTempFlags();
897 }
898 
899 
900 LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_SYMBOL** aSymbol,
901  bool aEndPointOnly ) const
902 {
903  SCH_SYMBOL* candidate = nullptr;
904  LIB_PIN* pin = nullptr;
905 
906  for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
907  {
908  candidate = static_cast<SCH_SYMBOL*>( item );
909 
910  if( aEndPointOnly )
911  {
912  pin = nullptr;
913 
914  if( !candidate->GetLibSymbolRef() )
915  continue;
916 
917  for( pin = candidate->GetLibSymbolRef()->GetNextPin(); pin;
918  pin = candidate->GetLibSymbolRef()->GetNextPin( pin ) )
919  {
920  // Skip items not used for this part.
921  if( candidate->GetUnit() && pin->GetUnit() &&
922  ( pin->GetUnit() != candidate->GetUnit() ) )
923  continue;
924 
925  if( candidate->GetConvert() && pin->GetConvert() &&
926  ( pin->GetConvert() != candidate->GetConvert() ) )
927  continue;
928 
929  if( candidate->GetPinPhysicalPosition( pin ) == aPosition )
930  break;
931  }
932 
933  if( pin )
934  break;
935  }
936  else
937  {
938  pin = (LIB_PIN*) candidate->GetDrawItem( aPosition, LIB_PIN_T );
939 
940  if( pin )
941  break;
942  }
943  }
944 
945  if( pin && aSymbol )
946  *aSymbol = candidate;
947 
948  return pin;
949 }
950 
951 
952 SCH_SHEET_PIN* SCH_SCREEN::GetSheetPin( const wxPoint& aPosition ) const
953 {
954  SCH_SHEET_PIN* sheetPin = nullptr;
955 
956  for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
957  {
958  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
959 
960  sheetPin = sheet->GetPin( aPosition );
961 
962  if( sheetPin )
963  break;
964  }
965 
966  return sheetPin;
967 }
968 
969 
970 size_t SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const
971 {
972  size_t count = 0;
973 
974  for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
975  {
976  if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
977  count++;
978  }
979 
980  return count;
981 }
982 
983 
985 {
986 
987  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
988  {
989  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
990 
991  symbol->ClearAnnotation( aSheetPath );
992  }
993 }
994 
995 
997 {
998  if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
999  return;
1000 
1001  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1002  {
1003  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1004 
1005  // Add (when not existing) all sheet path entries
1006  for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1007  symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1008  }
1009 }
1010 
1011 
1012 void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1013 {
1014  static KICAD_T hierarchicalTypes[] = { SCH_SYMBOL_T, SCH_SHEET_T, SCH_GLOBAL_LABEL_T, EOT };
1015 
1016  for( SCH_ITEM* item : Items() )
1017  {
1018  if( item->IsType( hierarchicalTypes ) )
1019  aItems->push_back( item );
1020  }
1021 }
1022 
1023 
1024 void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1025 {
1026  for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1027  aItems->push_back( item );
1028 
1029  std::sort( aItems->begin(), aItems->end(),
1030  []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1031  {
1032  if( a->GetPosition().x == b->GetPosition().x )
1033  {
1034  // Ensure deterministic sort
1035  if( a->GetPosition().y == b->GetPosition().y )
1036  return a->m_Uuid < b->m_Uuid;
1037 
1038  return a->GetPosition().y < b->GetPosition().y;
1039  }
1040  else
1041  return a->GetPosition().x < b->GetPosition().x;
1042  } );
1043 }
1044 
1045 
1047  std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1048 {
1049  std::vector<DANGLING_END_ITEM> endPoints;
1050 
1051  for( SCH_ITEM* item : Items() )
1052  {
1053  if( item->IsConnectable() )
1054  {
1055  endPoints.clear();
1056 
1057  for( SCH_ITEM* overlapping : Items().Overlapping( item->GetBoundingBox() ) )
1058  overlapping->GetEndPoints( endPoints );
1059 
1060  if( item->UpdateDanglingState( endPoints, aPath ) )
1061  {
1062  if( aChangedHandler )
1063  (*aChangedHandler)( item );
1064  }
1065  }
1066  }
1067 }
1068 
1069 
1070 SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLayer,
1071  SCH_LINE_TEST_T aSearchType ) const
1072 {
1073  // an accuracy of 0 had problems with rounding errors; use at least 1
1074  aAccuracy = std::max( aAccuracy, 1 );
1075 
1076  for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1077  {
1078  if( item->Type() != SCH_LINE_T )
1079  continue;
1080 
1081  if( item->GetLayer() != aLayer )
1082  continue;
1083 
1084  if( !item->HitTest( aPosition, aAccuracy ) )
1085  continue;
1086 
1087  switch( aSearchType )
1088  {
1089  case ENTIRE_LENGTH_T:
1090  return (SCH_LINE*) item;
1091 
1092  case EXCLUDE_END_POINTS_T:
1093  if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1094  return (SCH_LINE*) item;
1095  break;
1096 
1097  case END_POINTS_ONLY_T:
1098  if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1099  return (SCH_LINE*) item;
1100  }
1101  }
1102 
1103  return nullptr;
1104 }
1105 
1106 
1107 SCH_TEXT* SCH_SCREEN::GetLabel( const wxPoint& aPosition, int aAccuracy ) const
1108 {
1109  for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1110  {
1111  switch( item->Type() )
1112  {
1113  case SCH_LABEL_T:
1114  case SCH_GLOBAL_LABEL_T:
1115  case SCH_HIER_LABEL_T:
1116  if( item->HitTest( aPosition, aAccuracy ) )
1117  return static_cast<SCH_TEXT*>( item );
1118 
1119  break;
1120 
1121  default:
1122  ;
1123  }
1124  }
1125 
1126  return nullptr;
1127 }
1128 
1129 
1131 {
1132  wxCHECK( aLibSymbol, /* void */ );
1133 
1134  wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1135 
1136  auto it = m_libSymbols.find( libSymbolName );
1137 
1138  if( it != m_libSymbols.end() )
1139  {
1140  delete it->second;
1141  m_libSymbols.erase( it );
1142  }
1143 
1144  m_libSymbols[libSymbolName] = aLibSymbol;
1145 }
1146 
1147 
1148 void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1149 {
1150  m_aliases.insert( aAlias );
1151 }
1152 
1153 
1154 #if defined(DEBUG)
1155 void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1156 {
1157  // for now, make it look like XML, expand on this later.
1158  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1159 
1160  for( const SCH_ITEM* item : Items() )
1161  item->Show( nestLevel + 1, os );
1162 
1163  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1164 }
1165 #endif
1166 
1167 
1169 {
1170  m_index = 0;
1171  buildScreenList( aSheet );
1172 }
1173 
1174 
1176 {
1177 }
1178 
1179 
1181 {
1182  m_index = 0;
1183 
1184  if( m_screens.size() > 0 )
1185  return m_screens[0];
1186 
1187  return nullptr;
1188 }
1189 
1190 
1192 {
1193  if( m_index < m_screens.size() )
1194  m_index++;
1195 
1196  return GetScreen( m_index );
1197 }
1198 
1199 
1200 SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1201 {
1202  if( aIndex < m_screens.size() )
1203  return m_screens[ aIndex ];
1204 
1205  return nullptr;
1206 }
1207 
1208 
1209 SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1210 {
1211  if( aIndex < m_sheets.size() )
1212  return m_sheets[ aIndex ];
1213 
1214  return nullptr;
1215 }
1216 
1217 
1219 {
1220  if( aScreen == nullptr )
1221  return;
1222 
1223  for( const SCH_SCREEN* screen : m_screens )
1224  {
1225  if( screen == aScreen )
1226  return;
1227  }
1228 
1229  m_screens.push_back( aScreen );
1230  m_sheets.push_back( aSheet );
1231 }
1232 
1233 
1235 {
1236  if( aSheet && aSheet->Type() == SCH_SHEET_T )
1237  {
1238  SCH_SCREEN* screen = aSheet->GetScreen();
1239 
1240  wxCHECK_RET( screen, wxT( "No screen for aSheet" ) );
1241 
1242  addScreenToList( screen, aSheet );
1243 
1244  for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1245  buildScreenList( static_cast<SCH_SHEET*>( item ) );
1246  }
1247 }
1248 
1249 
1251 {
1252  SCH_SCREEN* first = GetFirst();
1253 
1254  if( !first )
1255  return;
1256 
1257  SCHEMATIC* sch = first->Schematic();
1258 
1259  wxCHECK_RET( sch, wxT( "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" ) );
1260 
1261  // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1262  SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1263  screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1264 
1265  // Search for new sheet paths, not existing in aInitialSheetPathList
1266  // and existing in sheetpathList
1267  for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1268  {
1269  bool path_exists = false;
1270 
1271  for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1272  {
1273  if( existing_sheetpath.Path() == sheetpath.Path() )
1274  {
1275  path_exists = true;
1276  break;
1277  }
1278  }
1279 
1280  if( !path_exists )
1281  {
1282  // A new sheet path is found: clear the annotation corresponding to this new path:
1283  SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1284 
1285  // Clear annotation and create the AR for this path, if not exists,
1286  // when the screen is shared by sheet paths.
1287  // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1288  // reference default value and takes the latest displayed value
1289  curr_screen->EnsureAlternateReferencesExist();
1290  curr_screen->ClearAnnotation( &sheetpath );
1291  }
1292  }
1293 }
1294 
1295 
1297 {
1298  std::vector<SCH_ITEM*> items;
1299  int count = 0;
1300 
1301  auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1302  {
1303  return a->m_Uuid < b->m_Uuid;
1304  };
1305 
1306  std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1307 
1308  for( SCH_SCREEN* screen : m_screens )
1309  screen->GetHierarchicalItems( &items );
1310 
1311  if( items.size() < 2 )
1312  return 0;
1313 
1314  for( EDA_ITEM* item : items )
1315  {
1316  if( !unique_stamps.insert( item ).second )
1317  {
1318  // Reset to fully random UUID. This may lose reference, but better to be
1319  // deterministic about it rather than to have duplicate UUIDs with random
1320  // side-effects.
1321  const_cast<KIID&>( item->m_Uuid ) = KIID();
1322  count++;
1323  }
1324  }
1325 
1326  return count;
1327 }
1328 
1329 
1331 {
1332  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1333  {
1334  for( SCH_ITEM* item : screen->Items() )
1335  item->ClearEditFlags();
1336  }
1337 }
1338 
1339 
1341 {
1342  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1343  {
1344  for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1345  {
1346  if( item == aMarker )
1347  {
1348  screen->DeleteItem( item );
1349  return;
1350  }
1351  }
1352  }
1353 }
1354 
1355 
1356 void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::TYPEMARKER aMarkerType, int aErrorCode,
1357  bool aIncludeExclusions )
1358 {
1359  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1360  {
1361  std::vector<SCH_ITEM*> markers;
1362 
1363  for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1364  {
1365  SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1366  std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1367 
1368  if( marker->GetMarkerType() == aMarkerType
1369  && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1370  && ( !marker->IsExcluded() || aIncludeExclusions ) )
1371  {
1372  markers.push_back( item );
1373  }
1374  }
1375 
1376  for( SCH_ITEM* marker : markers )
1377  screen->DeleteItem( marker );
1378  }
1379 }
1380 
1381 
1383  bool aIncludeExclusions )
1384 {
1385  DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1386 }
1387 
1388 
1390 {
1391  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1392  screen->UpdateSymbolLinks( aReporter );
1393 
1394  SCH_SCREEN* first = GetFirst();
1395 
1396  if( !first )
1397  return;
1398 
1399  SCHEMATIC* sch = first->Schematic();
1400 
1401  wxCHECK_RET( sch, wxT( "Null schematic in SCH_SCREENS::UpdateSymbolLinks" ) );
1402 
1403  SCH_SHEET_LIST sheets = sch->GetSheets();
1404 
1405  // All of the library symbols have been replaced with copies so the connection graph
1406  // pointers are stale.
1407  if( sch->ConnectionGraph() )
1408  sch->ConnectionGraph()->Recalculate( sheets, true );
1409 }
1410 
1411 
1413 {
1414  bool has_symbols = false;
1415 
1416  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1417  {
1418  for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1419  {
1420  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1421  has_symbols = true;
1422 
1423  if( !symbol->GetLibId().GetLibNickname().empty() )
1424  return false;
1425  }
1426  }
1427 
1428  // return true (i.e. has no fully defined symbol) only if at least one symbol is found
1429  return has_symbols ? true : false;
1430 }
1431 
1432 
1433 size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1434 {
1435  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1436  {
1437  for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1438  {
1439  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1440  const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1441 
1442  if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1443  aLibNicknames.Add( nickname );
1444  }
1445  }
1446 
1447  return aLibNicknames.GetCount();
1448 }
1449 
1450 
1451 int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1452 {
1453  SCH_SCREEN* screen;
1454  int cnt = 0;
1455 
1456  for( screen = GetFirst(); screen; screen = GetNext() )
1457  {
1458  for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1459  {
1460  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1461 
1462  if( symbol->GetLibId().GetLibNickname() != aFrom )
1463  continue;
1464 
1465  LIB_ID id = symbol->GetLibId();
1466  id.SetLibNickname( aTo );
1467  symbol->SetLibId( id );
1468  cnt++;
1469  }
1470  }
1471 
1472  return cnt;
1473 }
1474 
1475 
1476 bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1477 {
1478  for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1479  {
1480  if( screen->GetFileName() == aSchematicFileName )
1481  return true;
1482  }
1483 
1484  return false;
1485 }
1486 
1487 
1488 bool SCH_SCREENS::CanCauseCaseSensitivityIssue( const wxString& aSchematicFileName ) const
1489 {
1490  wxString lhsLower;
1491  wxString rhsLower;
1492  wxFileName lhs;
1493  wxFileName rhs = aSchematicFileName;
1494 
1495  wxCHECK( rhs.IsAbsolute(), false );
1496 
1497  for( const SCH_SCREEN* screen : m_screens )
1498  {
1499  lhs = screen->GetFileName();
1500 
1501  if( lhs.GetPath() != rhs.GetPath() )
1502  continue;
1503 
1504  lhsLower = lhs.GetFullName().Lower();
1505  rhsLower = rhs.GetFullName().Lower();
1506 
1507  if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
1508  return true;
1509  }
1510 
1511  return false;
1512 }
1513 
1514 
1516 {
1517  SCH_SCREEN* first = GetFirst();
1518 
1519  if( !first )
1520  return;
1521 
1522  SCHEMATIC* sch = first->Schematic();
1523 
1524  wxCHECK_RET( sch, wxT( "Null schematic in SCH_SCREENS::BuildClientSheetPathList" ) );
1525 
1526  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1527  curr_screen->GetClientSheetPaths().clear();
1528 
1529  for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1530  {
1531  SCH_SCREEN* used_screen = sheetpath.LastScreen();
1532 
1533  // SEarch for the used_screen in list and add this unique sheet path:
1534  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1535  {
1536  if( used_screen == curr_screen )
1537  {
1538  curr_screen->GetClientSheetPaths().push_back( sheetpath );
1539  break;
1540  }
1541  }
1542  }
1543 }
Field Reference of part, i.e. "IC21".
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:70
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:230
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition: sch_rtree.h:60
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
bool IsCache() const
void Plot(PLOTTER *aPlotter) const
Plot all the schematic objects to aPlotter.
Definition: sch_screen.cpp:838
bool IsExplicitJunction(const wxPoint &aPosition) const
Indicates that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:413
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
bool Remove(SCH_ITEM *aItem)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:273
SCH_SCREEN * GetNext()
SCH_SHEET_PIN * GetPin(const wxPoint &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:555
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void DeleteMarkers(enum MARKER_BASE::TYPEMARKER aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
wxPoint GetStartPoint() const
Definition: sch_line.h:90
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
Holds all the data relating to one schematic.
Definition: schematic.h:59
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:131
Object used to load, save, search, and otherwise manipulate symbol library files.
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:545
void clearLibSymbols()
Definition: sch_screen.cpp:101
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition: sch_screen.h:508
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath)
Clear exiting symbol annotation.
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:99
void ClearEditFlags()
void addScreenToList(SCH_SCREEN *aScreen, SCH_SHEET *aSheet)
void sort()
Definition: multivector.h:247
int m_refCount
Definition: sch_screen.h:523
int ChangeSymbolLibNickname(const wxString &aFrom, const wxString &aTo)
Change all of the symbol library nicknames.
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
void SetConnectivityDirty()
Definition: sch_screen.cpp:790
int GetLibraryCount()
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:130
void Clear()
Definition: title_block.h:113
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr)
Updates the connection graph for the given list of sheets.
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:261
wxPoint GetPinPhysicalPosition(const LIB_PIN *Pin) const
void EnsureAlternateReferencesExist()
For screens shared by many sheetpaths (complex hierarchies): to be able to clear or modify any refere...
Definition: sch_screen.cpp:996
virtual wxPoint GetPosition() const
Definition: eda_item.h:251
wxString m_fileName
Definition: sch_screen.h:521
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:70
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
int m_modification_sync
Definition: sch_screen.h:540
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:102
Define a library symbol object.
Definition: lib_symbol.h:96
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:280
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:380
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:115
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_line.cpp:833
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:165
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:228
void InitDataPoints(const wxSize &aPageSizeInternalUnits)
Definition: base_screen.cpp:46
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
Definition: sch_screen.cpp:66
unsigned int m_index
Definition: sch_screen.h:724
Definition: kiid.h:44
bool HasItems(KICAD_T aItemType) const
Definition: sch_screen.cpp:132
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
Definition: sch_screen.cpp:764
int GetAngleFrom(const wxPoint &aPoint) const
Definition: sch_line.cpp:472
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:723
TITLE_BLOCK m_titles
Definition: sch_screen.h:536
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition: sch_rtree.h:79
PAGE_INFO m_paper
Definition: sch_screen.h:535
Field Value of part, i.e. "3.3K".
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
SCH_LINE * GetBus(const wxPoint &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:429
bool m_Center
Center on screen.
Definition: base_screen.h:96
void DeleteItem(SCH_ITEM *aItem)
Removes aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:311
LIB_ID GetLibId() const override
Definition: lib_symbol.h:135
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:271
SCH_LINE_TEST_T
Definition: sch_screen.h:69
Handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:40
iterator end()
Returns a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:277
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:362
SCH_SHEET_PIN * GetSheetPin(const wxPoint &aPosition) const
Test the screen if aPosition is a sheet label object.
Definition: sch_screen.cpp:952
int m_pageCount
The number of BASE_SCREEN objects in this design.
Definition: base_screen.h:111
EE_RTREE m_rtree
Definition: sch_screen.h:538
void DeleteAllMarkers(enum MARKER_BASE::TYPEMARKER aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
bool IsJunction(const wxPoint &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:403
SCH_ITEM * GetItem(const wxPoint &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:342
void BuildClientSheetPathList()
built the list of sheet paths sharing a screen for each screen in use
bool doIsJunction(const wxPoint &aPosition, bool aBreakCrossings, bool *aHasExplicitJunctionDot, bool *aHasBusEntry) const
Definition: sch_screen.cpp:444
bool HasSchematic(const wxString &aSchematicFileName)
Check if one of the schematics in the list of screens is aSchematicFileName.
Definition for symbol library class.
EDA_ITEM * GetParent() const
Definition: eda_item.h:114
#define STRUCT_DELETED
flag indication structures to be erased
#define _(s)
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:90
bool IsExcluded() const
Definition: marker_base.h:95
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:161
bool IsEndPoint(const wxPoint &aPoint) const
Definition: sch_line.h:80
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:136
void DeleteMarker(SCH_MARKER *aMarker)
Delete a specific marker.
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_screen.cpp:140
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:484
iterator end()
Definition: sch_rtree.h:224
UTF8 Format() const
Definition: lib_id.cpp:116
void FreeDrawList()
Free all the items from the schematic associated with the screen.
Definition: sch_screen.cpp:247
wxString UnescapeString(const wxString &aSource)
A collection of SYMBOL_LIB objects.
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:353
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
const KIID m_Uuid
Definition: eda_item.h:474
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:126
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:97
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:259
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
bool IsExplicitJunctionNeeded(const wxPoint &aPosition) const
Indicates that a junction dot is necessary at the given location, and does not yet exist.
Definition: sch_screen.cpp:423
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
size_t CountConnectedItems(const wxPoint &aPos, bool aTestJunctions) const
Definition: sch_screen.cpp:970
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
void buildScreenList(SCH_SHEET *aSheet)
void DecRefCount()
Definition: sch_screen.cpp:124
Base plotter engine class.
Definition: plotter.h:121
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project SYMB...
Definition: sch_screen.cpp:610
SCH_SHEET & Root() const
Definition: schematic.h:92
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:156
iterator begin()
Definition: sch_rtree.h:219
Schematic symbol object.
Definition: sch_symbol.h:78
bool IsExplicitJunctionAllowed(const wxPoint &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:433
void Print(const RENDER_SETTINGS *aSettings)
Print all the items in the screen to aDC.
Definition: sch_screen.cpp:797
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
bool m_zoomInitialized
Definition: sch_screen.h:543
SCH_LINE * GetLine(const wxPoint &aPosition, int aAccuracy=0, int aLayer=LAYER_NOTES, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Return a line item located at aPosition.
std::vector< SCH_SCREEN * > m_screens
Definition: sch_screen.h:722
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:146
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:93
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:268
SCH_LINE * GetWire(const wxPoint &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:423
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:92
SCH_SCREENS(SCH_SHEET *aSheet)
std::unordered_set< std::shared_ptr< BUS_ALIAS > > m_aliases
List of bus aliases stored in this screen.
Definition: sch_screen.h:552
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:110
wxString wx_str() const
Definition: utf8.cpp:46
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition: sch_rtree.h:192
Handle the component boundary box.
Definition: eda_rect.h:42
SCH_SHEET * GetSheet(unsigned int aIndex) const
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
SCH_TEXT * GetLabel(const wxPoint &aPosition, int aAccuracy=0) const
Return a label item located at aPosition.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
int GetDefaultPenWidth() const
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Clear the annotation for the symbols in aSheetPath on the screen.
Definition: sch_screen.cpp:984
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
boost::ptr_vector< WIRE > WIRES
Definition: specctra.h:2983
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition: sch_screen.h:179
bool CanCauseCaseSensitivityIssue(const wxString &aSchematicFileName) const
Check aSchematicFileName for a potential file name case sensitivity issue.
SCH_SCREEN * GetFirst()
SCH_SCREEN * GetScreen(unsigned int aIndex) const
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_line.cpp:190
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:893
void Update(SCH_ITEM *aItem)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:266
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:110
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the symbols inside new sheetpaths when a complex hierarchy is modified and n...
int GetUnit() const
Definition: sch_symbol.h:196
LIB_ITEM * GetDrawItem(const wxPoint &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the symbol library item at aPosition that is part of this symbol.
std::map< wxString, LIB_SYMBOL * > m_libSymbols
Library symbols required for this schematic.
Definition: sch_screen.h:555
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
LIB_PIN * GetPin(const wxPoint &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
Definition: sch_screen.cpp:900
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nicknames into aLibNicknames.
int GetConvert() const
Definition: sch_symbol.h:224
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:182
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
void clear()
Remove all items from the RTree.
Definition: sch_rtree.h:112
void GetHierarchicalItems(std::vector< SCH_ITEM * > *aItems) const
Add all schematic sheet and symbol objects in the screen to aItems.
bool IsConnected(const wxPoint &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:129
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition: lib_id.h:114
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:101
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:593
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
void IncRefCount()
Definition: sch_screen.cpp:118
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:148
bool empty() const
Definition: utf8.h:103
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:336
virtual wxString GetClass() const override
Return the class name.
Definition: sch_screen.h:124
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
Definition: base_screen.h:119
std::set< SCH_ITEM * > MarkConnections(SCH_LINE *aSegment)
Return all wires and junctions connected to aSegment which are not connected any symbol pin.
Definition: sch_screen.cpp:358
wxPoint GetEndPoint() const
Definition: sch_line.h:93