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-2017 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 <fctsys.h>
33 #include <gr_basic.h>
34 #include <common.h>
35 #include <kicad_string.h>
36 #include <eeschema_id.h>
37 #include <pgm_base.h>
38 #include <kiway.h>
39 #include <sch_draw_panel.h>
40 #include <sch_item_struct.h>
41 #include <sch_edit_frame.h>
42 #include <plotter.h>
43 
44 #include <netlist.h>
45 #include <netlist_object.h>
46 #include <class_library.h>
47 #include <sch_junction.h>
48 #include <sch_bus_entry.h>
49 #include <sch_line.h>
50 #include <sch_marker.h>
51 #include <sch_no_connect.h>
52 #include <sch_sheet.h>
53 #include <sch_component.h>
54 #include <sch_text.h>
55 #include <lib_pin.h>
56 #include <symbol_lib_table.h>
57 #include <tool/common_tools.h>
58 
59 #define EESCHEMA_FILE_STAMP "EESchema"
60 
61 /* Default zoom values. Limited to these values to keep a decent size
62  * to menus
63  */
64 static double SchematicZoomList[] =
65 {
66  0.5, 0.7, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 11.0,
67  13.0, 16.0, 20.0, 26.0, 32.0, 48.0, 64.0, 80.0, 128.0
68 };
69 
70 /* Default grid sizes for the schematic editor.
71  * Do NOT add others values (mainly grid values in mm), because they
72  * can break the schematic: Because wires and pins are considered as
73  * connected when the are to the same coordinate we cannot mix
74  * coordinates in mils (internal units) and mm (that cannot exactly
75  * converted in mils in many cases). In fact schematic must only use
76  * 50 and 25 mils to place labels, wires and components others values
77  * are useful only for graphic items (mainly in library editor) so use
78  * integer values in mils only. The 100 mil grid is added to help
79  * conform to the KiCad Library Convention. Which states: "Using a
80  * 100mil grid, pin ends and origin must lie on grid nodes IEC-60617"
81 */
83  { ID_POPUP_GRID_LEVEL_100, wxRealPoint( 100, 100 ) },
84  { ID_POPUP_GRID_LEVEL_50, wxRealPoint( 50, 50 ) },
85  { ID_POPUP_GRID_LEVEL_25, wxRealPoint( 25, 25 ) },
86  { ID_POPUP_GRID_LEVEL_10, wxRealPoint( 10, 10 ) },
87  { ID_POPUP_GRID_LEVEL_5, wxRealPoint( 5, 5 ) },
88  { ID_POPUP_GRID_LEVEL_2, wxRealPoint( 2, 2 ) },
89  { ID_POPUP_GRID_LEVEL_1, wxRealPoint( 1, 1 ) },
90 };
91 
92 
95  KIWAY_HOLDER( aKiway ),
96  m_paper( wxT( "A4" ) )
97 {
99 
100  SetZoom( 32 );
101 
102  for( unsigned i = 0; i < arrayDim( SchematicZoomList ); i++ )
103  m_ZoomList.push_back( SchematicZoomList[i] );
104 
105  for( unsigned i = 0; i < arrayDim( SchematicGridList ); i++ )
107 
108  // Set the default grid size, now that the grid list is populated
109  SetGrid( wxRealPoint( 50, 50 ) );
110 
111  m_refCount = 0;
112 
113  // Suitable for schematic only. For libedit and viewlib, must be set to true
114  m_Center = false;
115 
116  InitDataPoints( m_paper.GetSizeIU() );
117 }
118 
119 
121 {
123 
124  // Now delete items in draw list. We do that only if the list is not empty,
125  // because if the list was appended to another list (see SCH_SCREEN::Append( SCH_SCREEN* aScreen )
126  // it is empty but as no longer the ownership (m_drawList.meOwner == false) of items, and calling
127  // FreeDrawList() with m_drawList.meOwner == false will generate a debug alert in debug mode
128  if( GetDrawItems() )
129  FreeDrawList();
130 }
131 
132 
134 {
135  m_refCount++;
136 }
137 
138 
140 {
141  wxCHECK_RET( m_refCount != 0,
142  wxT( "Screen reference count already zero. Bad programmer!" ) );
143  m_refCount--;
144 }
145 
146 
148 {
149  wxCHECK_RET( aScreen, "Invalid screen object." );
150 
151  // No need to decend the hierarchy. Once the top level screen is copied, all of it's
152  // children are copied as well.
153  m_drawList.Append( aScreen->m_drawList );
154 
155  // This screen owns the objects now. This prevents the object from being delete when
156  // aSheet is deleted.
157  aScreen->m_drawList.SetOwnership( false );
158 }
159 
160 
162 {
163  FreeDrawList();
164 
165  // Clear the project settings
167 
168  m_titles.Clear();
169 }
170 
171 
173 {
175 }
176 
177 
179 {
180  m_drawList.Remove( aItem );
181 }
182 
183 
185 {
186  wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
187 
188  SetModify();
189 
190  if( aItem->Type() == SCH_SHEET_PIN_T )
191  {
192  // This structure is attached to a sheet, get the parent sheet object.
193  SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
194  SCH_SHEET* sheet = sheetPin->GetParent();
195  wxCHECK_RET( sheet, wxT( "Sheet label parent not properly set, bad programmer!" ) );
196  sheet->RemovePin( sheetPin );
197  return;
198  }
199  else
200  {
201  m_drawList.Remove( aItem );
202  delete aItem;
203  }
204 }
205 
206 
208 {
209  SCH_ITEM* itemList = m_drawList.begin();
210 
211  while( itemList )
212  {
213  if( itemList == aItem )
214  return true;
215 
216  itemList = itemList->Next();
217  }
218 
219  return false;
220 }
221 
222 
223 SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType ) const
224 {
225  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
226  {
227  if( (aType == SCH_FIELD_T) && (item->Type() == SCH_COMPONENT_T) )
228  {
229  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
230 
231  for( int i = REFERENCE; i < component->GetFieldCount(); i++ )
232  {
233  SCH_FIELD* field = component->GetField( i );
234 
235  if( field->HitTest( aPosition, aAccuracy ) )
236  return (SCH_ITEM*) field;
237  }
238  }
239  else if( (aType == SCH_SHEET_PIN_T) && (item->Type() == SCH_SHEET_T) )
240  {
241  SCH_SHEET* sheet = (SCH_SHEET*)item;
242 
243  SCH_SHEET_PIN* label = sheet->GetPin( aPosition );
244 
245  if( label )
246  return (SCH_ITEM*) label;
247  }
248  else if( ( ( item->Type() == aType ) || ( aType == NOT_USED ) )
249  && item->HitTest( aPosition, aAccuracy ) )
250  {
251  return item;
252  }
253  }
254 
255  return NULL;
256 }
257 
258 
260 {
261  SCH_ITEM* item;
262  SCH_ITEM* next_item;
263 
264  for( item = m_drawList.begin(); item; item = next_item )
265  {
266  next_item = item->Next();
267 
268  switch( item->Type() )
269  {
270  case SCH_JUNCTION_T:
271  case SCH_LINE_T:
272  Remove( item );
273  delete item;
274  break;
275 
276  default:
277  break;
278  }
279  }
280 
281  m_drawList.Append( aWireList );
282 }
283 
284 
286 {
287  wxCHECK_RET( (aSegment) && (aSegment->Type() == SCH_LINE_T),
288  wxT( "Invalid object pointer." ) );
289 
290  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
291  {
292  if( item->GetFlags() & CANDIDATE )
293  continue;
294 
295  if( item->Type() == SCH_JUNCTION_T )
296  {
297  SCH_JUNCTION* junction = (SCH_JUNCTION*) item;
298 
299  if( aSegment->IsEndPoint( junction->GetPosition() ) )
300  item->SetFlags( CANDIDATE );
301 
302  continue;
303  }
304 
305  if( item->Type() != SCH_LINE_T )
306  continue;
307 
308  SCH_LINE* segment = (SCH_LINE*) item;
309 
310  if( aSegment->IsEndPoint( segment->GetStartPoint() )
311  && !GetPin( segment->GetStartPoint(), NULL, true ) )
312  {
313  item->SetFlags( CANDIDATE );
314  MarkConnections( segment );
315  }
316 
317  if( aSegment->IsEndPoint( segment->GetEndPoint() )
318  && !GetPin( segment->GetEndPoint(), NULL, true ) )
319  {
320  item->SetFlags( CANDIDATE );
321  MarkConnections( segment );
322  }
323  }
324 }
325 
326 
327 bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
328 {
329  bool has_nonparallel[2] = { false };
330  int end_count[2] = { 0 };
331  int pin_count = 0;
332 
333  std::vector<SCH_LINE*> lines[2];
334 
335  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
336  {
337  if( item->GetFlags() & STRUCT_DELETED )
338  continue;
339 
340  if( aNew && ( item->Type() == SCH_JUNCTION_T ) && ( item->HitTest( aPosition ) ) )
341  return false;
342 
343  if( ( item->Type() == SCH_LINE_T )
344  && ( item->HitTest( aPosition, 0 ) ) )
345  {
346  if( item->GetLayer() == LAYER_WIRE )
347  lines[0].push_back( (SCH_LINE*) item );
348  else if( item->GetLayer() == LAYER_BUS )
349  lines[1].push_back( (SCH_LINE*) item );
350  }
351 
352  if( ( item->Type() == SCH_COMPONENT_T )
353  && ( item->IsConnected( aPosition ) ) )
354  pin_count++;
355  }
356 
357  for( int i = 0; i < 2; i++ )
358  {
359  bool removed_overlapping = false;
360  end_count[i] = lines[i].size();
361 
362  for( auto line = lines[i].begin(); line < lines[i].end(); line++ )
363  {
364  // Consider ending on a line to be equivalent to two endpoints because
365  // we will want to split the line if anything else connects
366  if( !(*line)->IsEndPoint( aPosition ) )
367  end_count[i]++;
368 
369  for( auto second_line = lines[i].end() - 1; second_line > line; second_line-- )
370  {
371  if( !(*line)->IsParallel( *second_line ) )
372  has_nonparallel[i] = true;
373  else if( !removed_overlapping
374  && (*line)->IsSameQuadrant( *second_line, aPosition ) )
375  {
381  removed_overlapping = true;
382  end_count[i]--;
383  }
384  }
385  }
386  }
387 
388  //
389 
390  // If there are three or more endpoints
391  if( pin_count + end_count[0] > 2 )
392  return true;
393 
394  // If there is at least one segment that ends on a non-parallel line or
395  // junction of two other lines
396  if( has_nonparallel[0] && end_count[0] > 2 )
397  return true;
398 
399  // Check for bus - bus junction requirements
400  if( has_nonparallel[1] && end_count[1] > 2 )
401  return true;
402 
403  return false;
404 }
405 
406 
407 bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer )
408 {
409  wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
410  wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
411 
412  SCH_SHEET_PIN* label;
413  SCH_TEXT* text;
414 
415  switch( aLayer )
416  {
417  case LAYER_BUS:
418 
419  if( GetBus( aPosition ) )
420  return true;
421 
422  label = GetSheetLabel( aPosition );
423 
424  if( label && IsBusLabel( label->GetText() ) && label->IsConnected( aPosition ) )
425  return true;
426 
427  text = GetLabel( aPosition );
428 
429  if( text && IsBusLabel( text->GetText() ) && text->IsConnected( aPosition )
430  && (text->Type() != SCH_LABEL_T) )
431  return true;
432 
433  break;
434 
435  case LAYER_NOTES:
436 
437  if( GetLine( aPosition ) )
438  return true;
439 
440  break;
441 
442  case LAYER_WIRE:
444  return true;
445 
446  if( GetItem( aPosition, std::max( GetDefaultLineThickness(), 3 ), SCH_BUS_BUS_ENTRY_T) )
447  return true;
448 
449  if( GetItem( aPosition, std::max( GetDefaultLineThickness(), 3 ), SCH_JUNCTION_T ) )
450  return true;
451 
452  if( GetPin( aPosition, NULL, true ) )
453  return true;
454 
455  if( GetWire( aPosition ) )
456  return true;
457 
458  text = GetLabel( aPosition );
459 
460  if( text && text->IsConnected( aPosition ) && !IsBusLabel( text->GetText() ) )
461  return true;
462 
463  label = GetSheetLabel( aPosition );
464 
465  if( label && label->IsConnected( aPosition ) && !IsBusLabel( label->GetText() ) )
466  return true;
467 
468  break;
469 
470  default:
471  break;
472  }
473 
474  return false;
475 }
476 
477 
478 void SCH_SCREEN::UpdateSymbolLinks( bool aForce )
479 {
480  // Initialize or reinitialize the pointer to the LIB_PART for each component
481  // found in m_drawList, but only if needed (change in lib or schematic)
482  // therefore the calculation time is usually very low.
483  if( m_drawList.GetCount() )
484  {
485  SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
486  int mod_hash = libs->GetModifyHash();
488 
490 
491  // Must we resolve?
492  if( (m_modification_sync != mod_hash) || aForce )
493  {
494  SCH_COMPONENT::ResolveAll( c, *libs, Prj().SchLibs()->GetCacheLibrary() );
495 
496  m_modification_sync = mod_hash; // note the last mod_hash
497  }
498  // Resolving will update the pin caches but we must ensure that this happens
499  // even if the libraries don't change.
500  else
502  }
503 }
504 
505 
506 void SCH_SCREEN::Draw( EDA_DRAW_PANEL* aCanvas, wxDC* aDC, GR_DRAWMODE aDrawMode, COLOR4D aColor )
507 {
508  /* note: SCH_SCREEN::Draw is useful only for schematic.
509  * library editor and library viewer do not use m_drawList, and therefore
510  * their SCH_SCREEN::Draw() draws nothing
511  */
512  std::vector< SCH_ITEM* > junctions;
513 
514  // Ensure links are up to date, even if a library was reloaded for some reason:
516 
517  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
518  {
519  if( item->IsMoving() || item->IsResized() )
520  continue;
521 
522  if( item->Type() == SCH_JUNCTION_T )
523  junctions.push_back( item );
524  else
525  // uncomment line below when there is a virtual EDA_ITEM::GetBoundingBox()
526  // if( panel->GetClipBox().Intersects( item->GetBoundingBox() ) )
527  item->Draw( aCanvas, aDC, wxPoint( 0, 0 ), aDrawMode, aColor );
528  }
529 
530  for( auto item : junctions )
531  item->Draw( aCanvas, aDC, wxPoint( 0, 0 ), aDrawMode, aColor );
532 }
533 
534 
535 void SCH_SCREEN::Plot( PLOTTER* aPlotter )
536 {
537  // Ensure links are up to date, even if a library was reloaded for some reason:
539 
540  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
541  {
542  aPlotter->SetCurrentLineWidth( item->GetPenSize() );
543  item->Plot( aPlotter );
544  }
545 }
546 
547 
549 {
550  if( aItemCount == 0 )
551  return;
552 
553  for( auto& command : aList.m_CommandsList )
554  {
555  command->ClearListAndDeleteItems();
556  delete command;
557  }
558 
559  aList.m_CommandsList.clear();
560 }
561 
562 
564 {
565  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
566  item->ClearFlags();
567 }
568 
569 
570 LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent,
571  bool aEndPointOnly ) const
572 {
573  SCH_ITEM* item;
574  SCH_COMPONENT* component = NULL;
575  LIB_PIN* pin = NULL;
576 
577  for( item = m_drawList.begin(); item; item = item->Next() )
578  {
579  if( item->Type() != SCH_COMPONENT_T )
580  continue;
581 
582  component = (SCH_COMPONENT*) item;
583 
584  if( aEndPointOnly )
585  {
586  pin = NULL;
587 
588  auto part = component->GetPartRef().lock();
589 
590  if( !part )
591  continue;
592 
593  for( pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
594  {
595  // Skip items not used for this part.
596  if( component->GetUnit() && pin->GetUnit() &&
597  ( pin->GetUnit() != component->GetUnit() ) )
598  continue;
599 
600  if( component->GetConvert() && pin->GetConvert() &&
601  ( pin->GetConvert() != component->GetConvert() ) )
602  continue;
603 
604  if(component->GetPinPhysicalPosition( pin ) == aPosition )
605  break;
606  }
607  if( pin )
608  break;
609  }
610  else
611  {
612  pin = (LIB_PIN*) component->GetDrawItem( aPosition, LIB_PIN_T );
613 
614  if( pin )
615  break;
616  }
617  }
618 
619  if( pin && aComponent )
620  *aComponent = component;
621 
622  return pin;
623 }
624 
625 
626 SCH_SHEET* SCH_SCREEN::GetSheet( const wxString& aName )
627 {
628  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
629  {
630  if( item->Type() != SCH_SHEET_T )
631  continue;
632 
633  SCH_SHEET* sheet = (SCH_SHEET*) item;
634 
635  if( aName.CmpNoCase( sheet->GetName() ) == 0 )
636  return sheet;
637  }
638 
639  return NULL;
640 }
641 
642 
643 SCH_SHEET_PIN* SCH_SCREEN::GetSheetLabel( const wxPoint& aPosition )
644 {
645  SCH_SHEET_PIN* sheetPin = NULL;
646 
647  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
648  {
649  if( item->Type() != SCH_SHEET_T )
650  continue;
651 
652  SCH_SHEET* sheet = (SCH_SHEET*) item;
653  sheetPin = sheet->GetPin( aPosition );
654 
655  if( sheetPin )
656  break;
657  }
658 
659  return sheetPin;
660 }
661 
662 
663 int SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const
664 {
665  SCH_ITEM* item;
666  int count = 0;
667 
668  for( item = m_drawList.begin(); item; item = item->Next() )
669  {
670  if( item->Type() == SCH_JUNCTION_T && !aTestJunctions )
671  continue;
672 
673  if( item->IsConnected( aPos ) )
674  count++;
675  }
676 
677  return count;
678 }
679 
680 
682 {
683  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
684  {
685  if( item->Type() == SCH_COMPONENT_T )
686  {
687  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
688 
689  component->ClearAnnotation( aSheetPath );
690 
691  // Clear the modified component flag set by component->ClearAnnotation
692  // because we do not use it here and we should not leave this flag set,
693  // when an editing is finished:
694  component->ClearFlags();
695  }
696  }
697 }
698 
699 
701 {
702  if( GetClientSheetPathsCount() <= 1 ) // No need for alternate reference
703  return;
704 
705  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
706  {
707  if( item->Type() != SCH_COMPONENT_T )
708  continue;
709 
710  // Add (when not existing) all sheet path entries
711  for( unsigned int ii = 0; ii < m_clientSheetPathList.GetCount(); ii++ )
712  ((SCH_COMPONENT*)item)->AddSheetPathReferenceEntryIfMissing( m_clientSheetPathList[ii] );
713  }
714 }
715 
716 
718 {
719  SCH_ITEM* item = m_drawList.begin();
720 
721  while( item )
722  {
723  if( ( item->Type() == SCH_SHEET_T ) || ( item->Type() == SCH_COMPONENT_T ) )
724  aItems.push_back( item );
725 
726  item = item->Next();
727  }
728 }
729 
730 
732 {
733  auto addConnections = [ this ]( SCH_ITEM* item ) -> void
734  {
735  std::vector< wxPoint > connections;
736  item->GetConnectionPoints( connections );
737  for( auto conn : connections )
738  addConnectedItemsToBlock( item, conn );
739  };
740 
741  PICKED_ITEMS_LIST* pickedlist = &m_BlockLocate.GetItems();
742 
743  if( pickedlist->GetCount() == 0 )
744  return;
745 
747 
748  for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ )
749  {
750  SCH_ITEM* item = (SCH_ITEM*) pickedlist->GetPickedItem( ii );
751  item->SetFlags( SELECTED );
752  }
753 
754  if( !m_BlockLocate.IsDragging() )
755  return;
756 
757  // Select all the items in the screen connected to the items in the block.
758  // be sure end lines that are on the block limits are seen inside this block
759  m_BlockLocate.Inflate( 1 );
760  unsigned last_select_id = pickedlist->GetCount();
761 
762  for( unsigned ii = 0; ii < last_select_id; ii++ )
763  {
764  SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii );
765  item->SetFlags( IS_DRAGGED );
766 
767  if( item->Type() == SCH_LINE_T )
768  {
770 
771  if( !item->IsSelected() )
772  { // This is a special case:
773  // this selected wire has no ends in block.
774  // But it was selected (because it intersects the selecting area),
775  // so we must keep it selected and select items connected to it
776  // Note: another option could be: remove it from drag list
777  item->SetFlags( SELECTED | SKIP_STRUCT );
778  addConnections( item );
779  }
780 
781  pickedlist->SetPickerFlags( item->GetFlags(), ii );
782  }
783  else if( item->IsConnectable() )
784  {
785  addConnections( item );
786  }
787  }
788 
789  // Select the items that are connected to a block object that was added
790  // to our selection list in the last step.
791  for( unsigned ii = last_select_id; ii < pickedlist->GetCount(); ii++ )
792  {
793  SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii );
794 
795  if( item->Type() == SCH_COMPONENT_T ||
796  item->Type() == SCH_BUS_BUS_ENTRY_T ||
797  item->Type() == SCH_BUS_WIRE_ENTRY_T ||
798  item->Type() == SCH_SHEET_T ||
799  ( item->Type() == SCH_LINE_T && !( item->GetFlags() & ( ENDPOINT | STARTPOINT ) ) ) )
800  {
801  item->SetFlags( IS_DRAGGED );
802  addConnections( item );
803  }
804  }
805 
806  m_BlockLocate.Inflate( -1 );
807 }
808 
809 
810 void SCH_SCREEN::addConnectedItemsToBlock( const SCH_ITEM* aItem, const wxPoint& position )
811 {
812  SCH_ITEM* item;
813  ITEM_PICKER picker;
814 
815  for( item = m_drawList.begin(); item; item = item->Next() )
816  {
817 
818  if( !item->IsConnectable() || ( item->GetFlags() & SKIP_STRUCT )
819  || !item->CanConnect( aItem ) || item == aItem )
820  continue;
821 
822  // A line having 2 ends, it can be tested twice: one time per end
823  if( item->Type() == SCH_LINE_T )
824  {
825  SCH_LINE* line = (SCH_LINE*) item;
826 
827  if( !item->HitTest( position ) )
828  continue;
829 
830  // First time through. Flags set to denote an end that is not moving
831  if( !item->IsSelected() )
832  item->SetFlags( CANDIDATE | STARTPOINT | ENDPOINT );
833 
834  if( line->GetStartPoint() == position )
835  item->ClearFlags( STARTPOINT );
836  else if( line->GetEndPoint() == position )
837  item->ClearFlags( ENDPOINT );
838  else
839  // This picks up items such as labels that can connect to the middle of a line
840  item->ClearFlags( STARTPOINT | ENDPOINT );
841  }
842  // We want to move a mid-connected label or bus entry when the full line is being moved
843  else if( !item->IsSelected()
844  && aItem->Type() == SCH_LINE_T
845  && !( aItem->GetFlags() & ( ENDPOINT | STARTPOINT ) ) )
846  {
847  std::vector< wxPoint > connections;
848  item->GetConnectionPoints( connections );
849 
850  for( auto conn : connections )
851  {
852  if( aItem->HitTest( conn ) )
853  {
854  item->SetFlags( CANDIDATE );
855  break;
856  }
857  }
858  }
859 
860  if( item->IsSelected() )
861  continue;
862 
863  if( ( item->GetFlags() & CANDIDATE ) || item->IsConnected( position ) ) // Deal with all non-line items
864  {
865  item->ClearFlags( CANDIDATE );
866  item->SetFlags( SELECTED );
867  picker.SetItem( item );
868  picker.SetFlags( item->GetFlags() );
869  m_BlockLocate.GetItems().PushItem( picker );
870  }
871  }
872 }
873 
874 
876 {
877  ITEM_PICKER picker;
878  EDA_RECT area;
879  unsigned count;
880 
882  area.SetSize( m_BlockLocate.GetSize() );
883  area.Normalize();
884 
885  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
886  {
887  // An item is picked if its bounding box intersects the reference area.
888  if( item->HitTest( area ) &&
889  ( !m_BlockLocate.IsDragging() || item->IsType( SCH_COLLECTOR::DraggableItems ) ) )
890  {
891  picker.SetItem( item );
892  m_BlockLocate.PushItem( picker );
893  }
894  }
895 
896  // if the block is composed of one item,
897  // select it as the current item
898  count = m_BlockLocate.GetCount();
899  if( count == 1 )
900  {
902  }
903  else
904  {
905  SetCurItem( NULL );
906  }
907 
908  return count;
909 }
910 
911 
913 {
914  SCH_ITEM* item;
915  std::vector< DANGLING_END_ITEM > endPoints;
916  bool hasStateChanged = false;
917 
918  for( item = m_drawList.begin(); item; item = item->Next() )
919  item->GetEndPoints( endPoints );
920 
921  for( item = m_drawList.begin(); item; item = item->Next() )
922  {
923  if( item->UpdateDanglingState( endPoints ) )
924  {
925  hasStateChanged = true;
926  }
927  }
928 
929  return hasStateChanged;
930 }
931 
932 
933 int SCH_SCREEN::GetNode( const wxPoint& aPosition, EDA_ITEMS& aList )
934 {
935  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
936  {
937  if( item->Type() == SCH_LINE_T && item->HitTest( aPosition )
938  && (item->GetLayer() == LAYER_BUS || item->GetLayer() == LAYER_WIRE) )
939  {
940  aList.push_back( item );
941  }
942  else if( item->Type() == SCH_JUNCTION_T && item->HitTest( aPosition ) )
943  {
944  aList.push_back( item );
945  }
946  }
947 
948  return (int) aList.size();
949 }
950 
951 
952 SCH_LINE* SCH_SCREEN::GetWireOrBus( const wxPoint& aPosition )
953 {
954  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
955  {
956  if( (item->Type() == SCH_LINE_T) && item->HitTest( aPosition )
957  && (item->GetLayer() == LAYER_BUS || item->GetLayer() == LAYER_WIRE) )
958  {
959  return (SCH_LINE*) item;
960  }
961  }
962 
963  return NULL;
964 }
965 
966 
967 SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLayer,
968  SCH_LINE_TEST_T aSearchType )
969 {
970  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
971  {
972  if( item->Type() != SCH_LINE_T )
973  continue;
974 
975  if( item->GetLayer() != aLayer )
976  continue;
977 
978  if( !item->HitTest( aPosition, aAccuracy ) )
979  continue;
980 
981  switch( aSearchType )
982  {
983  case ENTIRE_LENGTH_T:
984  return (SCH_LINE*) item;
985 
987  if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
988  return (SCH_LINE*) item;
989  break;
990 
991  case END_POINTS_ONLY_T:
992  if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
993  return (SCH_LINE*) item;
994  }
995  }
996 
997  return NULL;
998 }
999 
1000 
1001 SCH_TEXT* SCH_SCREEN::GetLabel( const wxPoint& aPosition, int aAccuracy )
1002 {
1003  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
1004  {
1005  switch( item->Type() )
1006  {
1007  case SCH_LABEL_T:
1008  case SCH_GLOBAL_LABEL_T:
1010  if( item->HitTest( aPosition, aAccuracy ) )
1011  return (SCH_TEXT*) item;
1012 
1013  default:
1014  ;
1015  }
1016  }
1017 
1018  return NULL;
1019 }
1020 
1021 
1022 bool SCH_SCREEN::SetComponentFootprint( SCH_SHEET_PATH* aSheetPath, const wxString& aReference,
1023  const wxString& aFootPrint, bool aSetVisible )
1024 {
1025  SCH_COMPONENT* component;
1026  bool found = false;
1027 
1028  for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
1029  {
1030  if( item->Type() != SCH_COMPONENT_T )
1031  continue;
1032 
1033  component = (SCH_COMPONENT*) item;
1034 
1035  if( aReference.CmpNoCase( component->GetRef( aSheetPath ) ) == 0 )
1036  {
1037  // Found: Init Footprint Field
1038 
1039  /* Give a reasonable value to the field position and
1040  * orientation, if the text is empty at position 0, because
1041  * it is probably not yet initialized
1042  */
1043  SCH_FIELD * fpfield = component->GetField( FOOTPRINT );
1044  if( fpfield->GetText().IsEmpty()
1045  && ( fpfield->GetTextPos() == component->GetPosition() ) )
1046  {
1047  fpfield->SetTextAngle( component->GetField( VALUE )->GetTextAngle() );
1048  fpfield->SetTextPos( component->GetField( VALUE )->GetTextPos() );
1049  fpfield->SetTextSize( component->GetField( VALUE )->GetTextSize() );
1050 
1051  if( fpfield->GetTextAngle() == 0.0 )
1052  fpfield->Offset( wxPoint( 0, 100 ) );
1053  else
1054  fpfield->Offset( wxPoint( 100, 0 ) );
1055  }
1056 
1057  fpfield->SetText( aFootPrint );
1058  fpfield->SetVisible( aSetVisible );
1059 
1060  found = true;
1061  }
1062  }
1063 
1064  return found;
1065 }
1066 
1067 
1068 int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aList,
1069  bool aFullConnection )
1070 {
1071  SCH_ITEM* item;
1072  EDA_ITEM* tmp;
1073  EDA_ITEMS list;
1074 
1075  // Clear flags member for all items.
1077 
1078  if( GetNode( aPosition, list ) == 0 )
1079  return 0;
1080 
1081  for( size_t i = 0; i < list.size(); i++ )
1082  {
1083  item = (SCH_ITEM*) list[ i ];
1085 
1086  /* Put this structure in the picked list: */
1087  ITEM_PICKER picker( item, UR_DELETED );
1088  aList.PushItem( picker );
1089  }
1090 
1091  // Mark all wires, junctions, .. connected to the item(s) found.
1092  if( aFullConnection )
1093  {
1094  SCH_LINE* segment;
1095 
1096  for( item = m_drawList.begin(); item; item = item->Next() )
1097  {
1098  if( !(item->GetFlags() & SELECTEDNODE) )
1099  continue;
1100 
1101  if( item->Type() != SCH_LINE_T )
1102  continue;
1103 
1104  MarkConnections( (SCH_LINE*) item );
1105  }
1106 
1107  // Search all attached wires (i.e wire with one new dangling end )
1108  for( item = m_drawList.begin(); item; item = item->Next() )
1109  {
1110  bool noconnect = false;
1111 
1112  if( item->GetFlags() & STRUCT_DELETED )
1113  continue; // Already seen
1114 
1115  if( !(item->GetFlags() & CANDIDATE) )
1116  continue; // not a candidate
1117 
1118  if( item->Type() != SCH_LINE_T )
1119  continue;
1120 
1121  item->SetFlags( SKIP_STRUCT );
1122 
1123  segment = (SCH_LINE*) item;
1124 
1125  /* If the wire start point is connected to a wire that was already found
1126  * and now is not connected, add the wire to the list. */
1127  for( tmp = m_drawList.begin(); tmp; tmp = tmp->Next() )
1128  {
1129  // Ensure tmp is a previously deleted segment:
1130  if( ( tmp->GetFlags() & STRUCT_DELETED ) == 0 )
1131  continue;
1132 
1133  if( tmp->Type() != SCH_LINE_T )
1134  continue;
1135 
1136  SCH_LINE* testSegment = (SCH_LINE*) tmp;
1137 
1138  // Test for segment connected to the previously deleted segment:
1139  if( testSegment->IsEndPoint( segment->GetStartPoint() ) )
1140  break;
1141  }
1142 
1143  // when tmp != NULL, segment is a new candidate:
1144  // put it in deleted list if
1145  // the start point is not connected to another item (like pin)
1146  if( tmp && !CountConnectedItems( segment->GetStartPoint(), true ) )
1147  noconnect = true;
1148 
1149  /* If the wire end point is connected to a wire that has already been found
1150  * and now is not connected, add the wire to the list. */
1151  for( tmp = m_drawList.begin(); tmp; tmp = tmp->Next() )
1152  {
1153  // Ensure tmp is a previously deleted segment:
1154  if( ( tmp->GetFlags() & STRUCT_DELETED ) == 0 )
1155  continue;
1156 
1157  if( tmp->Type() != SCH_LINE_T )
1158  continue;
1159 
1160  SCH_LINE* testSegment = (SCH_LINE*) tmp;
1161 
1162  // Test for segment connected to the previously deleted segment:
1163  if( testSegment->IsEndPoint( segment->GetEndPoint() ) )
1164  break;
1165  }
1166 
1167  // when tmp != NULL, segment is a new candidate:
1168  // put it in deleted list if
1169  // the end point is not connected to another item (like pin)
1170  if( tmp && !CountConnectedItems( segment->GetEndPoint(), true ) )
1171  noconnect = true;
1172 
1173  item->ClearFlags( SKIP_STRUCT );
1174 
1175  if( noconnect )
1176  {
1177  item->SetFlags( STRUCT_DELETED );
1178 
1179  ITEM_PICKER picker( item, UR_DELETED );
1180  aList.PushItem( picker );
1181 
1182  item = m_drawList.begin();
1183  }
1184  }
1185 
1186  for( item = m_drawList.begin(); item; item = item->Next() )
1187  {
1188  if( item->GetFlags() & STRUCT_DELETED )
1189  continue;
1190 
1191  if( item->Type() != SCH_LABEL_T )
1192  continue;
1193 
1194  tmp = GetWireOrBus( ( (SCH_TEXT*) item )->GetPosition() );
1195 
1196  if( tmp && ( tmp->GetFlags() & STRUCT_DELETED ) )
1197  {
1198  item->SetFlags( STRUCT_DELETED );
1199 
1200  ITEM_PICKER picker( item, UR_DELETED );
1201  aList.PushItem( picker );
1202  }
1203  }
1204  }
1205 
1207 
1208  return aList.GetCount();
1209 }
1210 
1211 
1212 #if defined(DEBUG)
1213 void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1214 {
1215  // for now, make it look like XML, expand on this later.
1216  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1217 
1218  for( EDA_ITEM* item = m_drawList.begin(); item; item = item->Next() )
1219  {
1220  item->Show( nestLevel+1, os );
1221  }
1222 
1223  NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1224 }
1225 #endif
1226 
1227 
1231 static bool SortByTimeStamp( const EDA_ITEM* item1, const EDA_ITEM* item2 )
1232 {
1233  int ii = item1->GetTimeStamp() - item2->GetTimeStamp();
1234 
1235  /* If the time stamps are the same, compare type in order to have component objects
1236  * before sheet object. This is done because changing the sheet time stamp
1237  * before the component time stamp could cause the current annotation to be lost.
1238  */
1239  if( ( ii == 0 && ( item1->Type() != item2->Type() ) ) && ( item1->Type() == SCH_SHEET_T ) )
1240  ii = -1;
1241 
1242  return ii < 0;
1243 }
1244 
1245 
1247 {
1248  m_index = 0;
1249  buildScreenList( ( !aSheet ) ? g_RootSheet : aSheet );
1250 }
1251 
1252 
1254 {
1255 }
1256 
1257 
1259 {
1260  m_index = 0;
1261 
1262  if( m_screens.size() > 0 )
1263  return m_screens[0];
1264 
1265  return NULL;
1266 }
1267 
1268 
1270 {
1271  if( m_index < m_screens.size() )
1272  m_index++;
1273 
1274  return GetScreen( m_index );
1275 }
1276 
1277 
1278 SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1279 {
1280  if( aIndex < m_screens.size() )
1281  return m_screens[ aIndex ];
1282 
1283  return NULL;
1284 }
1285 
1286 
1288 {
1289  if( aScreen == NULL )
1290  return;
1291 
1292  for( unsigned int i = 0; i < m_screens.size(); i++ )
1293  {
1294  if( m_screens[i] == aScreen )
1295  return;
1296  }
1297 
1298  m_screens.push_back( aScreen );
1299 }
1300 
1301 
1303 {
1304  if( aSheet && aSheet->Type() == SCH_SHEET_T )
1305  {
1306  SCH_SCREEN* screen = aSheet->GetScreen();
1307 
1308  addScreenToList( screen );
1309 
1310  EDA_ITEM* strct = screen->GetDrawItems();
1311 
1312  while( strct )
1313  {
1314  if( strct->Type() == SCH_SHEET_T )
1315  {
1316  buildScreenList( ( SCH_SHEET* )strct );
1317  }
1318 
1319  strct = strct->Next();
1320  }
1321  }
1322 }
1323 
1324 
1326 {
1327  for( size_t i = 0; i < m_screens.size(); i++ )
1328  m_screens[i]->ClearAnnotation( NULL );
1329 }
1330 
1331 
1333 {
1334  // Clear the annotation for the components inside new sheetpaths
1335  // not already in aInitialSheetList
1336  SCH_SCREENS screensList( g_RootSheet ); // The list of screens, shared by sheet paths
1337  screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1338 
1339  // Search for new sheet paths, not existing in aInitialSheetPathList
1340  // and existing in sheetpathList
1341  SCH_SHEET_LIST sheetpathList( g_RootSheet );
1342 
1343  for( SCH_SHEET_PATH& sheetpath: sheetpathList )
1344  {
1345  bool path_exists = false;
1346 
1347  for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1348  {
1349  if( existing_sheetpath.Path() == sheetpath.Path() )
1350  {
1351  path_exists = true;
1352  break;
1353  }
1354  }
1355 
1356  if( !path_exists )
1357  {
1358  // A new sheet path is found: clear the annotation corresponding to this new path:
1359  SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1360 
1361  // Clear annotation and create the AR for this path, if not exists,
1362  // when the screen is shared by sheet paths.
1363  // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1364  // reference default value and takes the latest displayed value
1365  curr_screen->EnsureAlternateReferencesExist();
1366  curr_screen->ClearAnnotation( &sheetpath );
1367  }
1368  }
1369 }
1370 
1371 
1373 {
1374  EDA_ITEMS items;
1375  SCH_ITEM* item;
1376 
1377  for( size_t i = 0; i < m_screens.size(); i++ )
1378  m_screens[i]->GetHierarchicalItems( items );
1379 
1380  if( items.size() < 2 )
1381  return 0;
1382 
1383  sort( items.begin(), items.end(), SortByTimeStamp );
1384 
1385  int count = 0;
1386 
1387  for( size_t ii = 0; ii < items.size() - 1; ii++ )
1388  {
1389  item = (SCH_ITEM*)items[ii];
1390 
1391  SCH_ITEM* nextItem = (SCH_ITEM*)items[ii + 1];
1392 
1393  if( item->GetTimeStamp() == nextItem->GetTimeStamp() )
1394  {
1395  count++;
1396 
1397  // for a component, update its Time stamp and its paths
1398  // (m_PathsAndReferences field)
1399  if( item->Type() == SCH_COMPONENT_T )
1400  ( (SCH_COMPONENT*) item )->SetTimeStamp( GetNewTimeStamp() );
1401 
1402  // for a sheet, update only its time stamp (annotation of its
1403  // components will be lost)
1404  // @todo: see how to change sheet paths for its cmp list (can
1405  // be possible in most cases)
1406  else
1407  item->SetTimeStamp( GetNewTimeStamp() );
1408  }
1409  }
1410 
1411  return count;
1412 }
1413 
1414 
1416 {
1417  SCH_ITEM* item;
1418  SCH_ITEM* nextItem;
1419  SCH_MARKER* marker;
1420  SCH_SCREEN* screen;
1421 
1422  for( screen = GetFirst(); screen; screen = GetNext() )
1423  {
1424  for( item = screen->GetDrawItems(); item; item = nextItem )
1425  {
1426  nextItem = item->Next();
1427 
1428  if( item->Type() != SCH_MARKER_T )
1429  continue;
1430 
1431  marker = (SCH_MARKER*) item;
1432 
1433  if( marker->GetMarkerType() != aMarkerType )
1434  continue;
1435 
1436  screen->DeleteItem( marker );
1437  }
1438  }
1439 }
1440 
1441 
1443  enum MARKER_BASE::MARKER_SEVERITY aSeverity )
1444 {
1445  int count = 0;
1446 
1447  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1448  {
1449  for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
1450  {
1451  if( item->Type() != SCH_MARKER_T )
1452  continue;
1453 
1454  SCH_MARKER* marker = (SCH_MARKER*) item;
1455 
1456  if( ( aMarkerType != MARKER_BASE::MARKER_UNSPEC ) &&
1457  ( marker->GetMarkerType() != aMarkerType ) )
1458  continue;
1459 
1460  if( aSeverity == MARKER_BASE::MARKER_SEVERITY_UNSPEC ||
1461  aSeverity == marker->GetErrorLevel() )
1462  count++;
1463  }
1464  }
1465 
1466  return count;
1467 }
1468 
1469 
1471 {
1472  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1473  screen->UpdateSymbolLinks( aForce );
1474 }
1475 
1476 
1478 {
1479  for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1480  screen->TestDanglingEnds();
1481 }
1482 
1483 
1485 {
1486  SCH_COMPONENT* symbol;
1487  SCH_ITEM* item;
1488  SCH_ITEM* nextItem;
1489  SCH_SCREEN* screen;
1490  unsigned cnt = 0;
1491 
1492  for( screen = GetFirst(); screen; screen = GetNext() )
1493  {
1494  for( item = screen->GetDrawItems(); item; item = nextItem )
1495  {
1496  nextItem = item->Next();
1497 
1498  if( item->Type() != SCH_COMPONENT_T )
1499  continue;
1500 
1501  cnt += 1;
1502  symbol = dynamic_cast< SCH_COMPONENT* >( item );
1503  wxASSERT( symbol );
1504 
1505  if( !symbol->GetLibId().GetLibNickname().empty() )
1506  return false;
1507  }
1508  }
1509 
1510  if( cnt == 0 )
1511  return false;
1512 
1513  return true;
1514 }
1515 
1516 
1517 size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1518 {
1519  SCH_COMPONENT* symbol;
1520  SCH_ITEM* item;
1521  SCH_ITEM* nextItem;
1522  SCH_SCREEN* screen;
1523  wxString nickname;
1524 
1525  for( screen = GetFirst(); screen; screen = GetNext() )
1526  {
1527  for( item = screen->GetDrawItems(); item; item = nextItem )
1528  {
1529  nextItem = item->Next();
1530 
1531  if( item->Type() != SCH_COMPONENT_T )
1532  continue;
1533 
1534  symbol = dynamic_cast< SCH_COMPONENT* >( item );
1535  wxASSERT( symbol );
1536 
1537  if( !symbol )
1538  continue;
1539 
1540  nickname = symbol->GetLibId().GetLibNickname();
1541 
1542  if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1543  aLibNicknames.Add( nickname );;
1544  }
1545  }
1546 
1547  return aLibNicknames.GetCount();
1548 }
1549 
1550 
1551 int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1552 {
1553  SCH_COMPONENT* symbol;
1554  SCH_ITEM* item;
1555  SCH_ITEM* nextItem;
1556  SCH_SCREEN* screen;
1557  int cnt = 0;
1558 
1559  for( screen = GetFirst(); screen; screen = GetNext() )
1560  {
1561  for( item = screen->GetDrawItems(); item; item = nextItem )
1562  {
1563  nextItem = item->Next();
1564 
1565  if( item->Type() != SCH_COMPONENT_T )
1566  continue;
1567 
1568  symbol = dynamic_cast< SCH_COMPONENT* >( item );
1569  wxASSERT( symbol );
1570 
1571  if( symbol->GetLibId().GetLibNickname() != aFrom )
1572  continue;
1573 
1574  LIB_ID id = symbol->GetLibId();
1575  id.SetLibNickname( aTo );
1576  symbol->SetLibId( id );
1577  cnt++;
1578  }
1579  }
1580 
1581  return cnt;
1582 }
1583 
1584 
1586 {
1587  SCH_SHEET_LIST sheetList( g_RootSheet );
1588 
1589  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1590  curr_screen->GetClientSheetPaths().Clear();
1591 
1592  for( SCH_SHEET_PATH& sheetpath: sheetList )
1593  {
1594  SCH_SCREEN* used_screen = sheetpath.LastScreen();
1595 
1596  // SEarch for the used_screen in list and add this unique sheet path:
1597  for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1598  {
1599  if( used_screen == curr_screen )
1600  {
1601  curr_screen->GetClientSheetPaths().Add( sheetpath.Path() );
1602  break;
1603  }
1604  }
1605  }
1606 }
void SetTextAngle(double aAngle)
Definition: eda_text.h:169
Definition of the SCH_SHEET class for Eeschema.
Class SCH_SHEET_LIST.
Class SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:56
Class KIWAY_HOLDER is a mix in class which holds the location of a wxWindow's KIWAY.
Definition: kiway_player.h:48
void Offset(const wxPoint &aOffset)
Definition: eda_text.h:242
SCH_SCREEN * GetNext()
int m_ScreenNumber
Definition: base_screen.h:216
SCH_SHEET_PIN * GetPin(const wxPoint &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:371
BLOCK_SELECTOR m_BlockLocate
Block description for block commands.
Definition: base_screen.h:214
virtual bool IsConnectable() const
Function IsConnectable returns true if the schematic item can connect to another schematic item.
Class TYPE_COLLECTOR merely gathers up all SCH_ITEMs of a given set of KICAD_T type(s).
PART_REF & GetPartRef()
void DeleteAllMarkers(enum MARKER_BASE::TYPEMARKER aMarkerType)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Definition: sch_sheet.h:159
T * Remove(T *aElement)
Function Remove removes aElement from the list, but does not delete it.
Definition: dlist.h:211
wxPoint GetStartPoint() const
Definition: sch_line.h:76
bool IsSelected() const
Definition: base_struct.h:224
Base schematic object class definition.
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:327
virtual void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList)
Function GetEndPoints adds the schematic item end points to aItemList if the item has end points.
SCH_ITEM * Next() const
MARKER_SEVERITY GetErrorLevel() const
Definition: marker_base.h:176
static double SchematicZoomList[]
Definition: sch_screen.cpp:64
SCH_SHEET * GetSheet(const wxString &aName)
Returns a sheet object pointer that is named aName.
Definition: sch_screen.cpp:626
int GetClientSheetPathsCount()
Definition: sch_screen.h:153
void Append(T *aNewElement)
Function Append adds aNewElement to the end of the list.
Definition: dlist.h:177
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:125
void UpdateSymbolLinks(bool aForce=false)
Initialize or reinitialize the weak reference to the LIB_PART for each SCH_COMPONENT found in m_drawL...
Definition: sch_screen.cpp:478
the 3d code uses this value
Definition: typeinfo.h:80
SCH_MARKER class definition.
wxArrayString & GetClientSheetPaths()
Definition: sch_screen.h:155
int GetDefaultLineThickness()
Default line thickness used to draw/plot items having a default thickness line value (i....
int CountConnectedItems(const wxPoint &aPos, bool aTestJunctions) const
Definition: sch_screen.cpp:663
unsigned GetCount() const
Function GetCount returns the number of elements in the list.
Definition: dlist.h:126
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:236
#define SELECTEDNODE
flag indicating that the structure has already selected
Definition: base_struct.h:122
void SetVisible(bool aVisible)
Definition: eda_text.h:188
int m_refCount
Number of sheets referencing this screen.
Definition: sch_screen.h:74
int ChangeSymbolLibNickname(const wxString &aFrom, const wxString &aTo)
Change all of the symbol library nicknames.
virtual void GetConnectionPoints(std::vector< wxPoint > &aPoints) const
Function GetConnectionPoints add all the connection points for this item to aPoints.
double GetTextAngle() const
Definition: eda_text.h:177
SCH_SCREEN(KIWAY *aKiway)
Constructor.
Definition: sch_screen.cpp:93
static const KICAD_T ComponentsOnly[]
A scan list for schematic component items only.
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:124
T * begin() const
Definition: dlist.h:218
void Clear()
Definition: title_block.h:127
void PushItem(const ITEM_PICKER &aItem)
Function PushItem pushes aItem to the top of the list.
void Remove(SCH_ITEM *aItem)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:178
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 SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:227
void EnsureAlternateReferencesExist()
For screens shared by many sheetpaths (complex hierarchies): to be able to clear or modify any refere...
Definition: sch_screen.cpp:700
EDA_ITEM * GetItem(unsigned aIndex)
SCH_SCREENS(SCH_SHEET *aSheet=NULL)
#define CANDIDATE
flag indicating that the structure is connected
Definition: base_struct.h:124
void DeleteAll()
Function DeleteAll deletes all items on the list and leaves the list empty.
Definition: dlist.cpp:44
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
int m_modification_sync
inequality with PART_LIBS::GetModificationHash() will trigger ResolveAll().
Definition: sch_screen.h:95
SCH_SCREEN * GetScreen()
Definition: sch_sheet.h:279
Field Name Module PCB, i.e. "16DIP300".
unsigned GetCount() const
Function GetCount.
void addConnectedItemsToBlock(const SCH_ITEM *aItem, const wxPoint &aPosition)
Add items connected at aPosition to the block pick list.
Definition: sch_screen.cpp:810
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
bool IsDragging() const
Function IsDragging returns true if the current block command is a drag operation.
LIB_PIN * GetPin(const wxPoint &aPosition, SCH_COMPONENT **aComponent=NULL, bool aEndPointOnly=false) const
Test the screen for a component pin item at aPosition.
Definition: sch_screen.cpp:570
EDA_ITEM * Next() const
Definition: base_struct.h:209
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
static GRID_TYPE SchematicGridList[]
Definition: sch_screen.cpp:82
void InitDataPoints(const wxSize &aPageSizeInternalUnits)
Definition: base_screen.cpp:72
#define IS_DRAGGED
Item being dragged.
Definition: base_struct.h:116
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.
Definition: sch_screen.cpp:967
unsigned int m_index
Definition: sch_screen.h:527
bool HitTest(const wxPoint &aPosition, int aAccuracy) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: sch_field.cpp:461
#define SELECTED
Definition: base_struct.h:121
Class UNDO_REDO_CONTAINER is a holder to handle alist of undo (or redo) command.
virtual bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList)
Function IsDanglingStateChanged tests the schematic item to aItemList to check if it's dangling state...
timestamp_t GetNewTimeStamp()
Definition: common.cpp:216
int GetUnit() const
#define VALUE
void SetLibId(const LIB_ID &aName, PART_LIBS *aLibs=NULL)
int GetUnit() const
void RemovePin(SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:187
TITLE_BLOCK m_titles
Definition: sch_screen.h:88
virtual bool CanConnect(const SCH_ITEM *aItem) const
int GetConnection(const wxPoint &aPosition, PICKED_ITEMS_LIST &aList, bool aFullConnection)
Adds all of the wires and junctions to aList that make up a connection to the object at aPosition.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:256
PAGE_INFO m_paper
The size of the paper to print or plot on.
Definition: sch_screen.h:86
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:56
void GetHierarchicalItems(EDA_ITEMS &aItems)
Add all schematic sheet and component objects in the screen to aItems.
Definition: sch_screen.cpp:717
SCH_ITEM * GetItem(const wxPoint &aPosition, int aAccuracy=0, KICAD_T aType=NOT_USED) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:223
wxString GetName() const
Definition: sch_sheet.h:267
int UpdatePickList()
Add all the items in the screen within the block selection rectangle to the pick list.
Definition: sch_screen.cpp:875
std::vector< PICKED_ITEMS_LIST * > m_CommandsList
wxPoint GetPosition() const override
Function GetPosition.
Definition: sch_junction.h:104
static void ResolveAll(const SCH_COLLECTOR &aComponents, PART_LIBS *aLibs)
bool m_Center
Center on screen.
Definition: base_screen.h:202
void DeleteItem(SCH_ITEM *aItem)
Removes aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:184
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:37
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: base_struct.h:550
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
SCH_LINE_TEST_T
Definition: sch_screen.h:56
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:76
void MarkConnections(SCH_LINE *aSegment)
Add all wires and junctions connected to aSegment which are not connected any component pin to aItemL...
Definition: sch_screen.cpp:285
const wxSize & GetTextSize() const
Definition: eda_text.h:228
virtual void ClearUndoRedoList()
Function ClearUndoRedoList clear undo and redo list, using ClearUndoORRedoList() picked items are del...
void Clear()
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:161
void Draw(EDA_DRAW_PANEL *aCanvas, wxDC *aDC, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED)
Draw all the items in the screen to aCanvas.
Definition: sch_screen.cpp:506
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
Function GetPickedItem.
void BuildClientSheetPathList()
built the list of sheet paths sharing a screen for each screen in use
timestamp_t GetTimeStamp() const
Definition: base_struct.h:207
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:123
Class KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within...
Definition: kiway.h:258
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
void SetFlags(STATUS_FLAGS aFlags)
int GetNode(const wxPoint &aPosition, EDA_ITEMS &aList)
Return all the items at aPosition that form a node.
Definition: sch_screen.cpp:933
SCH_SHEET_PIN * GetSheetLabel(const wxPoint &aPosition)
Test the screen if aPosition is a sheet label object.
Definition: sch_screen.cpp:643
bool IsEndPoint(const wxPoint &aPoint) const
Definition: sch_line.h:69
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:61
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:462
virtual bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
Class SCH_SHEET_PATH.
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Clear exiting component annotation.
void SetItem(EDA_ITEM *aItem)
bool SetPickerFlags(STATUS_FLAGS aFlags, unsigned aIdx)
Function SetPickerFlags set the flags of the picker (usually to the picked item m_Flags value)
void SelectBlockItems()
Create a list of items found when a block command is initiated.
Definition: sch_screen.cpp:731
int GetConvert() const
const wxString GetRef(const SCH_SHEET_PATH *aSheet)
Return the reference for the given sheet path.
int GetFieldCount() const
Return the number of fields in this symbol.
void FreeDrawList()
Free all the items from the schematic associated with the screen.
Definition: sch_screen.cpp:172
bool IsBusLabel(const wxString &aLabel)
Function IsBusLabel test if aLabel has a bus notation.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:209
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:99
void Plot(PLOTTER *aPlotter)
Plot all the schematic objects to aPlotter.
Definition: sch_screen.cpp:535
int GetMarkerCount(enum MARKER_BASE::TYPEMARKER aMarkerType, enum MARKER_BASE::MARKER_SEVERITY aSeverity)
Return the number of ERC markers of aMarkerType from all of the screens in the list.
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:193
DLIST< SCH_ITEM > m_drawList
Object list for the screen.
Definition: sch_screen.h:93
void Normalize()
Function Normalize ensures that the height ant width are positive.
void buildScreenList(SCH_SHEET *aSheet)
void DecRefCount()
Definition: sch_screen.cpp:139
Base plotter engine class.
Definition: plotter.h:97
void addScreenToList(SCH_SCREEN *aScreen)
void SetSize(const wxSize &size)
Definition: eda_rect.h:126
Definition the SCH_COMPONENT class for Eeschema.
void AddGrid(const GRID_TYPE &grid)
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer)
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:407
see class PGM_BASE
void UpdateSymbolLinks(bool aForce=false)
Initialize or reinitialize the weak reference to the LIB_PART for each SCH_COMPONENT found in the ful...
static const KICAD_T DraggableItems[]
A scan list for all draggable schematic items.
void TestDanglingEnds()
SCH_TEXT * GetLabel(const wxPoint &aPosition, int aAccuracy=0)
Return a label item located at aPosition.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
std::vector< SCH_SCREEN * > m_screens
Definition: sch_screen.h:526
virtual bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item.
Class GRID_TYPE is for grid arrays.
Definition: base_screen.h:45
void Append(SCH_ITEM *aItem)
Definition: sch_screen.h:162
void ClearAnnotation()
Clear the annotation for all components in the hierarchy.
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:188
#define max(a, b)
Definition: auxiliary.h:86
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
Definition: sch_screen.cpp:912
void SetCurItem(SCH_ITEM *aItem)
Sets the currently selected object, m_CurrentItem.
Definition: sch_screen.h:204
size_t i
Definition: json11.cpp:597
#define ENDPOINT
Definition: base_struct.h:120
virtual bool IsSelectStateChanged(const wxRect &aRect)
Function IsSelectStateChanged checks if the selection state of an item inside aRect has changed.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:70
wxPoint GetPosition() const override
Function GetPosition.
void Collect(SCH_ITEM *aBoard, const KICAD_T aScanList[])
Function Collect scans a BOARD_ITEM using this class's Inspector method, which does the collection.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
The common library.
PICKED_ITEMS_LIST & GetItems()
SCH_LINE * GetWireOrBus(const wxPoint &aPosition)
Return a wire or bus item located at aPosition.
Definition: sch_screen.cpp:952
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:257
unsigned GetCount() const
int m_NumberOfScreens
Definition: base_screen.h:217
const wxPoint & GetTextPos() const
Definition: eda_text.h:237
void SetOwnership(bool Iown)
Function SetOwnership controls whether the list owns the objects and is responsible for deleteing the...
Definition: dlist.h:119
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath)
Clear the annotation for the components in aSheetPath on the screen.
Definition: sch_screen.cpp:681
int ReplaceDuplicateTimeStamps()
Test all sheet and component objects in the schematic for duplicate time stamps and replaces them as ...
void ReplaceWires(DLIST< SCH_ITEM > &aWireList)
Replace all of the wires, buses, and junctions in the screen with aWireList.
Definition: sch_screen.cpp:259
int GetConvert() const
SCH_SCREEN * GetFirst()
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:563
virtual void ClearUndoORRedoList(UNDO_REDO_CONTAINER &aList, int aItemCount=-1) override
Free the undo or redo list from aList element.
Definition: sch_screen.cpp:548
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:324
int SetGrid(const wxRealPoint &size)
set the current grid size m_Grid.
Definition of the NETLIST_OBJECT class.
bool CheckIfOnDrawList(SCH_ITEM *st)
Definition: sch_screen.cpp:207
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
const LIB_ID & GetLibId() const
wxPoint GetPinPhysicalPosition(const LIB_PIN *Pin) const
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nickames into aLibNicknames.
static bool SortByTimeStamp(const EDA_ITEM *item1, const EDA_ITEM *item2)
Sort a list of schematic items by time stamp and type.
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Implementation of the label properties dialog.
bool IsConnected(const wxPoint &aPoint) const
Function IsConnected tests the item to see if it is connected to aPoint.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:523
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
std::vector< double > m_ZoomList
standard zoom (i.e. scale) coefficients.
Definition: base_screen.h:219
wxArrayString m_clientSheetPathList
the list of scheet paths sharing this screen used in some annotation calculations to update alternate...
Definition: sch_screen.h:83
void IncRefCount()
Definition: sch_screen.cpp:133
const wxSize GetSize() const
Definition: eda_rect.h:101
static void UpdateAllPinCaches(const SCH_COLLECTOR &aComponents)
Update the pin cache for all components in aComponents.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:206
bool empty() const
Definition: utf8.h:108
virtual wxString GetClass() const override
Function GetClass returns the class name.
Definition: sch_screen.h:121
#define STARTPOINT
Definition: base_struct.h:119
virtual void SetText(const wxString &aText)
Definition: eda_text.h:154
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
void PushItem(ITEM_PICKER &aItem)
Function PushItem adds aItem to the list of items.
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
bool SetComponentFootprint(SCH_SHEET_PATH *aSheetPath, const wxString &aReference, const wxString &aFootPrint, bool aSetVisible)
Search this screen for a symbol with aReference and set the footprint field to aFootPrint if found.
SCH_LINE * GetBus(const wxPoint &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T)
Definition: sch_screen.h:468
SCH_ITEM * GetDrawItems() const
Definition: sch_screen.h:160
wxPoint GetEndPoint() const
Definition: sch_line.h:80