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 <eda_rect.h>
33 //#include <gr_text.h>
34 #include <id.h>
35 #include <kicad_string.h>
36 #include <kiway.h>
37 #include <pgm_base.h>
38 #include <plotter.h>
39 #include <project.h>
40 #include <reporter.h>
41 #include <sch_draw_panel.h>
42 #include <sch_edit_frame.h>
43 #include <sch_item.h>
44 
45 #include <class_library.h>
46 #include <class_libentry.h>
47 #include <connection_graph.h>
48 #include <lib_pin.h>
49 #include <sch_component.h>
50 #include <sch_junction.h>
51 #include <sch_line.h>
52 #include <sch_marker.h>
53 #include <sch_sheet.h>
54 #include <sch_text.h>
55 #include <schematic.h>
56 #include <symbol_lib_table.h>
57 #include <tool/common_tools.h>
58 
59 #include <thread>
60 #include <algorithm>
61 #include <future>
62 
63 // TODO(JE) Debugging only
64 #include <profile.h>
65 #include "sch_bus_entry.h"
66 
68  BASE_SCREEN( aParent, SCH_SCREEN_T ),
69  m_paper( wxT( "A4" ) )
70 {
72 
73  m_refCount = 0;
74 
75  // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
76  m_Center = false;
77 
78  InitDataPoints( m_paper.GetSizeIU() );
79 }
80 
81 
83 {
85  FreeDrawList();
86 }
87 
88 
90 {
91  wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
92  "SCH_SCREEN must have a SCHEMATIC parent!" );
93 
94  return static_cast<SCHEMATIC*>( GetParent() );
95 }
96 
97 
99 {
100  for( auto libSymbol : m_libSymbols )
101  delete libSymbol.second;
102 
103  m_libSymbols.clear();
104 }
105 
106 
108 {
109  m_refCount++;
110 }
111 
112 
114 {
115  wxCHECK_RET( m_refCount != 0,
116  wxT( "Screen reference count already zero. Bad programmer!" ) );
117  m_refCount--;
118 }
119 
120 
121 bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
122 {
123  EE_RTREE::EE_TYPE sheets = const_cast<EE_RTREE&>( m_rtree ).OfType( aItemType );
124 
125  return sheets.begin() != sheets.end();
126 }
127 
128 
130 {
131  if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
132  {
133  // Ensure the item can reach the SCHEMATIC through this screen
134  aItem->SetParent( this );
135 
136  if( aItem->Type() == SCH_COMPONENT_T )
137  {
138  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( aItem );
139 
140  if( symbol->GetPartRef() )
141  {
142  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
143 
144  if( it == m_libSymbols.end() )
145  {
147  new LIB_PART( *symbol->GetPartRef() );
148  }
149  else
150  {
151  // The original library symbol may have changed since the last time
152  // it was added to the schematic. If it has changed, then a new name
153  // must be created for the library symbol list to prevent all of the
154  // other schematic symbols referencing that library symbol from changing.
155  LIB_PART* foundSymbol = it->second;
156 
157  if( *foundSymbol != *symbol->GetPartRef() )
158  {
159  int cnt = 1;
160  wxString newName;
161 
162  newName.Printf( "%s_%d", symbol->GetLibId().Format().wx_str(), cnt );
163 
164  while( m_libSymbols.find( newName ) != m_libSymbols.end() )
165  {
166  cnt += 1;
167  newName.Printf( "%s_%d", symbol->GetLibId().Format().wx_str(), cnt );
168  }
169 
170  symbol->SetSchSymbolLibraryName( newName );
171  m_libSymbols[newName] = new LIB_PART( *symbol->GetPartRef() );
172  }
173  }
174  }
175  }
176 
177  m_rtree.insert( aItem );
179  }
180 }
181 
182 
184 {
185  wxCHECK_RET( aScreen, "Invalid screen object." );
186 
187  // No need to descend the hierarchy. Once the top level screen is copied, all of it's
188  // children are copied as well.
189  for( auto aItem : aScreen->m_rtree )
190  Append( aItem );
191 
192  aScreen->Clear( false );
193 }
194 
195 
196 void SCH_SCREEN::Clear( bool aFree )
197 {
198  if( aFree )
199  {
200  FreeDrawList();
201  clearLibSymbols();
202  }
203  else
204  {
205  m_rtree.clear();
206  }
207 
208  // Clear the project settings
210 
211  m_titles.Clear();
212 }
213 
214 
216 {
217  // We don't know which order we will encounter dependent items (e.g. pins or fields), so
218  // we store the items to be deleted until we've fully cleared the tree before deleting
219  std::vector<SCH_ITEM*> delete_list;
220 
221  std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
222  []( SCH_ITEM* aItem )
223  {
224  return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
225  } );
226 
227  m_rtree.clear();
228 
229  for( auto item : delete_list )
230  delete item;
231 }
232 
233 
235 {
236  if( Remove( aItem ) )
237  Append( aItem );
238 }
239 
240 
242 {
243  bool retv = m_rtree.remove( aItem );
244 
245  // Check if the library symbol for the removed schematic symbol is still required.
246  if( retv && aItem->Type() == SCH_COMPONENT_T )
247  {
248  SCH_COMPONENT* removedSymbol = static_cast<SCH_COMPONENT*>( aItem );
249 
250  bool removeUnusedLibSymbol = true;
251 
252  for( SCH_ITEM* item : Items().OfType( SCH_COMPONENT_T ) )
253  {
254  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
255 
256  if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
257  {
258  removeUnusedLibSymbol = false;
259  break;
260  }
261  }
262 
263  if( removeUnusedLibSymbol )
264  {
265  auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
266 
267  if( it != m_libSymbols.end() )
268  {
269  delete it->second;
270  m_libSymbols.erase( it );
271  }
272  }
273  }
274 
275  return retv;
276 }
277 
278 
280 {
281  wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
282 
283  // Markers are not saved in the file, no need to flag as modified.
284  // TODO: Maybe we should have a listing somewhere of items that aren't saved?
285  if( aItem->Type() != SCH_MARKER_T )
286  SetModify();
287 
288  Remove( aItem );
289 
290  if( aItem->Type() == SCH_SHEET_PIN_T )
291  {
292  // This structure is attached to a sheet, get the parent sheet object.
293  SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
294  SCH_SHEET* sheet = sheetPin->GetParent();
295  wxCHECK_RET( sheet, wxT( "Sheet label parent not properly set, bad programmer!" ) );
296  sheet->RemovePin( sheetPin );
297  return;
298  }
299 
300  delete aItem;
301 }
302 
303 
305 {
306  return m_rtree.contains( aItem, true );
307 }
308 
309 
310 SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType )
311 {
312  EDA_RECT bbox;
313  bbox.SetOrigin( aPosition );
314  bbox.Inflate( aAccuracy );
315 
316  for( auto item : Items().Overlapping( aType, bbox ) )
317  {
318  if( item->HitTest( aPosition, aAccuracy ) )
319  return item;
320  }
321 
322  return nullptr;
323 }
324 
325 
326 std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
327 {
328  std::set<SCH_ITEM*> retval;
329  std::stack<SCH_LINE*> to_search;
330 
331  wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
332 
333  to_search.push( aSegment );
334 
335  while( !to_search.empty() )
336  {
337  SCH_LINE* test_item = to_search.top();
338  to_search.pop();
339 
340  for( SCH_ITEM* item : Items().Overlapping( SCH_JUNCTION_T, test_item->GetBoundingBox() ) )
341  {
342  if( test_item->IsEndPoint( item->GetPosition() ) )
343  retval.insert( item );
344  }
345 
346  for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, test_item->GetBoundingBox() ) )
347  {
348  // Skip connecting lines on different layers (e.g. buses)
349  if( test_item->GetLayer() != item->GetLayer() )
350  continue;
351 
352  SCH_LINE* line = static_cast<SCH_LINE*>( item );
353 
354  if( ( test_item->IsEndPoint( line->GetStartPoint() )
355  && !GetPin( line->GetStartPoint(), NULL, true ) )
356  || ( test_item->IsEndPoint( line->GetEndPoint() )
357  && !GetPin( line->GetEndPoint(), nullptr, true ) ) )
358  {
359  auto result = retval.insert( line );
360 
361  if( result.second )
362  to_search.push( line );
363  }
364  }
365  }
366 
367  return retval;
368 }
369 
370 
371 bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
372 {
373  enum { WIRES, BUSES } layers;
374 
375  bool has_nonparallel[ sizeof( layers ) ] = { false };
376  int end_count[ sizeof( layers ) ] = { 0 };
377  int entry_count = 0;
378  int pin_count = 0;
379 
380  std::vector<SCH_LINE*> lines[ sizeof( layers ) ];
381 
382  for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
383  {
384  if( item->GetEditFlags() & STRUCT_DELETED )
385  continue;
386 
387  switch( item->Type() )
388  {
389  case SCH_JUNCTION_T:
390  if( aNew && item->HitTest( aPosition ) )
391  return false;
392 
393  break;
394 
395  case SCH_LINE_T:
396  if( item->HitTest( aPosition, 0 ) )
397  {
398  if( item->GetLayer() == LAYER_WIRE )
399  lines[WIRES].push_back( (SCH_LINE*) item );
400  else if( item->GetLayer() == LAYER_BUS )
401  lines[BUSES].push_back( (SCH_LINE*) item );
402  }
403  break;
404 
406  case SCH_BUS_BUS_ENTRY_T:
407  if( item->IsConnected( aPosition ) )
408  entry_count++;
409 
410  break;
411 
412  case SCH_COMPONENT_T:
413  case SCH_SHEET_T:
414  if( item->IsConnected( aPosition ) )
415  pin_count++;
416 
417  break;
418 
419  default:
420  break;
421  }
422  }
423 
424  for( int i : { WIRES, BUSES } )
425  {
426  bool removed_overlapping = false;
427  bool mid_point = false;
428 
429  for( auto line = lines[i].begin(); line < lines[i].end(); line++ )
430  {
431  if( !(*line)->IsEndPoint( aPosition ) )
432  mid_point = true;
433  else
434  end_count[i]++;
435 
436  for( auto second_line = lines[i].end() - 1; second_line > line; second_line-- )
437  {
438  if( !(*line)->IsParallel( *second_line ) )
439  has_nonparallel[i] = true;
440  else if( !removed_overlapping
441  && (*line)->IsSameQuadrant( *second_line, aPosition ) )
442  {
443  removed_overlapping = true;
444  }
445  }
446  }
447 
451  if( mid_point )
452  end_count[i] += 2;
453 
456  if( removed_overlapping )
457  end_count[i]--;
458  }
459 
460  // If there are three or more endpoints
461  if( pin_count && pin_count + end_count[WIRES] > 2 )
462  return true;
463 
464  // If there is at least one segment that ends on a non-parallel line or
465  // junction of two other lines
466  if( has_nonparallel[WIRES] && end_count[WIRES] > 2 )
467  return true;
468 
469  // Check for bus - bus junction requirements
470  if( has_nonparallel[BUSES] && end_count[BUSES] > 2 )
471  return true;
472 
473  // Check for bus - bus entry requirements
474  if( !aNew && entry_count && end_count[BUSES] )
475  return true;
476 
477  return false;
478 }
479 
480 
481 bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer )
482 {
483  wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
484  wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
485 
486  SCH_SHEET_PIN* label;
487  SCH_TEXT* text;
488  SCH_CONNECTION conn;
489 
490  switch( aLayer )
491  {
492  case LAYER_BUS:
493 
494  if( GetBus( aPosition ) )
495  return true;
496 
497  label = GetSheetLabel( aPosition );
498 
499  if( label && conn.MightBeBusLabel( label->GetText() ) && label->IsConnected( aPosition ) )
500  return true;
501 
502  text = GetLabel( aPosition );
503 
504  if( text && conn.MightBeBusLabel( text->GetText() ) && text->IsConnected( aPosition )
505  && (text->Type() != SCH_LABEL_T) )
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  if( GetItem( aPosition, Mils2iu( 6 ), SCH_BUS_WIRE_ENTRY_T) )
519  return true;
520 
521  if( GetItem( aPosition, Mils2iu( 6 ), SCH_BUS_BUS_ENTRY_T) )
522  return true;
523 
524  if( GetItem( aPosition, Schematic()->Settings().m_JunctionSize, SCH_JUNCTION_T ) )
525  return true;
526 
527  if( GetPin( aPosition, NULL, true ) )
528  return true;
529 
530  if( GetWire( aPosition ) )
531  return true;
532 
533  text = GetLabel( aPosition );
534 
535  if( text && text->IsConnected( aPosition ) && !conn.MightBeBusLabel( text->GetText() ) )
536  return true;
537 
538  label = GetSheetLabel( aPosition );
539 
540  if( label && label->IsConnected( aPosition ) && !conn.MightBeBusLabel( label->GetText() ) )
541  return true;
542 
543  break;
544 
545  default:
546  break;
547  }
548 
549  return false;
550 }
551 
552 
554 {
555  wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
556 
557  wxString msg;
558  std::unique_ptr< LIB_PART > libSymbol;
559  std::vector<SCH_COMPONENT*> symbols;
560  SYMBOL_LIB_TABLE* libs = Schematic()->Prj().SchSymbolLibTable();
561 
562  // This will be a nullptr if an s-expression schematic is loaded.
563  PART_LIBS* legacyLibs = Schematic()->Prj().SchLibs();
564 
565  for( auto item : Items().OfType( SCH_COMPONENT_T ) )
566  symbols.push_back( static_cast<SCH_COMPONENT*>( item ) );
567 
568  // Remove them from the R tree. There bounding box size may change.
569  for( auto symbol : symbols )
570  Remove( symbol );
571 
572  // Clear all existing symbol links.
573  clearLibSymbols();
574 
575  for( auto symbol : symbols )
576  {
577  LIB_PART* tmp = nullptr;
578  libSymbol.reset();
579 
580  // If the symbol is already in the internal library, map the symbol to it.
581  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
582 
583  if( ( it != m_libSymbols.end() ) )
584  {
585  if( aReporter )
586  {
587  msg.Printf( _( "Setting schematic symbol '%s %s' library identifier "
588  "to '%s'. " ),
589  symbol->GetField( REFERENCE_FIELD )->GetText(),
590  symbol->GetField( VALUE_FIELD )->GetText(),
591  symbol->GetLibId().Format().wx_str() );
592  aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
593  }
594 
595  // Internal library symbols are already flattened so just make a copy.
596  symbol->SetLibSymbol( new LIB_PART( *it->second ) );
597  continue;
598  }
599 
600  if( !symbol->GetLibId().IsValid() )
601  {
602  if( aReporter )
603  {
604  msg.Printf( _( "Schematic symbol reference '%s' library identifier is not "
605  "valid. Unable to link library symbol." ),
606  symbol->GetLibId().Format().wx_str() );
607  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
608  }
609 
610  continue;
611  }
612 
613  // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the the library nickname
614  // is not found in the table so check if the library still exists in the table
615  // before attempting to load the symbol.
616  if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
617  {
618  if( aReporter )
619  {
620  msg.Printf( _( "Symbol library '%s' not found and no fallback cache "
621  "library available. Unable to link library symbol." ),
622  symbol->GetLibId().GetLibNickname().wx_str() );
623  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
624  }
625 
626  continue;
627  }
628 
629  if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
630  {
631  try
632  {
633  tmp = libs->LoadSymbol( symbol->GetLibId() );
634  }
635  catch( const IO_ERROR& ioe )
636  {
637  if( aReporter )
638  {
639  msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
640  symbol->GetLibId().Format().wx_str() );
641  aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
642  }
643  }
644  }
645 
646  if( !tmp && legacyLibs )
647  {
648  // If here, only the cache library should be loaded if the loaded schematic
649  // is the legacy file format.
650  wxCHECK2( legacyLibs->GetLibraryCount() == 1, continue );
651 
652  PART_LIB& legacyCacheLib = legacyLibs->at( 0 );
653 
654  // ...and it better be the cache library.
655  wxCHECK2( legacyCacheLib.IsCache(), continue );
656 
657  wxString id = symbol->GetLibId().Format();
658 
659  id.Replace( ':', '_' );
660 
661  if( aReporter )
662  {
663  msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
664  symbol->GetField( REFERENCE_FIELD )->GetText(),
665  symbol->GetField( VALUE_FIELD )->GetText(),
666  id );
667  aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
668  }
669 
670  tmp = legacyCacheLib.FindPart( id );
671  }
672 
673  if( tmp )
674  {
675  // We want a full symbol not just the top level child symbol.
676  libSymbol = tmp->Flatten();
677  libSymbol->SetParent();
678 
679  m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
680  new LIB_PART( *libSymbol.get() ) } );
681 
682  if( aReporter )
683  {
684  msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'. " ),
685  symbol->GetField( REFERENCE_FIELD )->GetText(),
686  symbol->GetField( VALUE_FIELD )->GetText(),
687  symbol->GetLibId().Format().wx_str() );
688  aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
689  }
690  }
691  else
692  {
693  if( aReporter )
694  {
695  msg.Printf( _( "No library symbol found for schematic symbol '%s %s'. " ),
696  symbol->GetField( REFERENCE_FIELD )->GetText(),
697  symbol->GetField( VALUE_FIELD )->GetText() );
698  aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
699  }
700  }
701 
702  symbol->SetLibSymbol( libSymbol.release() );
703  }
704 
705  // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
706  // item with the new bbox
707  for( auto symbol : symbols )
708  Append( symbol );
709 }
710 
711 
713 {
714  std::vector<SCH_COMPONENT*> symbols;
715 
716  for( auto item : Items().OfType( SCH_COMPONENT_T ) )
717  symbols.push_back( static_cast<SCH_COMPONENT*>( item ) );
718 
719  for( auto symbol : symbols )
720  {
721  // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
722  m_rtree.remove( symbol );
723 
724  auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
725 
726  LIB_PART* libSymbol = nullptr;
727 
728  if( it != m_libSymbols.end() )
729  libSymbol = new LIB_PART( *it->second );
730 
731  symbol->SetLibSymbol( libSymbol );
732 
733  m_rtree.insert( symbol );
734  }
735 }
736 
737 
739 {
740  // Ensure links are up to date, even if a library was reloaded for some reason:
741  std::vector< SCH_ITEM* > junctions;
742  std::vector<SCH_ITEM*> bitmaps;
743  std::vector<SCH_ITEM*> other;
744 
745  for( auto item : Items() )
746  {
747  if( item->IsMoving() || item->IsResized() )
748  continue;
749 
750  if( item->Type() == SCH_JUNCTION_T )
751  junctions.push_back( item );
752  else if( item->Type() == SCH_BITMAP_T )
753  bitmaps.push_back( item );
754  else
755  other.push_back( item );
756  }
757 
759  std::sort( other.begin(), other.end(),
760  []( const SCH_ITEM* a, const SCH_ITEM* b )
761  {
762  if( a->Type() == b->Type() )
763  return a->GetLayer() > b->GetLayer();
764 
765  return a->Type() > b->Type();
766  } );
767 
768  for( auto item : bitmaps )
769  item->Print( aSettings, wxPoint( 0, 0 ) );
770 
771  for( auto item : other )
772  item->Print( aSettings, wxPoint( 0, 0 ) );
773 
774  for( auto item : junctions )
775  item->Print( aSettings, wxPoint( 0, 0 ) );
776 }
777 
778 
779 void SCH_SCREEN::Plot( PLOTTER* aPlotter )
780 {
781  // Ensure links are up to date, even if a library was reloaded for some reason:
782  std::vector< SCH_ITEM* > junctions;
783  std::vector< SCH_ITEM* > bitmaps;
784  std::vector< SCH_ITEM* > other;
785 
786  for( auto item : Items() )
787  {
788  if( item->IsMoving() || item->IsResized() )
789  continue;
790 
791  if( item->Type() == SCH_JUNCTION_T )
792  junctions.push_back( item );
793  else if( item->Type() == SCH_BITMAP_T )
794  bitmaps.push_back( item );
795  else
796  other.push_back( item );
797  }
798 
800  std::sort( other.begin(), other.end(), []( const SCH_ITEM* a, const SCH_ITEM* b ) {
801  if( a->Type() == b->Type() )
802  return a->GetLayer() > b->GetLayer();
803 
804  return a->Type() > b->Type();
805  } );
806 
807  int defaultPenWidth = aPlotter->RenderSettings()->GetDefaultPenWidth();
808 
809  // Bitmaps are drawn first to ensure they are in the background
810  // This is particularly important for the wxPostscriptDC (used in *nix printers) as
811  // the bitmap PS command clears the screen
812  for( SCH_ITEM* item : bitmaps )
813  {
814  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
815  item->Plot( aPlotter );
816  }
817 
818  for( SCH_ITEM* item : other )
819  {
820  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
821  item->Plot( aPlotter );
822  }
823 
824  for( SCH_ITEM* item : junctions )
825  {
826  aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
827  item->Plot( aPlotter );
828  }
829 }
830 
831 
833 {
834  for( auto item : Items() )
835  item->ClearTempFlags();
836 }
837 
838 
839 LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aSymbol,
840  bool aEndPointOnly )
841 {
842  SCH_COMPONENT* candidate = NULL;
843  LIB_PIN* pin = NULL;
844 
845  for( SCH_ITEM* item : Items().Overlapping( SCH_COMPONENT_T, aPosition ) )
846  {
847  candidate = static_cast<SCH_COMPONENT*>( item );
848 
849  if( aEndPointOnly )
850  {
851  pin = NULL;
852 
853  if( !candidate->GetPartRef() )
854  continue;
855 
856  for( pin = candidate->GetPartRef()->GetNextPin(); pin;
857  pin = candidate->GetPartRef()->GetNextPin( pin ) )
858  {
859  // Skip items not used for this part.
860  if( candidate->GetUnit() && pin->GetUnit() &&
861  ( pin->GetUnit() != candidate->GetUnit() ) )
862  continue;
863 
864  if( candidate->GetConvert() && pin->GetConvert() &&
865  ( pin->GetConvert() != candidate->GetConvert() ) )
866  continue;
867 
868  if( candidate->GetPinPhysicalPosition( pin ) == aPosition )
869  break;
870  }
871  if( pin )
872  break;
873  }
874  else
875  {
876  pin = (LIB_PIN*) candidate->GetDrawItem( aPosition, LIB_PIN_T );
877 
878  if( pin )
879  break;
880  }
881  }
882 
883  if( pin && aSymbol )
884  *aSymbol = candidate;
885 
886  return pin;
887 }
888 
889 
890 SCH_SHEET_PIN* SCH_SCREEN::GetSheetLabel( const wxPoint& aPosition )
891 {
892  SCH_SHEET_PIN* sheetPin = nullptr;
893 
894  for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
895  {
896  auto sheet = static_cast<SCH_SHEET*>( item );
897 
898  sheetPin = sheet->GetPin( aPosition );
899 
900  if( sheetPin )
901  break;
902  }
903 
904  return sheetPin;
905 }
906 
907 
908 size_t SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions )
909 {
910  size_t count = 0;
911 
912  for( SCH_ITEM* item : Items() )
913  {
914  if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
915  count++;
916  }
917 
918  return count;
919 }
920 
921 
923 {
924 
925  for( SCH_ITEM* item : Items().OfType( SCH_COMPONENT_T ) )
926  {
927  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
928 
929  symbol->ClearAnnotation( aSheetPath );
930  }
931 }
932 
933 
935 {
936  if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
937  return;
938 
939  for( SCH_ITEM* item : Items().OfType( SCH_COMPONENT_T ) )
940  {
941  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
942 
943  // Add (when not existing) all sheet path entries
944  for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
945  symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
946  }
947 }
948 
949 
950 void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems )
951 {
952  static KICAD_T hierarchicalTypes[] = { SCH_COMPONENT_T, SCH_SHEET_T, SCH_GLOBAL_LABEL_T, EOT };
953 
954  for( SCH_ITEM* item : Items() )
955  {
956  if( item->IsType( hierarchicalTypes ) )
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 symbols inside new sheetpaths not already in aInitialSheetList
1212  SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1213  screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1214 
1215  // Search for new sheet paths, not existing in aInitialSheetPathList
1216  // and existing in sheetpathList
1217  for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1218  {
1219  bool path_exists = false;
1220 
1221  for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1222  {
1223  if( existing_sheetpath.Path() == sheetpath.Path() )
1224  {
1225  path_exists = true;
1226  break;
1227  }
1228  }
1229 
1230  if( !path_exists )
1231  {
1232  // A new sheet path is found: clear the annotation corresponding to this new path:
1233  SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1234 
1235  // Clear annotation and create the AR for this path, if not exists,
1236  // when the screen is shared by sheet paths.
1237  // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1238  // reference default value and takes the latest displayed value
1239  curr_screen->EnsureAlternateReferencesExist();
1240  curr_screen->ClearAnnotation( &sheetpath );
1241  }
1242  }
1243 }
1244 
1245 
1247 {
1248  std::vector<SCH_ITEM*> items;
1249  int count = 0;
1250 
1251  auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1252  {
1253  return a->m_Uuid < b->m_Uuid;
1254  };
1255 
1256  std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1257 
1258  for( SCH_SCREEN* screen : m_screens )
1259  screen->GetHierarchicalItems( &items );
1260 
1261  if( items.size() < 2 )
1262  return 0;
1263 
1264  for( EDA_ITEM* item : items )
1265  {
1266  if( !unique_stamps.insert( item ).second )
1267  {
1268  // Reset to fully random UUID. This may lose reference, but better to be
1269  // deterministic about it rather than to have duplicate UUIDs with random
1270  // side-effects.
1271  const_cast<KIID&>( item->m_Uuid ) = KIID();
1272  count++;
1273  }
1274  }
1275 
1276  return count;
1277 }
1278 
1279 
1281 {
1282  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1283  {
1284  for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1285  {
1286  if( item == aMarker )
1287  {
1288  screen->DeleteItem( item );
1289  return;
1290  }
1291  }
1292  }
1293 }
1294 
1295 
1296 void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::TYPEMARKER aMarkerType, int aErrorCode,
1297  bool aIncludeExclusions )
1298 {
1299  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1300  {
1301  std::vector<SCH_ITEM*> markers;
1302 
1303  for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1304  {
1305  SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1306  std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1307 
1308  if( marker->GetMarkerType() == aMarkerType
1309  && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1310  && ( !marker->IsExcluded() || aIncludeExclusions ) )
1311  {
1312  markers.push_back( item );
1313  }
1314  }
1315 
1316  for( SCH_ITEM* marker : markers )
1317  screen->DeleteItem( marker );
1318  }
1319 }
1320 
1321 
1323  bool aIncludeExclusions )
1324 {
1325  DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1326 }
1327 
1328 
1330 {
1331  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1332  screen->UpdateSymbolLinks( aReporter );
1333 
1334  SCH_SCREEN* first = GetFirst();
1335 
1336  if( !first )
1337  return;
1338 
1339  SCHEMATIC* sch = first->Schematic();
1340 
1341  wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1342 
1343  SCH_SHEET_LIST sheets = sch->GetSheets();
1344 
1345  // All of the library symbols have been replaced with copies so the connection graph
1346  // pointer are stale.
1347  if( sch->ConnectionGraph() )
1348  sch->ConnectionGraph()->Recalculate( sheets, true );
1349 }
1350 
1351 
1353 {
1354  std::vector<SCH_SCREEN*> screens;
1355  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1356  screens.push_back( screen );
1357 
1358  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
1359  screens.size() );
1360 
1361  std::atomic<size_t> nextScreen( 0 );
1362  std::vector<std::future<size_t>> returns( parallelThreadCount );
1363 
1364  auto update_lambda = [&screens, &nextScreen]() -> size_t
1365  {
1366  for( auto i = nextScreen++; i < screens.size(); i = nextScreen++ )
1367  screens[i]->TestDanglingEnds();
1368 
1369  return 1;
1370  };
1371 
1372  if( parallelThreadCount == 1 )
1373  update_lambda();
1374  else
1375  {
1376  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
1377  returns[ii] = std::async( std::launch::async, update_lambda );
1378 
1379  // Finalize the threads
1380  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
1381  returns[ii].wait();
1382  }
1383 }
1384 
1385 
1387 {
1388  SCH_SCREEN* screen;
1389  unsigned cnt = 0;
1390 
1391  for( screen = GetFirst(); screen; screen = GetNext() )
1392  {
1393  for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
1394  {
1395  cnt++;
1396  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
1397 
1398  if( !symbol->GetLibId().GetLibNickname().empty() )
1399  return false;
1400  }
1401  }
1402 
1403  return cnt != 0;
1404 }
1405 
1406 
1407 size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1408 {
1409  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1410  {
1411  for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
1412  {
1413  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
1414  const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1415 
1416  if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1417  aLibNicknames.Add( nickname );
1418  }
1419  }
1420 
1421  return aLibNicknames.GetCount();
1422 }
1423 
1424 
1425 int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1426 {
1427  SCH_SCREEN* screen;
1428  int cnt = 0;
1429 
1430  for( screen = GetFirst(); screen; screen = GetNext() )
1431  {
1432  for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
1433  {
1434  auto symbol = static_cast<SCH_COMPONENT*>( item );
1435 
1436  if( symbol->GetLibId().GetLibNickname() != aFrom )
1437  continue;
1438 
1439  LIB_ID id = symbol->GetLibId();
1440  id.SetLibNickname( aTo );
1441  symbol->SetLibId( id );
1442  cnt++;
1443  }
1444  }
1445 
1446  return cnt;
1447 }
1448 
1449 
1450 bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1451 {
1452  for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1453  {
1454  if( screen->GetFileName() == aSchematicFileName )
1455  return true;
1456  }
1457 
1458  return false;
1459 }
1460 
1461 
1462 bool SCH_SCREENS::CanCauseCaseSensitivityIssue( const wxString& aSchematicFileName ) const
1463 {
1464  wxString lhsLower;
1465  wxString rhsLower;
1466  wxFileName lhs;
1467  wxFileName rhs = aSchematicFileName;
1468 
1469  wxCHECK( rhs.IsAbsolute(), false );
1470 
1471  for( const SCH_SCREEN* screen : m_screens )
1472  {
1473  lhs = screen->GetFileName();
1474 
1475  if( lhs.GetPath() != rhs.GetPath() )
1476  continue;
1477 
1478  lhsLower = lhs.GetFullName().Lower();
1479  rhsLower = rhs.GetFullName().Lower();
1480 
1481  if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
1482  return true;
1483  }
1484 
1485  return false;
1486 }
1487 
1488 
1490 {
1491  SCH_SCREEN* first = GetFirst();
1492 
1493  if( !first )
1494  return;
1495 
1496  SCHEMATIC* sch = first->Schematic();
1497 
1498  wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
1499 
1500  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1501  curr_screen->GetClientSheetPaths().clear();
1502 
1503  for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1504  {
1505  SCH_SCREEN* used_screen = sheetpath.LastScreen();
1506 
1507  // SEarch for the used_screen in list and add this unique sheet path:
1508  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1509  {
1510  if( used_screen == curr_screen )
1511  {
1512  curr_screen->GetClientSheetPaths().push_back( sheetpath );
1513  break;
1514  }
1515  }
1516  }
1517 }
UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to...
Definition: utf8.h:73
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
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:51
static bool MightBeBusLabel(const wxString &aLabel)
Test if aLabel looks like a bus notation.
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:241
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.
Definition: sch_sheet.h:169
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:97
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:44
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:137
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:371
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:98
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:125
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:934
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
virtual wxPoint GetPosition() const
Definition: eda_item.h:325
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:284
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:184
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:196
Field Value of part, i.e. "3.3K".
void InitDataPoints(const wxSize &aPageSizeInternalUnits)
Definition: base_screen.cpp:48
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:67
unsigned int m_index
Definition: sch_screen.h:526
Definition: kiid.h:44
bool HasItems(KICAD_T aItemType) const
Definition: sch_screen.cpp:121
int GetUnit() const
Definition: lib_item.h:296
int GetUnit() const
void RemovePin(SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:291
void UpdateLocalLibSymbolLinks()
Initialize the LIB_PART reference for each SCH_COMPONENT found in this schematic with the local proje...
Definition: sch_screen.cpp:712
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:525
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:95
void DeleteItem(SCH_ITEM *aItem)
Removes aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:279
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:41
iterator end()
Definition: sch_rtree.h:253
int m_pageCount
The number of BASE_SCREEN objects in this design.
Definition: base_screen.h:63
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
bool HasSchematic(const wxString &aSchematicFileName)
Check if one of the schematics in the list of screens is aSchematicFileName.
EDA_ITEM * GetParent() const
Definition: eda_item.h:183
void Print(RENDER_SETTINGS *aSettings)
Print all the items in the screen to aDC.
Definition: sch_screen.cpp:738
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
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:950
SCH_SHEET_PIN * GetSheetLabel(const wxPoint &aPosition)
Test the screen if aPosition is a sheet label object.
Definition: sch_screen.cpp:890
bool IsEndPoint(const wxPoint &aPoint) const
Definition: sch_line.h:87
#define STRUCT_DELETED
flag indication structures to be erased
Definition: eda_item.h:115
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:85
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:434
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
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:299
size_t CountConnectedItems(const wxPoint &aPos, bool aTestJunctions)
Definition: sch_screen.cpp:908
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:215
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
void Plot(PLOTTER *aPlotter)
Plot all the schematic objects to aPlotter.
Definition: sch_screen.cpp:779
const KIID m_Uuid
Definition: eda_item.h:151
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:122
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:285
A collection of PART_LIB objects.
void buildScreenList(SCH_SHEET *aSheet)
void DecRefCount()
Definition: sch_screen.cpp:113
Base plotter engine class.
Definition: plotter.h:131
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:553
SCH_SHEET & Root() const
Definition: schematic.h:102
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:165
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer)
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:481
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:524
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:129
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:89
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:159
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:79
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
Definition: schematic.h:85
EDA_ITEM is a base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:148
int GetDefaultPenWidth() const
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Clear the annotation for the components in aSheetPath on the screen.
Definition: sch_screen.cpp:922
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:2949
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Definition: sch_screen.h:206
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:310
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:165
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:832
void Update(SCH_ITEM *aItem)
Updates aItem's bounding box in the tree.
Definition: sch_screen.cpp:234
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:120
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:304
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath)
Clear exiting component annotation.
const LIB_ID & GetLibId() const
Field Reference of part, i.e. "IC21".
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:133
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:122
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:521
LIB_PIN * GetPin(const wxPoint &aPosition, SCH_COMPONENT **aSymbol=NULL, bool aEndPointOnly=false)
Test the screen for a component pin item at aPosition.
Definition: sch_screen.cpp:839
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
void IncRefCount()
Definition: sch_screen.cpp:107
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
bool TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr)
Test all of the connectable objects in the schematic for unused connection points.
bool empty() const
Definition: utf8.h:108
virtual wxString GetClass() const override
Return the class name.
Definition: sch_screen.h:176
std::map< wxString, LIB_PART * > m_libSymbols
Library symbols required for this schematic.
Definition: sch_screen.h:123
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
Definition: base_screen.h:71
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:326
SCH_LINE * GetBus(const wxPoint &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T)
Definition: sch_screen.h:440
wxPoint GetEndPoint() const
Definition: sch_line.h:97