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