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 <dick@softplc.com>
6  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
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  "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( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
184  cnt );
185 
186  while( m_libSymbols.find( newName ) != m_libSymbols.end() )
187  {
188  cnt += 1;
189  newName.Printf( "%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, "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( auto 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( auto 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::IsJunctionNeeded( const wxPoint& aPosition, bool aNew ) const
404 {
405  enum layers { WIRES = 0, BUSES };
406 
407  bool breakLines[ 2 ] = { false };
408  std::unordered_set<int> exitAngles[ 2 ];
409  std::vector<const SCH_LINE*> midPointLines[ 2 ];
410 
411  // A pin at 90º still shouldn't match a line at 90º so just give pins unique numbers
412  int uniqueAngle = 10000;
413 
414  for( const SCH_ITEM* item : Items().Overlapping( aPosition ) )
415  {
416  if( item->GetEditFlags() & STRUCT_DELETED )
417  continue;
418 
419  switch( item->Type() )
420  {
421  case SCH_JUNCTION_T:
422  if( aNew && item->HitTest( aPosition, -1 ) )
423  return false;
424 
425  break;
426 
427  case SCH_LINE_T:
428  {
429  const SCH_LINE* line = static_cast<const SCH_LINE*>( item );
430  int layer;
431 
432  if( line->GetStartPoint() == line->GetEndPoint() )
433  break;
434  else if( line->GetLayer() == LAYER_WIRE )
435  layer = WIRES;
436  else if( line->GetLayer() == LAYER_BUS )
437  layer = BUSES;
438  else
439  break;
440 
441  if( line->IsConnected( aPosition ) )
442  {
443  breakLines[ layer ] = true;
444  exitAngles[ layer ].insert( line->GetAngleFrom( aPosition ) );
445  }
446  else if( line->HitTest( aPosition, -1 ) )
447  {
448  // Defer any line midpoints until we know whether or not we're breaking them
449  midPointLines[ layer ].push_back( line );
450  }
451  }
452  break;
453 
455  case SCH_SYMBOL_T:
456  case SCH_SHEET_T:
457  if( item->IsConnected( aPosition ) )
458  {
459  breakLines[ WIRES ] = true;
460  exitAngles[ WIRES ].insert( uniqueAngle++ );
461  }
462 
463  break;
464 
465  default:
466  break;
467  }
468  }
469 
470  for( int layer : { WIRES, BUSES } )
471  {
472  if( breakLines[ layer ] )
473  {
474  for( const SCH_LINE* line : midPointLines[ layer ] )
475  {
476  exitAngles[ layer ].insert( line->GetAngleFrom( aPosition ) );
477  exitAngles[ layer ].insert( line->GetReverseAngleFrom( aPosition ) );
478  }
479  }
480  }
481 
482  return exitAngles[ WIRES ].size() >= 3 || exitAngles[ BUSES ].size() >= 3;
483 }
484 
485 
486 bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer ) const
487 {
488  wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
489  wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
490 
491  switch( aLayer )
492  {
493  case LAYER_BUS:
494  {
495  if( GetBus( aPosition ) )
496  return true;
497 
498  SCH_SHEET_PIN* sheetPin = GetSheetPin( aPosition );
499 
500  if( sheetPin && sheetPin->IsConnected( aPosition ) )
501  return true;
502 
503  SCH_TEXT* label = GetLabel( aPosition );
504 
505  if( label && label->IsConnected( aPosition ) )
506  return true;
507  }
508  break;
509 
510  case LAYER_NOTES:
511  {
512  if( GetLine( aPosition ) )
513  return true;
514  }
515  break;
516 
517  case LAYER_WIRE:
518  {
519  if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T) )
520  return true;
521 
522  if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
523  return true;
524 
525  if( GetPin( aPosition, nullptr, true ) )
526  return true;
527 
528  if( GetWire( aPosition ) )
529  return true;
530 
531  SCH_TEXT* label = GetLabel( aPosition, 1 );
532 
533  if( label && label->IsConnected( aPosition ) )
534  return true;
535 
536  SCH_SHEET_PIN* sheetPin = GetSheetPin( aPosition );
537 
538  if( sheetPin && sheetPin->IsConnected( aPosition ) )
539  return true;
540  }
541  break;
542 
543  default:
544  break;
545  }
546 
547  return false;
548 }
549 
550 
552 {
553  wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
554 
555  wxString msg;
556  std::unique_ptr< LIB_SYMBOL > libSymbol;
557  std::vector<SCH_SYMBOL*> symbols;
558  SYMBOL_LIB_TABLE* libs = Schematic()->Prj().SchSymbolLibTable();
559 
560  // This will be a nullptr if an s-expression schematic is loaded.
561  SYMBOL_LIBS* legacyLibs = Schematic()->Prj().SchLibs();
562 
563  for( auto item : Items().OfType( SCH_SYMBOL_T ) )
564  symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
565 
566  // Remove them from the R tree. There bounding box size may change.
567  for( auto symbol : symbols )
568  Remove( symbol );
569 
570  // Clear all existing symbol links.
571  clearLibSymbols();
572 
573  for( SCH_SYMBOL* symbol : symbols )
574  {
575  LIB_SYMBOL* tmp = nullptr;
576  libSymbol.reset();
577 
578  // If the symbol is already in the internal library, map the symbol to it.
579  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
580 
581  if( ( it != m_libSymbols.end() ) )
582  {
583  if( aReporter )
584  {
585  msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
586  symbol->GetField( REFERENCE_FIELD )->GetText(),
587  symbol->GetField( VALUE_FIELD )->GetText(),
588  UnescapeString( symbol->GetLibId().Format() ) );
589  aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
590  }
591 
592  // Internal library symbols are already flattened so just make a copy.
593  symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
594  continue;
595  }
596 
597  if( !symbol->GetLibId().IsValid() )
598  {
599  if( aReporter )
600  {
601  msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
602  "Unable to link library symbol." ),
603  UnescapeString( symbol->GetLibId().Format() ) );
604  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
605  }
606 
607  continue;
608  }
609 
610  // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
611  // is not found in the table so check if the library still exists in the table
612  // before attempting to load the symbol.
613  if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
614  {
615  if( aReporter )
616  {
617  msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
618  "available. Unable to link library symbol." ),
619  symbol->GetLibId().GetLibNickname().wx_str() );
620  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
621  }
622 
623  continue;
624  }
625 
626  if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
627  {
628  try
629  {
630  tmp = libs->LoadSymbol( symbol->GetLibId() );
631  }
632  catch( const IO_ERROR& ioe )
633  {
634  if( aReporter )
635  {
636  msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
637  UnescapeString( symbol->GetLibId().Format() ) );
638  aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
639  }
640  }
641  }
642 
643  if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
644  {
645  SYMBOL_LIB& legacyCacheLib = legacyLibs->at( 0 );
646 
647  // It better be the cache library.
648  wxCHECK2( legacyCacheLib.IsCache(), continue );
649 
650  wxString id = symbol->GetLibId().Format();
651 
652  id.Replace( ':', '_' );
653 
654  if( aReporter )
655  {
656  msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
657  symbol->GetField( REFERENCE_FIELD )->GetText(),
658  symbol->GetField( VALUE_FIELD )->GetText(),
659  UnescapeString( id ) );
660  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
661  }
662 
663  tmp = legacyCacheLib.FindSymbol( id );
664  }
665 
666  if( tmp )
667  {
668  // We want a full symbol not just the top level child symbol.
669  libSymbol = tmp->Flatten();
670  libSymbol->SetParent();
671 
672  m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
673  new LIB_SYMBOL( *libSymbol.get() ) } );
674 
675  if( aReporter )
676  {
677  msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
678  symbol->GetField( REFERENCE_FIELD )->GetText(),
679  symbol->GetField( VALUE_FIELD )->GetText(),
680  UnescapeString( symbol->GetLibId().Format() ) );
681  aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
682  }
683  }
684  else
685  {
686  if( aReporter )
687  {
688  msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
689  symbol->GetField( REFERENCE_FIELD )->GetText(),
690  symbol->GetField( VALUE_FIELD )->GetText() );
691  aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
692  }
693  }
694 
695  symbol->SetLibSymbol( libSymbol.release() );
696  }
697 
698  // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
699  // item with the new bbox
700  for( auto symbol : symbols )
701  Append( symbol );
702 }
703 
704 
706 {
707  std::vector<SCH_SYMBOL*> symbols;
708 
709  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
710  symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
711 
712  for( SCH_SYMBOL* symbol : symbols )
713  {
714  // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
715  m_rtree.remove( symbol );
716 
717  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
718 
719  LIB_SYMBOL* libSymbol = nullptr;
720 
721  if( it != m_libSymbols.end() )
722  libSymbol = new LIB_SYMBOL( *it->second );
723 
724  symbol->SetLibSymbol( libSymbol );
725 
726  m_rtree.insert( symbol );
727  }
728 }
729 
730 
731 void SCH_SCREEN::Print( const RENDER_SETTINGS* aSettings )
732 {
733  // Ensure links are up to date, even if a library was reloaded for some reason:
734  std::vector<SCH_ITEM*> junctions;
735  std::vector<SCH_ITEM*> bitmaps;
736  std::vector<SCH_ITEM*> other;
737 
738  for( SCH_ITEM* item : Items() )
739  {
740  if( item->IsMoving() || item->IsResized() )
741  continue;
742 
743  if( item->Type() == SCH_JUNCTION_T )
744  junctions.push_back( item );
745  else if( item->Type() == SCH_BITMAP_T )
746  bitmaps.push_back( item );
747  else
748  other.push_back( item );
749  }
750 
752  std::sort( other.begin(), other.end(),
753  []( const SCH_ITEM* a, const SCH_ITEM* b )
754  {
755  if( a->Type() == b->Type() )
756  return a->GetLayer() > b->GetLayer();
757 
758  return a->Type() > b->Type();
759  } );
760 
761  for( SCH_ITEM* item : bitmaps )
762  item->Print( aSettings, wxPoint( 0, 0 ) );
763 
764  for( SCH_ITEM* item : other )
765  item->Print( aSettings, wxPoint( 0, 0 ) );
766 
767  for( SCH_ITEM* item : junctions )
768  item->Print( aSettings, wxPoint( 0, 0 ) );
769 }
770 
771 
772 void SCH_SCREEN::Plot( PLOTTER* aPlotter ) const
773 {
774  // Ensure links are up to date, even if a library was reloaded for some reason:
775  std::vector< SCH_ITEM* > junctions;
776  std::vector< SCH_ITEM* > bitmaps;
777  std::vector< SCH_ITEM* > other;
778 
779  for( auto item : Items() )
780  {
781  if( item->IsMoving() || item->IsResized() )
782  continue;
783 
784  if( item->Type() == SCH_JUNCTION_T )
785  junctions.push_back( item );
786  else if( item->Type() == SCH_BITMAP_T )
787  bitmaps.push_back( item );
788  else
789  other.push_back( item );
790  }
791 
793  std::sort( other.begin(), other.end(),
794  []( const SCH_ITEM* a, const SCH_ITEM* b )
795  {
796  if( a->Type() == b->Type() )
797  return a->GetLayer() > b->GetLayer();
798 
799  return a->Type() > b->Type();
800  } );
801 
802  int defaultPenWidth = aPlotter->RenderSettings()->GetDefaultPenWidth();
803 
804  // Bitmaps are drawn first to ensure they are in the background
805  // This is particularly important for the wxPostscriptDC (used in *nix printers) as
806  // the bitmap PS command clears the screen
807  for( const SCH_ITEM* item : bitmaps )
808  {
809  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
810  item->Plot( aPlotter );
811  }
812 
813  for( const SCH_ITEM* item : other )
814  {
815  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
816  item->Plot( aPlotter );
817  }
818 
819  for( const SCH_ITEM* item : junctions )
820  {
821  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
822  item->Plot( aPlotter );
823  }
824 }
825 
826 
828 {
829  for( SCH_ITEM* item : Items() )
830  item->ClearTempFlags();
831 }
832 
833 
834 LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_SYMBOL** aSymbol,
835  bool aEndPointOnly ) const
836 {
837  SCH_SYMBOL* candidate = nullptr;
838  LIB_PIN* pin = nullptr;
839 
840  for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
841  {
842  candidate = static_cast<SCH_SYMBOL*>( item );
843 
844  if( aEndPointOnly )
845  {
846  pin = nullptr;
847 
848  if( !candidate->GetLibSymbolRef() )
849  continue;
850 
851  for( pin = candidate->GetLibSymbolRef()->GetNextPin(); pin;
852  pin = candidate->GetLibSymbolRef()->GetNextPin( pin ) )
853  {
854  // Skip items not used for this part.
855  if( candidate->GetUnit() && pin->GetUnit() &&
856  ( pin->GetUnit() != candidate->GetUnit() ) )
857  continue;
858 
859  if( candidate->GetConvert() && pin->GetConvert() &&
860  ( pin->GetConvert() != candidate->GetConvert() ) )
861  continue;
862 
863  if( candidate->GetPinPhysicalPosition( pin ) == aPosition )
864  break;
865  }
866 
867  if( pin )
868  break;
869  }
870  else
871  {
872  pin = (LIB_PIN*) candidate->GetDrawItem( aPosition, LIB_PIN_T );
873 
874  if( pin )
875  break;
876  }
877  }
878 
879  if( pin && aSymbol )
880  *aSymbol = candidate;
881 
882  return pin;
883 }
884 
885 
886 SCH_SHEET_PIN* SCH_SCREEN::GetSheetPin( const wxPoint& aPosition ) const
887 {
888  SCH_SHEET_PIN* sheetPin = nullptr;
889 
890  for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
891  {
892  auto sheet = static_cast<SCH_SHEET*>( item );
893 
894  sheetPin = sheet->GetPin( aPosition );
895 
896  if( sheetPin )
897  break;
898  }
899 
900  return sheetPin;
901 }
902 
903 
904 size_t SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const
905 {
906  size_t count = 0;
907 
908  for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
909  {
910  if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
911  count++;
912  }
913 
914  return count;
915 }
916 
917 
919 {
920 
921  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
922  {
923  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
924 
925  symbol->ClearAnnotation( aSheetPath );
926  }
927 }
928 
929 
931 {
932  if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
933  return;
934 
935  for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
936  {
937  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
938 
939  // Add (when not existing) all sheet path entries
940  for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
941  symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
942  }
943 }
944 
945 
946 void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
947 {
948  static KICAD_T hierarchicalTypes[] = { SCH_SYMBOL_T, SCH_SHEET_T, SCH_GLOBAL_LABEL_T, EOT };
949 
950  for( SCH_ITEM* item : Items() )
951  {
952  if( item->IsType( hierarchicalTypes ) )
953  aItems->push_back( item );
954  }
955 }
956 
957 
958 void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
959 {
960  for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
961  aItems->push_back( item );
962 
963  std::sort( aItems->begin(), aItems->end(),
964  []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
965  {
966  if( a->GetPosition().x == b->GetPosition().x )
967  {
968  // Ensure deterministic sort
969  if( a->GetPosition().y == b->GetPosition().y )
970  return a->m_Uuid < b->m_Uuid;
971 
972  return a->GetPosition().y < b->GetPosition().y;
973  }
974  else
975  return a->GetPosition().x < b->GetPosition().x;
976  } );
977 }
978 
979 
981  std::function<void( SCH_ITEM* )>* aChangedHandler ) const
982 {
983  std::vector<DANGLING_END_ITEM> endPoints;
984 
985  for( SCH_ITEM* item : Items() )
986  {
987  if( item->IsConnectable() )
988  {
989  endPoints.clear();
990 
991  for( SCH_ITEM* overlapping : Items().Overlapping( item->GetBoundingBox() ) )
992  overlapping->GetEndPoints( endPoints );
993 
994  if( item->UpdateDanglingState( endPoints, aPath ) )
995  {
996  if( aChangedHandler )
997  (*aChangedHandler)( item );
998  }
999  }
1000  }
1001 }
1002 
1003 
1004 SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLayer,
1005  SCH_LINE_TEST_T aSearchType ) const
1006 {
1007  // an accuracy of 0 had problems with rounding errors; use at least 1
1008  aAccuracy = std::max( aAccuracy, 1 );
1009 
1010  for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1011  {
1012  if( item->Type() != SCH_LINE_T )
1013  continue;
1014 
1015  if( item->GetLayer() != aLayer )
1016  continue;
1017 
1018  if( !item->HitTest( aPosition, aAccuracy ) )
1019  continue;
1020 
1021  switch( aSearchType )
1022  {
1023  case ENTIRE_LENGTH_T:
1024  return (SCH_LINE*) item;
1025 
1026  case EXCLUDE_END_POINTS_T:
1027  if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1028  return (SCH_LINE*) item;
1029  break;
1030 
1031  case END_POINTS_ONLY_T:
1032  if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1033  return (SCH_LINE*) item;
1034  }
1035  }
1036 
1037  return nullptr;
1038 }
1039 
1040 
1041 SCH_TEXT* SCH_SCREEN::GetLabel( const wxPoint& aPosition, int aAccuracy ) const
1042 {
1043  for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1044  {
1045  switch( item->Type() )
1046  {
1047  case SCH_LABEL_T:
1048  case SCH_GLOBAL_LABEL_T:
1049  case SCH_HIER_LABEL_T:
1050  if( item->HitTest( aPosition, aAccuracy ) )
1051  return static_cast<SCH_TEXT*>( item );
1052 
1053  break;
1054 
1055  default:
1056  ;
1057  }
1058  }
1059 
1060  return nullptr;
1061 }
1062 
1063 
1065 {
1066  wxCHECK( aLibSymbol, /* void */ );
1067 
1068  wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1069 
1070  auto it = m_libSymbols.find( libSymbolName );
1071 
1072  if( it != m_libSymbols.end() )
1073  {
1074  delete it->second;
1075  m_libSymbols.erase( it );
1076  }
1077 
1078  m_libSymbols[libSymbolName] = aLibSymbol;
1079 }
1080 
1081 
1082 void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1083 {
1084  m_aliases.insert( aAlias );
1085 }
1086 
1087 
1088 #if defined(DEBUG)
1089 void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1090 {
1091  // for now, make it look like XML, expand on this later.
1092  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1093 
1094  for( const SCH_ITEM* item : Items() )
1095  item->Show( nestLevel + 1, os );
1096 
1097  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1098 }
1099 #endif
1100 
1101 
1103 {
1104  m_index = 0;
1105  buildScreenList( aSheet );
1106 }
1107 
1108 
1110 {
1111 }
1112 
1113 
1115 {
1116  m_index = 0;
1117 
1118  if( m_screens.size() > 0 )
1119  return m_screens[0];
1120 
1121  return nullptr;
1122 }
1123 
1124 
1126 {
1127  if( m_index < m_screens.size() )
1128  m_index++;
1129 
1130  return GetScreen( m_index );
1131 }
1132 
1133 
1134 SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1135 {
1136  if( aIndex < m_screens.size() )
1137  return m_screens[ aIndex ];
1138 
1139  return nullptr;
1140 }
1141 
1142 
1143 SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1144 {
1145  if( aIndex < m_sheets.size() )
1146  return m_sheets[ aIndex ];
1147 
1148  return nullptr;
1149 }
1150 
1151 
1153 {
1154  if( aScreen == nullptr )
1155  return;
1156 
1157  for( const SCH_SCREEN* screen : m_screens )
1158  {
1159  if( screen == aScreen )
1160  return;
1161  }
1162 
1163  m_screens.push_back( aScreen );
1164  m_sheets.push_back( aSheet );
1165 }
1166 
1167 
1169 {
1170  if( aSheet && aSheet->Type() == SCH_SHEET_T )
1171  {
1172  SCH_SCREEN* screen = aSheet->GetScreen();
1173 
1174  wxCHECK_RET( screen, "No screen for aSheet" );
1175 
1176  addScreenToList( screen, aSheet );
1177 
1178  for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1179  buildScreenList( static_cast<SCH_SHEET*>( item ) );
1180  }
1181 }
1182 
1183 
1185 {
1186  SCH_SCREEN* first = GetFirst();
1187 
1188  if( !first )
1189  return;
1190 
1191  SCHEMATIC* sch = first->Schematic();
1192 
1193  wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1194 
1195  // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1196  SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1197  screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1198 
1199  // Search for new sheet paths, not existing in aInitialSheetPathList
1200  // and existing in sheetpathList
1201  for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1202  {
1203  bool path_exists = false;
1204 
1205  for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1206  {
1207  if( existing_sheetpath.Path() == sheetpath.Path() )
1208  {
1209  path_exists = true;
1210  break;
1211  }
1212  }
1213 
1214  if( !path_exists )
1215  {
1216  // A new sheet path is found: clear the annotation corresponding to this new path:
1217  SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1218 
1219  // Clear annotation and create the AR for this path, if not exists,
1220  // when the screen is shared by sheet paths.
1221  // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1222  // reference default value and takes the latest displayed value
1223  curr_screen->EnsureAlternateReferencesExist();
1224  curr_screen->ClearAnnotation( &sheetpath );
1225  }
1226  }
1227 }
1228 
1229 
1231 {
1232  std::vector<SCH_ITEM*> items;
1233  int count = 0;
1234 
1235  auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1236  {
1237  return a->m_Uuid < b->m_Uuid;
1238  };
1239 
1240  std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1241 
1242  for( SCH_SCREEN* screen : m_screens )
1243  screen->GetHierarchicalItems( &items );
1244 
1245  if( items.size() < 2 )
1246  return 0;
1247 
1248  for( EDA_ITEM* item : items )
1249  {
1250  if( !unique_stamps.insert( item ).second )
1251  {
1252  // Reset to fully random UUID. This may lose reference, but better to be
1253  // deterministic about it rather than to have duplicate UUIDs with random
1254  // side-effects.
1255  const_cast<KIID&>( item->m_Uuid ) = KIID();
1256  count++;
1257  }
1258  }
1259 
1260  return count;
1261 }
1262 
1263 
1265 {
1266  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1267  {
1268  for( SCH_ITEM* item : screen->Items() )
1269  item->ClearEditFlags();
1270  }
1271 }
1272 
1273 
1275 {
1276  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1277  {
1278  for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1279  {
1280  if( item == aMarker )
1281  {
1282  screen->DeleteItem( item );
1283  return;
1284  }
1285  }
1286  }
1287 }
1288 
1289 
1290 void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::TYPEMARKER aMarkerType, int aErrorCode,
1291  bool aIncludeExclusions )
1292 {
1293  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1294  {
1295  std::vector<SCH_ITEM*> markers;
1296 
1297  for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1298  {
1299  SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1300  std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1301 
1302  if( marker->GetMarkerType() == aMarkerType
1303  && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1304  && ( !marker->IsExcluded() || aIncludeExclusions ) )
1305  {
1306  markers.push_back( item );
1307  }
1308  }
1309 
1310  for( SCH_ITEM* marker : markers )
1311  screen->DeleteItem( marker );
1312  }
1313 }
1314 
1315 
1317  bool aIncludeExclusions )
1318 {
1319  DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1320 }
1321 
1322 
1324 {
1325  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1326  screen->UpdateSymbolLinks( aReporter );
1327 
1328  SCH_SCREEN* first = GetFirst();
1329 
1330  if( !first )
1331  return;
1332 
1333  SCHEMATIC* sch = first->Schematic();
1334 
1335  wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1336 
1337  SCH_SHEET_LIST sheets = sch->GetSheets();
1338 
1339  // All of the library symbols have been replaced with copies so the connection graph
1340  // pointers are stale.
1341  if( sch->ConnectionGraph() )
1342  sch->ConnectionGraph()->Recalculate( sheets, true );
1343 }
1344 
1345 
1347 {
1348  bool has_symbols = false;
1349 
1350  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1351  {
1352  for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1353  {
1354  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1355  has_symbols = true;
1356 
1357  if( !symbol->GetLibId().GetLibNickname().empty() )
1358  return false;
1359  }
1360  }
1361 
1362  // return true (i.e. has no fully defined symbol) only if at least one symbol is found
1363  return has_symbols ? true : false;
1364 }
1365 
1366 
1367 size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1368 {
1369  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1370  {
1371  for( auto item : screen->Items().OfType( SCH_SYMBOL_T ) )
1372  {
1373  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1374  const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1375 
1376  if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1377  aLibNicknames.Add( nickname );
1378  }
1379  }
1380 
1381  return aLibNicknames.GetCount();
1382 }
1383 
1384 
1385 int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1386 {
1387  SCH_SCREEN* screen;
1388  int cnt = 0;
1389 
1390  for( screen = GetFirst(); screen; screen = GetNext() )
1391  {
1392  for( auto item : screen->Items().OfType( SCH_SYMBOL_T ) )
1393  {
1394  auto symbol = static_cast<SCH_SYMBOL*>( item );
1395 
1396  if( symbol->GetLibId().GetLibNickname() != aFrom )
1397  continue;
1398 
1399  LIB_ID id = symbol->GetLibId();
1400  id.SetLibNickname( aTo );
1401  symbol->SetLibId( id );
1402  cnt++;
1403  }
1404  }
1405 
1406  return cnt;
1407 }
1408 
1409 
1410 bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1411 {
1412  for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1413  {
1414  if( screen->GetFileName() == aSchematicFileName )
1415  return true;
1416  }
1417 
1418  return false;
1419 }
1420 
1421 
1422 bool SCH_SCREENS::CanCauseCaseSensitivityIssue( const wxString& aSchematicFileName ) const
1423 {
1424  wxString lhsLower;
1425  wxString rhsLower;
1426  wxFileName lhs;
1427  wxFileName rhs = aSchematicFileName;
1428 
1429  wxCHECK( rhs.IsAbsolute(), false );
1430 
1431  for( const SCH_SCREEN* screen : m_screens )
1432  {
1433  lhs = screen->GetFileName();
1434 
1435  if( lhs.GetPath() != rhs.GetPath() )
1436  continue;
1437 
1438  lhsLower = lhs.GetFullName().Lower();
1439  rhsLower = rhs.GetFullName().Lower();
1440 
1441  if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
1442  return true;
1443  }
1444 
1445  return false;
1446 }
1447 
1448 
1450 {
1451  SCH_SCREEN* first = GetFirst();
1452 
1453  if( !first )
1454  return;
1455 
1456  SCHEMATIC* sch = first->Schematic();
1457 
1458  wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
1459 
1460  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1461  curr_screen->GetClientSheetPaths().clear();
1462 
1463  for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1464  {
1465  SCH_SCREEN* used_screen = sheetpath.LastScreen();
1466 
1467  // SEarch for the used_screen in list and add this unique sheet path:
1468  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1469  {
1470  if( used_screen == curr_screen )
1471  {
1472  curr_screen->GetClientSheetPaths().push_back( sheetpath );
1473  break;
1474  }
1475  }
1476  }
1477 }
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:216
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:772
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()
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,...
Definition: sch_screen.cpp:958
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:486
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:487
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:498
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.
Definition: sch_screen.cpp:980
int GetLibraryCount()
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:121
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.
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:930
virtual wxPoint GetPosition() const
Definition: eda_item.h:252
wxString m_fileName
Definition: sch_screen.h:496
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:515
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
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:257
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:331
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:116
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Test if aPosition is contained within or on the bounding box of an item.
Definition: sch_line.cpp:772
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:164
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:699
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:705
int GetAngleFrom(const wxPoint &aPoint) const
Definition: sch_line.cpp:427
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:698
TITLE_BLOCK m_titles
Definition: sch_screen.h:511
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition: sch_rtree.h:75
PAGE_INFO m_paper
Definition: sch_screen.h:510
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:408
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:248
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:263
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:313
SCH_SHEET_PIN * GetSheetPin(const wxPoint &aPosition) const
Test the screen if aPosition is a sheet label object.
Definition: sch_screen.cpp:886
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:513
void DeleteAllMarkers(enum MARKER_BASE::TYPEMARKER aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
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 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:115
#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:94
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:160
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:473
iterator end()
Definition: sch_rtree.h:210
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:310
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:475
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:118
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:257
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
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:904
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:551
SCH_SHEET & Root() const
Definition: schematic.h:92
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:156
iterator begin()
Definition: sch_rtree.h:205
Schematic symbol object.
Definition: sch_symbol.h:78
void Print(const RENDER_SETTINGS *aSettings)
Print all the items in the screen to aDC.
Definition: sch_screen.cpp:731
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:518
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:697
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:146
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:92
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:254
SCH_LINE * GetWire(const wxPoint &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:402
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:527
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:178
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:100
bool IsJunctionNeeded(const wxPoint &aPosition, bool aNew=false) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:403
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:918
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:177
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:170
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:827
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:195
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:530
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:834
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nicknames into aLibNicknames.
int GetConvert() const
Definition: sch_symbol.h:223
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:104
void GetHierarchicalItems(std::vector< SCH_ITEM * > *aItems) const
Add all schematic sheet and symbol objects in the screen to aItems.
Definition: sch_screen.cpp:946
bool IsConnected(const wxPoint &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:122
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:100
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:568
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:113
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:147
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