KiCad PCB EDA Suite
sch_screen.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 1992-2023 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
27#include <wx/filefn.h>
28
29#include <eda_item.h>
30#include <id.h>
31#include <string_utils.h>
32#include <kiway.h>
33#include <plotters/plotter.h>
34#include <project.h>
35#include <reporter.h>
36#include <sch_draw_panel.h>
37#include <sch_edit_frame.h>
38#include <sch_item.h>
39
40#include <symbol_library.h>
41#include <connection_graph.h>
42#include <lib_item.h>
43#include <lib_pin.h>
44#include <lib_shape.h>
45#include <sch_symbol.h>
46#include <sch_junction.h>
47#include <sch_line.h>
48#include <sch_marker.h>
49#include <sch_sheet.h>
50#include <sch_sheet_pin.h>
51#include <sch_text.h>
52#include <schematic.h>
53#include <symbol_lib_table.h>
54#include <tool/common_tools.h>
55#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
56#include <sim/sim_value.h> //
57#include <locale_io.h>
58
59#include <algorithm>
60
61// TODO(JE) Debugging only
62#include <profile.h>
63#include "sch_bus_entry.h"
64#include "sim/sim_model_ideal.h"
65
67 BASE_SCREEN( aParent, SCH_SCREEN_T ),
68 m_fileFormatVersionAtLoad( 0 ),
69 m_paper( wxT( "A4" ) ),
70 m_isReadOnly( false ),
71 m_fileExists( false )
72{
74 m_refCount = 0;
75 m_zoomInitialized = false;
76 m_LastZoomLevel = 1.0;
77
78 // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
79 m_Center = false;
80
82}
83
84
86{
89}
90
91
93{
94 wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
95 wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
96
97 return static_cast<SCHEMATIC*>( GetParent() );
98}
99
100
102{
103 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : m_libSymbols )
104 delete libSymbol.second;
105
106 m_libSymbols.clear();
107}
108
109
110void SCH_SCREEN::SetFileName( const wxString& aFileName )
111{
112 wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
113
114 m_fileName = aFileName;
115}
116
117
119{
120 m_refCount++;
121}
122
123
125{
126 wxCHECK_RET( m_refCount != 0, wxT( "Screen reference count already zero. Bad programmer!" ) );
127 m_refCount--;
128}
129
130
131bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
132{
133 EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
134
135 return sheets.begin() != sheets.end();
136}
137
138
139bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
140{
141 return aItem && SCH_SCREEN_T == aItem->Type();
142}
143
144
146{
147 if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
148 {
149 // Ensure the item can reach the SCHEMATIC through this screen
150 aItem->SetParent( this );
151
152 if( aItem->Type() == SCH_SYMBOL_T )
153 {
154 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
155
156 if( symbol->GetLibSymbolRef() )
157 {
158 symbol->GetLibSymbolRef()->GetDrawItems().sort();
159
160 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
161
162 if( it == m_libSymbols.end() || !it->second )
163 {
165 new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
166 }
167 else
168 {
169 // The original library symbol may have changed since the last time
170 // it was added to the schematic. If it has changed, then a new name
171 // must be created for the library symbol list to prevent all of the
172 // other schematic symbols referencing that library symbol from changing.
173 LIB_SYMBOL* foundSymbol = it->second;
174
175 foundSymbol->GetDrawItems().sort();
176
177 if( *foundSymbol != *symbol->GetLibSymbolRef() )
178 {
179 int cnt = 1;
180 wxString newName;
181
182 newName.Printf( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
183 cnt );
184
185 while( m_libSymbols.find( newName ) != m_libSymbols.end() )
186 {
187 cnt += 1;
188 newName.Printf( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
189 cnt );
190 }
191
192 // Update the schematic symbol library link as this symbol only exists
193 // in the schematic.
194 symbol->SetSchSymbolLibraryName( newName );
195
196 LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
197 LIB_ID newLibId( wxEmptyString, newName );
198
199 newLibSymbol->SetLibId( newLibId );
200 newLibSymbol->SetName( newName );
201 symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
202 m_libSymbols[newName] = newLibSymbol;
203 }
204 }
205 }
206 }
207
208 m_rtree.insert( aItem );
210 }
211}
212
213
215{
216 wxCHECK_RET( aScreen, "Invalid screen object." );
217
218 // No need to descend the hierarchy. Once the top level screen is copied, all of its
219 // children are copied as well.
220 for( SCH_ITEM* aItem : aScreen->m_rtree )
221 Append( aItem );
222
223 aScreen->Clear( false );
224}
225
226
227void SCH_SCREEN::Clear( bool aFree )
228{
229 if( aFree )
230 {
231 FreeDrawList();
233 }
234 else
235 {
236 m_rtree.clear();
237 }
238
239 // Clear the project settings
241
242 m_titles.Clear();
243}
244
245
247{
248 // We don't know which order we will encounter dependent items (e.g. pins or fields), so
249 // we store the items to be deleted until we've fully cleared the tree before deleting
250 std::vector<SCH_ITEM*> delete_list;
251
252 std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
253 []( SCH_ITEM* aItem )
254 {
255 return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
256 } );
257
258 m_rtree.clear();
259
260 for( SCH_ITEM* item : delete_list )
261 delete item;
262}
263
264
266{
267 if( Remove( aItem ) )
268 Append( aItem );
269}
270
271
273{
274 bool retv = m_rtree.remove( aItem );
275
276 // Check if the library symbol for the removed schematic symbol is still required.
277 if( retv && aItem->Type() == SCH_SYMBOL_T )
278 {
279 SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
280
281 bool removeUnusedLibSymbol = true;
282
283 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
284 {
285 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
286
287 if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
288 {
289 removeUnusedLibSymbol = false;
290 break;
291 }
292 }
293
294 if( removeUnusedLibSymbol )
295 {
296 auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
297
298 if( it != m_libSymbols.end() )
299 {
300 delete it->second;
301 m_libSymbols.erase( it );
302 }
303 }
304 }
305
306 return retv;
307}
308
309
311{
312 wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
313
314 // Markers are not saved in the file, no need to flag as modified.
315 // TODO: Maybe we should have a listing somewhere of items that aren't saved?
316 if( aItem->Type() != SCH_MARKER_T )
318
319 Remove( aItem );
320
321 if( aItem->Type() == SCH_SHEET_PIN_T )
322 {
323 // This structure is attached to a sheet, get the parent sheet object.
324 SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
325 SCH_SHEET* sheet = sheetPin->GetParent();
326 wxCHECK_RET( sheet, wxT( "Sheet pin parent not properly set, bad programmer!" ) );
327 sheet->RemovePin( sheetPin );
328 return;
329 }
330
331 delete aItem;
332}
333
334
335bool SCH_SCREEN::CheckIfOnDrawList( const SCH_ITEM* aItem ) const
336{
337 return m_rtree.contains( aItem, true );
338}
339
340
341SCH_ITEM* SCH_SCREEN::GetItem( const VECTOR2I& aPosition, int aAccuracy, KICAD_T aType ) const
342{
343 BOX2I bbox;
344 bbox.SetOrigin( aPosition );
345 bbox.Inflate( aAccuracy );
346
347 for( SCH_ITEM* item : Items().Overlapping( aType, bbox ) )
348 {
349 if( item->HitTest( aPosition, aAccuracy ) )
350 return item;
351 }
352
353 return nullptr;
354}
355
356
357std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecondPass )
358{
359#define PROCESSED CANDIDATE // Don't use SKIP_STRUCT; IsConnected() returns false if it's set.
360
361 std::set<SCH_ITEM*> retval;
362 std::stack<SCH_LINE*> to_search;
363
364 wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
365
366 to_search.push( aSegment );
367
368 while( !to_search.empty() )
369 {
370 SCH_ITEM* item = to_search.top();
371 to_search.pop();
372
373 if( item->HasFlag( PROCESSED ) )
374 continue;
375
376 item->SetFlags( PROCESSED );
377
378 for( SCH_ITEM* candidate : Items().Overlapping( SCH_LINE_T, item->GetBoundingBox() ) )
379 {
380 SCH_LINE* line = static_cast<SCH_LINE*>( candidate );
381
382 if( line->HasFlag( PROCESSED ) )
383 continue;
384
385 // Skip connecting lines on different layers (e.g. buses)
386 if( item->GetLayer() != line->GetLayer() )
387 continue;
388
389 for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } )
390 {
391 if( item->IsConnected( pt ) )
392 {
393 SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
394 SCH_ITEM* pin = GetItem( pt, 0, SCH_PIN_T );
395
396 if( item->IsSelected() && aSecondPass )
397 {
398 if( junction )
399 retval.insert( junction );
400
401 retval.insert( line );
402 to_search.push( line );
403 }
404 else if( !junction && !pin )
405 {
406 retval.insert( line );
407 to_search.push( line );
408 }
409
410 break;
411 }
412 }
413 }
414 }
415
416 for( SCH_ITEM* item : Items() )
417 item->ClearTempFlags();
418
419 return retval;
420}
421
422
423bool SCH_SCREEN::IsJunction( const VECTOR2I& aPosition ) const
424{
425 bool hasExplicitJunction;
426 bool hasBusEntry;
427 bool isJunction = doIsJunction( aPosition, false, &hasExplicitJunction, &hasBusEntry );
428
429 return isJunction;
430}
431
432
433bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
434{
435 bool hasExplicitJunction;
436 bool hasBusEntry;
437 bool isJunction = doIsJunction( aPosition, false, &hasExplicitJunction, &hasBusEntry );
438
439 return isJunction && !hasBusEntry;
440}
441
442
443bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
444{
445 bool hasExplicitJunction;
446 bool hasBusEntry;
447 bool isJunction = doIsJunction( aPosition, false, &hasExplicitJunction, &hasBusEntry );
448
449 return isJunction && !hasBusEntry && !hasExplicitJunction;
450}
451
453 TEXT_SPIN_STYLE aDefaultOrientation,
454 const SCH_SHEET_PATH* aSheet ) const
455{
456 auto ret = aDefaultOrientation;
457 for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
458 {
459 if( item->GetEditFlags() & STRUCT_DELETED )
460 continue;
461
462 switch( item->Type() )
463 {
465 {
466 auto busEntry = static_cast<const SCH_BUS_WIRE_ENTRY*>( item );
467 if( busEntry->m_connected_bus_item )
468 {
469 // bus connected, take the bus direction into consideration ony if it is
470 // vertical or horizontal
471 auto bus = static_cast<const SCH_LINE*>( busEntry->m_connected_bus_item );
472 if( bus->Angle().AsDegrees() == 90.0 )
473 {
474 // bus is vertical -> label shall be horizontal and
475 // shall be placed to the side where the bus entry is
476 if( aPosition.x < bus->GetPosition().x )
478 else if( aPosition.x > bus->GetPosition().x )
480 }
481 else if( bus->Angle().AsDegrees() == 0.0 )
482 {
483 // bus is horizontal -> label shall be vertical and
484 // shall be placed to the side where the bus entry is
485 if( aPosition.y < bus->GetPosition().y )
487 else if( aPosition.y > bus->GetPosition().y )
489 }
490 }
491 }
492 break;
493
494 case SCH_LINE_T:
495 {
496 auto line = static_cast<const SCH_LINE*>( item );
497 // line angles goes between -90 and 90 degrees, but normalize
498 auto angle = line->Angle().Normalize90().AsDegrees();
499
500 if( -45 < angle && angle <= 45 )
501 {
502 if( line->GetStartPoint().x <= line->GetEndPoint().x )
503 {
504 ret = line->GetEndPoint() == aPosition ? TEXT_SPIN_STYLE::RIGHT
506 }
507 else
508 {
509 ret = line->GetEndPoint() == aPosition ? TEXT_SPIN_STYLE::LEFT
511 }
512 }
513 else
514 {
515 if( line->GetStartPoint().y <= line->GetEndPoint().y )
516 {
517 ret = line->GetEndPoint() == aPosition ? TEXT_SPIN_STYLE::BOTTOM
519 }
520 else
521 {
522 ret = line->GetEndPoint() == aPosition ? TEXT_SPIN_STYLE::UP
524 }
525 }
526 }
527 break;
528
529 case SCH_SYMBOL_T:
530 {
531 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
532
533 for( SCH_PIN* pin : symbol->GetPins( aSheet ) )
534 {
535 if( pin->GetPosition() == aPosition )
536 {
537 if( pin->GetOrientation() == PIN_RIGHT )
538 {
540 }
541 else if( pin->GetOrientation() == PIN_LEFT )
542 {
544 }
545 else if( pin->GetOrientation() == PIN_UP )
546 {
548 }
549 else if( pin->GetOrientation() == PIN_DOWN )
550 {
552 }
553
554 switch( static_cast<SYMBOL_ORIENTATION_T>(
555 symbol->GetOrientation() & ( ~( SYM_MIRROR_X | SYM_MIRROR_Y ) ) ) )
556 {
558 case SYM_ORIENT_90:
559 if( ret == TEXT_SPIN_STYLE::UP )
561 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
563 else if( ret == TEXT_SPIN_STYLE::LEFT )
565 else if( ret == TEXT_SPIN_STYLE::RIGHT )
567
568 if( symbol->GetOrientation() & SYM_MIRROR_X )
569 {
570 if( ret == TEXT_SPIN_STYLE::UP )
572 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
574 }
575
576 if( symbol->GetOrientation() & SYM_MIRROR_Y )
577 {
578 if( ret == TEXT_SPIN_STYLE::LEFT )
580 else if( ret == TEXT_SPIN_STYLE::RIGHT )
582 }
583 break;
585 case SYM_ORIENT_270:
586 if( ret == TEXT_SPIN_STYLE::UP )
588 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
590 else if( ret == TEXT_SPIN_STYLE::LEFT )
592 else if( ret == TEXT_SPIN_STYLE::RIGHT )
594
595 if( symbol->GetOrientation() & SYM_MIRROR_X )
596 {
597 if( ret == TEXT_SPIN_STYLE::UP )
599 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
601 }
602
603 if( symbol->GetOrientation() & SYM_MIRROR_Y )
604 {
605 if( ret == TEXT_SPIN_STYLE::LEFT )
607 else if( ret == TEXT_SPIN_STYLE::RIGHT )
609 }
610 break;
611 case SYM_ORIENT_180:
612 if( ret == TEXT_SPIN_STYLE::UP )
614 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
616 else if( ret == TEXT_SPIN_STYLE::LEFT )
618 else if( ret == TEXT_SPIN_STYLE::RIGHT )
620
621 if( symbol->GetOrientation() & SYM_MIRROR_X )
622 {
623 if( ret == TEXT_SPIN_STYLE::UP )
625 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
627 }
628
629 if( symbol->GetOrientation() & SYM_MIRROR_Y )
630 {
631 if( ret == TEXT_SPIN_STYLE::LEFT )
633 else if( ret == TEXT_SPIN_STYLE::RIGHT )
635 }
636 break;
637 case SYM_ORIENT_0:
638 case SYM_NORMAL:
639 default:
640 if( symbol->GetOrientation() & SYM_MIRROR_X )
641 {
642 if( ret == TEXT_SPIN_STYLE::UP )
644 else if( ret == TEXT_SPIN_STYLE::BOTTOM )
646 }
647
648 if( symbol->GetOrientation() & SYM_MIRROR_Y )
649 {
650 if( ret == TEXT_SPIN_STYLE::LEFT )
652 else if( ret == TEXT_SPIN_STYLE::RIGHT )
654 }
655 break;
656 }
657
658 break;
659 }
660 }
661 }
662 break;
663 default: break;
664 }
665 }
666 return ret;
667}
668
669
671{
672 bool hasExplicitJunction;
673 bool hasBusEntry;
674 bool isJunction = doIsJunction( aPosition, true, &hasExplicitJunction, &hasBusEntry );
675
676 return isJunction && !hasBusEntry;
677}
678
679
680
681bool SCH_SCREEN::doIsJunction( const VECTOR2I& aPosition, bool aBreakCrossings,
682 bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const
683{
684 enum layers { WIRES = 0, BUSES };
685
686 *aHasExplicitJunctionDot = false;
687 *aHasBusEntry = false;
688
689 bool breakLines[ 2 ] = { false };
690 std::unordered_set<int> exitAngles[ 2 ];
691 std::vector<const SCH_LINE*> midPointLines[ 2 ];
692
693 // A pin at 90° still shouldn't match a line at 90° so just give pins unique numbers
694 int uniqueAngle = 10000;
695
696 for( const SCH_ITEM* item : Items().Overlapping( aPosition ) )
697 {
698 if( item->GetEditFlags() & STRUCT_DELETED )
699 continue;
700
701 switch( item->Type() )
702 {
703 case SCH_JUNCTION_T:
704 if( item->HitTest( aPosition, -1 ) )
705 *aHasExplicitJunctionDot = true;
706
707 break;
708
709 case SCH_LINE_T:
710 {
711 const SCH_LINE* line = static_cast<const SCH_LINE*>( item );
712 int layer;
713
714 if( line->GetStartPoint() == line->GetEndPoint() )
715 break;
716 else if( line->GetLayer() == LAYER_WIRE )
717 layer = WIRES;
718 else if( line->GetLayer() == LAYER_BUS )
719 layer = BUSES;
720 else
721 break;
722
723 if( line->IsConnected( aPosition ) )
724 {
725 breakLines[ layer ] = true;
726 exitAngles[ layer ].insert( line->GetAngleFrom( aPosition ) );
727 }
728 else if( line->HitTest( aPosition, -1 ) )
729 {
730 if( aBreakCrossings )
731 breakLines[ layer ] = true;
732
733 // Defer any line midpoints until we know whether or not we're breaking them
734 midPointLines[ layer ].push_back( line );
735 }
736 }
737 break;
738
740 if( item->IsConnected( aPosition ) )
741 {
742 breakLines[ BUSES ] = true;
743 exitAngles[ BUSES ].insert( uniqueAngle++ );
744 breakLines[ WIRES ] = true;
745 exitAngles[ WIRES ].insert( uniqueAngle++ );
746 *aHasBusEntry = true;
747 }
748
749 break;
750
751 case SCH_SYMBOL_T:
752 case SCH_SHEET_T:
753 if( item->IsConnected( aPosition ) )
754 {
755 breakLines[ WIRES ] = true;
756 exitAngles[ WIRES ].insert( uniqueAngle++ );
757 }
758
759 break;
760
761 default:
762 break;
763 }
764 }
765
766 for( int layer : { WIRES, BUSES } )
767 {
768 if( breakLines[ layer ] )
769 {
770 for( const SCH_LINE* line : midPointLines[ layer ] )
771 {
772 exitAngles[ layer ].insert( line->GetAngleFrom( aPosition ) );
773 exitAngles[ layer ].insert( line->GetReverseAngleFrom( aPosition ) );
774 }
775 }
776 }
777
778 return exitAngles[ WIRES ].size() >= 3 || exitAngles[ BUSES ].size() >= 3;
779}
780
781
782bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
783{
784 wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
785 wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
786
787 SCH_SHEET_PIN* sheetPin;
788 SCH_LABEL_BASE* label;
789
790 switch( aLayer )
791 {
792 case LAYER_BUS:
793 if( GetBus( aPosition ) )
794 return true;
795
796 sheetPin = GetSheetPin( aPosition );
797
798 if( sheetPin && sheetPin->IsConnected( aPosition ) )
799 return true;
800
801 label = GetLabel( aPosition );
802
803 if( label && label->IsConnected( aPosition ) )
804 return true;
805
806 break;
807
808 case LAYER_NOTES:
809 if( GetLine( aPosition ) )
810 return true;
811
812 break;
813
814 case LAYER_WIRE:
815 if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T) )
816 return true;
817
818 if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
819 return true;
820
821 if( GetPin( aPosition, nullptr, true ) )
822 return true;
823
824 if( GetWire( aPosition ) )
825 return true;
826
827 label = GetLabel( aPosition, 1 );
828
829 if( label && label->IsConnected( aPosition ) )
830 return true;
831
832 sheetPin = GetSheetPin( aPosition );
833
834 if( sheetPin && sheetPin->IsConnected( aPosition ) )
835 return true;
836
837 break;
838
839 default:
840 break;
841 }
842
843 return false;
844}
845
846
848{
849 wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
850
851 wxString msg;
852 std::unique_ptr< LIB_SYMBOL > libSymbol;
853 std::vector<SCH_SYMBOL*> symbols;
854 SYMBOL_LIB_TABLE* libs = Schematic()->Prj().SchSymbolLibTable();
855
856 // This will be a nullptr if an s-expression schematic is loaded.
857 SYMBOL_LIBS* legacyLibs = Schematic()->Prj().SchLibs();
858
859 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
860 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
861
862 // Remove them from the R tree. There bounding box size may change.
863 for( SCH_SYMBOL* symbol : symbols )
864 Remove( symbol );
865
866 // Clear all existing symbol links.
868
869 for( SCH_SYMBOL* symbol : symbols )
870 {
871 LIB_SYMBOL* tmp = nullptr;
872 libSymbol.reset();
873
874 // If the symbol is already in the internal library, map the symbol to it.
875 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
876
877 if( ( it != m_libSymbols.end() ) )
878 {
879 if( aReporter )
880 {
881 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
882 symbol->GetField( REFERENCE_FIELD )->GetText(),
883 symbol->GetField( VALUE_FIELD )->GetText(),
884 UnescapeString( symbol->GetLibId().Format() ) );
885 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
886 }
887
888 // Internal library symbols are already flattened so just make a copy.
889 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
890 continue;
891 }
892
893 if( !symbol->GetLibId().IsValid() )
894 {
895 if( aReporter )
896 {
897 msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
898 "Unable to link library symbol." ),
899 UnescapeString( symbol->GetLibId().Format() ) );
900 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
901 }
902
903 continue;
904 }
905
906 // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
907 // is not found in the table so check if the library still exists in the table
908 // before attempting to load the symbol.
909 if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
910 {
911 if( aReporter )
912 {
913 msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
914 "available. Unable to link library symbol." ),
915 symbol->GetLibId().GetLibNickname().wx_str() );
916 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
917 }
918
919 continue;
920 }
921
922 if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
923 {
924 try
925 {
926 tmp = libs->LoadSymbol( symbol->GetLibId() );
927 }
928 catch( const IO_ERROR& ioe )
929 {
930 if( aReporter )
931 {
932 msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
933 UnescapeString( symbol->GetLibId().Format() ) );
934 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
935 }
936 }
937 }
938
939 if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
940 {
941 SYMBOL_LIB& legacyCacheLib = legacyLibs->back();
942
943 // It better be the cache library.
944 wxCHECK2( legacyCacheLib.IsCache(), continue );
945
946 wxString id = symbol->GetLibId().Format();
947
948 id.Replace( ':', '_' );
949
950 if( aReporter )
951 {
952 msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
953 symbol->GetField( REFERENCE_FIELD )->GetText(),
954 symbol->GetField( VALUE_FIELD )->GetText(),
955 UnescapeString( id ) );
956 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
957 }
958
959 tmp = legacyCacheLib.FindSymbol( id );
960 }
961
962 if( tmp )
963 {
964 // We want a full symbol not just the top level child symbol.
965 libSymbol = tmp->Flatten();
966 libSymbol->SetParent();
967
968 m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
969 new LIB_SYMBOL( *libSymbol.get() ) } );
970
971 if( aReporter )
972 {
973 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
974 symbol->GetField( REFERENCE_FIELD )->GetText(),
975 symbol->GetField( VALUE_FIELD )->GetText(),
976 UnescapeString( symbol->GetLibId().Format() ) );
977 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
978 }
979 }
980 else
981 {
982 if( aReporter )
983 {
984 msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
985 symbol->GetField( REFERENCE_FIELD )->GetText(),
986 symbol->GetField( VALUE_FIELD )->GetText() );
987 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
988 }
989 }
990
991 symbol->SetLibSymbol( libSymbol.release() );
992 }
993
994 // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
995 // item with the new bbox
996 for( SCH_SYMBOL* symbol : symbols )
997 Append( symbol );
998}
999
1000
1002{
1003 std::vector<SCH_SYMBOL*> symbols;
1004
1005 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1006 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
1007
1008 for( SCH_SYMBOL* symbol : symbols )
1009 {
1010 // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
1011 m_rtree.remove( symbol );
1012
1013 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
1014
1015 LIB_SYMBOL* libSymbol = nullptr;
1016
1017 if( it != m_libSymbols.end() )
1018 libSymbol = new LIB_SYMBOL( *it->second );
1019
1020 symbol->SetLibSymbol( libSymbol );
1021
1022 m_rtree.insert( symbol );
1023 }
1024}
1025
1026
1028{
1029 for( SCH_ITEM* item : Items() )
1030 item->SetConnectivityDirty( true );
1031}
1032
1033
1034void SCH_SCREEN::Print( const RENDER_SETTINGS* aSettings )
1035{
1036 // Ensure links are up to date, even if a library was reloaded for some reason:
1037 std::vector<SCH_ITEM*> junctions;
1038 std::vector<SCH_ITEM*> bitmaps;
1039 std::vector<SCH_ITEM*> other;
1040
1041 for( SCH_ITEM* item : Items() )
1042 {
1043 if( item->IsMoving() )
1044 continue;
1045
1046 if( item->Type() == SCH_JUNCTION_T )
1047 junctions.push_back( item );
1048 else if( item->Type() == SCH_BITMAP_T )
1049 bitmaps.push_back( item );
1050 else
1051 other.push_back( item );
1052 }
1053
1055 std::stable_sort( other.begin(), other.end(),
1056 []( const SCH_ITEM* a, const SCH_ITEM* b )
1057 {
1058 if( a->Type() == b->Type() )
1059 return a->GetLayer() > b->GetLayer();
1060
1061 return a->Type() < b->Type();
1062 } );
1063
1064 for( SCH_ITEM* item : bitmaps )
1065 item->Print( aSettings, VECTOR2I( 0, 0 ) );
1066
1067 for( SCH_ITEM* item : other )
1068 item->PrintBackground( aSettings, VECTOR2I( 0, 0 ) );
1069
1070 for( SCH_ITEM* item : other )
1071 item->Print( aSettings, VECTOR2I( 0, 0 ) );
1072
1073 for( SCH_ITEM* item : junctions )
1074 item->Print( aSettings, VECTOR2I( 0, 0 ) );
1075}
1076
1077
1078void SCH_SCREEN::Plot( PLOTTER* aPlotter ) const
1079{
1080 // Ensure links are up to date, even if a library was reloaded for some reason:
1081 std::vector<SCH_ITEM*> junctions;
1082 std::vector<SCH_ITEM*> bitmaps;
1083 std::vector<SCH_SYMBOL*> symbols;
1084 std::vector<SCH_ITEM*> other;
1085
1086 for( SCH_ITEM* item : Items() )
1087 {
1088 if( item->IsMoving() )
1089 continue;
1090
1091 if( item->Type() == SCH_JUNCTION_T )
1092 junctions.push_back( item );
1093 else if( item->Type() == SCH_BITMAP_T )
1094 bitmaps.push_back( item );
1095 else
1096 other.push_back( item );
1097
1098 // Where the symbols overlap each other, we need to plot the text items a second
1099 // time to get them on top of the overlapping element. This collection is in addition
1100 // to the symbols already collected in `other`
1101 if( item->Type() == SCH_SYMBOL_T )
1102 {
1103 for( SCH_ITEM* sym : m_rtree.Overlapping( SCH_SYMBOL_T, item->GetBoundingBox() ) )
1104 {
1105 if( sym != item )
1106 {
1107 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
1108 break;
1109 }
1110 }
1111 }
1112 }
1113
1115 std::sort( other.begin(), other.end(),
1116 []( const SCH_ITEM* a, const SCH_ITEM* b )
1117 {
1118 if( a->Type() == b->Type() )
1119 return a->GetLayer() > b->GetLayer();
1120
1121 return a->Type() > b->Type();
1122 } );
1123
1124 int defaultPenWidth = aPlotter->RenderSettings()->GetDefaultPenWidth();
1125 constexpr bool background = true;
1126
1127 // Bitmaps are drawn first to ensure they are in the background
1128 // This is particularly important for the wxPostscriptDC (used in *nix printers) as
1129 // the bitmap PS command clears the screen
1130 for( const SCH_ITEM* item : bitmaps )
1131 {
1132 aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
1133 item->Plot( aPlotter, background );
1134 }
1135
1136 for( const SCH_ITEM* item : other )
1137 {
1138 aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
1139 item->Plot( aPlotter, background );
1140 }
1141
1142 for( const SCH_ITEM* item : other )
1143 {
1144 aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
1145 item->Plot( aPlotter, !background );
1146 }
1147
1148 // After plotting the symbols as a group above (in `other`), we need to overplot the pins
1149 // and symbols to ensure that they are always visible
1150 for( const SCH_SYMBOL* sym :symbols )
1151 {
1152 aPlotter->SetCurrentLineWidth( std::max( sym->GetPenWidth(), defaultPenWidth ) );
1153
1154 for( SCH_FIELD field : sym->GetFields() )
1155 field.Plot( aPlotter, false );
1156
1157 sym->PlotPins( aPlotter );
1158
1159 if( sym->GetDNP() )
1160 sym->PlotDNP( aPlotter );
1161 }
1162
1163 for( const SCH_ITEM* item : junctions )
1164 {
1165 aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
1166 item->Plot( aPlotter, !background );
1167 }
1168}
1169
1170
1172{
1173 for( SCH_ITEM* item : Items() )
1174 item->ClearTempFlags();
1175}
1176
1177
1178LIB_PIN* SCH_SCREEN::GetPin( const VECTOR2I& aPosition, SCH_SYMBOL** aSymbol,
1179 bool aEndPointOnly ) const
1180{
1181 SCH_SYMBOL* candidate = nullptr;
1182 LIB_PIN* pin = nullptr;
1183
1184 for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
1185 {
1186 candidate = static_cast<SCH_SYMBOL*>( item );
1187
1188 if( aEndPointOnly )
1189 {
1190 pin = nullptr;
1191
1192 if( !candidate->GetLibSymbolRef() )
1193 continue;
1194
1195 std::vector<LIB_PIN*> pins;
1196 candidate->GetLibPins( pins );
1197
1198 for( LIB_PIN* test_pin : pins )
1199 {
1200 if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
1201 {
1202 pin = test_pin;
1203 break;
1204 }
1205 }
1206
1207 if( pin )
1208 break;
1209 }
1210 else
1211 {
1212 pin = (LIB_PIN*) candidate->GetDrawItem( aPosition, LIB_PIN_T );
1213
1214 if( pin )
1215 break;
1216 }
1217 }
1218
1219 if( pin && aSymbol )
1220 *aSymbol = candidate;
1221
1222 return pin;
1223}
1224
1225
1227{
1228 SCH_SHEET_PIN* sheetPin = nullptr;
1229
1230 for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
1231 {
1232 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1233
1234 sheetPin = sheet->GetPin( aPosition );
1235
1236 if( sheetPin )
1237 break;
1238 }
1239
1240 return sheetPin;
1241}
1242
1243
1244size_t SCH_SCREEN::CountConnectedItems( const VECTOR2I& aPos, bool aTestJunctions ) const
1245{
1246 size_t count = 0;
1247
1248 for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
1249 {
1250 if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
1251 count++;
1252 }
1253
1254 return count;
1255}
1256
1257
1258void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1259{
1260
1261 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1262 {
1263 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1264
1265 symbol->ClearAnnotation( aSheetPath, aResetPrefix );
1266 }
1267}
1268
1269
1271{
1272 if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
1273 return;
1274
1275 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1276 {
1277 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1278
1279 // Add (when not existing) all sheet path entries
1280 for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1281 symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1282 }
1283}
1284
1285
1286void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1287{
1288 for( SCH_ITEM* item : Items() )
1289 {
1290 if( item->IsType( { SCH_SYMBOL_T, SCH_SHEET_T, SCH_LABEL_LOCATE_ANY_T } ) )
1291 aItems->push_back( item );
1292 }
1293}
1294
1295
1296void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1297{
1298 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1299 aItems->push_back( item );
1300
1301 std::sort( aItems->begin(), aItems->end(),
1302 []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1303 {
1304 if( a->GetPosition().x == b->GetPosition().x )
1305 {
1306 // Ensure deterministic sort
1307 if( a->GetPosition().y == b->GetPosition().y )
1308 return a->m_Uuid < b->m_Uuid;
1309
1310 return a->GetPosition().y < b->GetPosition().y;
1311 }
1312 else
1313 {
1314 return a->GetPosition().x < b->GetPosition().x;
1315 }
1316 } );
1317}
1318
1319
1321 std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1322{
1323 std::vector<DANGLING_END_ITEM> endPoints;
1324
1325 for( SCH_ITEM* item : Items() )
1326 {
1327 if( item->IsConnectable() )
1328 {
1329 endPoints.clear();
1330
1331 for( SCH_ITEM* overlapping : Items().Overlapping( item->GetBoundingBox() ) )
1332 overlapping->GetEndPoints( endPoints );
1333
1334 if( item->UpdateDanglingState( endPoints, aPath ) )
1335 {
1336 if( aChangedHandler )
1337 (*aChangedHandler)( item );
1338 }
1339 }
1340 }
1341}
1342
1343
1344SCH_LINE* SCH_SCREEN::GetLine( const VECTOR2I& aPosition, int aAccuracy, int aLayer,
1345 SCH_LINE_TEST_T aSearchType ) const
1346{
1347 // an accuracy of 0 had problems with rounding errors; use at least 1
1348 aAccuracy = std::max( aAccuracy, 1 );
1349
1350 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1351 {
1352 if( item->Type() != SCH_LINE_T )
1353 continue;
1354
1355 if( item->GetLayer() != aLayer )
1356 continue;
1357
1358 if( !item->HitTest( aPosition, aAccuracy ) )
1359 continue;
1360
1361 switch( aSearchType )
1362 {
1363 case ENTIRE_LENGTH_T:
1364 return (SCH_LINE*) item;
1365
1367 if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1368 return (SCH_LINE*) item;
1369 break;
1370
1371 case END_POINTS_ONLY_T:
1372 if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1373 return (SCH_LINE*) item;
1374 }
1375 }
1376
1377 return nullptr;
1378}
1379
1380
1381std::vector<SCH_LINE*> SCH_SCREEN::GetBusesAndWires( const VECTOR2I& aPosition,
1382 bool aIgnoreEndpoints ) const
1383{
1384 std::vector<SCH_LINE*> retVal;
1385
1386 for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, aPosition ) )
1387 {
1388 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1389 {
1390 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
1391
1392 if( aIgnoreEndpoints && wire->IsEndPoint( aPosition ) )
1393 continue;
1394
1395 if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), aPosition ) )
1396 retVal.push_back( wire );
1397 }
1398 }
1399
1400 return retVal;
1401}
1402
1403
1404std::vector<VECTOR2I> SCH_SCREEN::GetConnections() const
1405{
1406 std::vector<VECTOR2I> retval;
1407
1408 for( SCH_ITEM* item : Items() )
1409 {
1410 // Avoid items that are changing
1411 if( !( item->GetEditFlags() & ( IS_MOVING | IS_DELETED ) ) )
1412 {
1413 std::vector<VECTOR2I> pts = item->GetConnectionPoints();
1414 retval.insert( retval.end(), pts.begin(), pts.end() );
1415 }
1416 }
1417
1418 // We always have some overlapping connection points. Drop duplicates here
1419 std::sort( retval.begin(), retval.end(),
1420 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1421 {
1422 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1423 } );
1424 retval.erase( std::unique( retval.begin(), retval.end() ), retval.end() );
1425
1426 return retval;
1427}
1428
1429
1430std::vector<VECTOR2I> SCH_SCREEN::GetNeededJunctions( const std::deque<EDA_ITEM*>& aItems ) const
1431{
1432 std::vector<VECTOR2I> pts;
1433 std::vector<VECTOR2I> connections = GetConnections();
1434
1435 for( const EDA_ITEM* edaItem : aItems )
1436 {
1437 const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( edaItem );
1438
1439 if( !item || !item->IsConnectable() )
1440 continue;
1441
1442 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
1443 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
1444
1445 // If the item is a line, we also add any connection points from the rest of the schematic
1446 // that terminate on the line after it is moved.
1447 if( item->Type() == SCH_LINE_T )
1448 {
1449 SCH_LINE* line = (SCH_LINE*) item;
1450
1451 for( const VECTOR2I& pt : connections )
1452 {
1453 if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
1454 pts.push_back( pt );
1455 }
1456 }
1457 }
1458
1459 // We always have some overlapping connection points. Drop duplicates here
1460 std::sort( pts.begin(), pts.end(),
1461 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1462 {
1463 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1464 } );
1465
1466 pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1467
1468 // We only want the needed junction points, remove all the others
1469 pts.erase( std::remove_if( pts.begin(), pts.end(),
1470 [this]( const VECTOR2I& a ) -> bool
1471 {
1472 return !IsExplicitJunctionNeeded( a );
1473 } ),
1474 pts.end() );
1475
1476 return pts;
1477}
1478
1479
1480SCH_LABEL_BASE* SCH_SCREEN::GetLabel( const VECTOR2I& aPosition, int aAccuracy ) const
1481{
1482 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1483 {
1484 switch( item->Type() )
1485 {
1486 case SCH_LABEL_T:
1487 case SCH_GLOBAL_LABEL_T:
1488 case SCH_HIER_LABEL_T:
1490 if( item->HitTest( aPosition, aAccuracy ) )
1491 return static_cast<SCH_LABEL_BASE*>( item );
1492
1493 break;
1494
1495 default:
1496 ;
1497 }
1498 }
1499
1500 return nullptr;
1501}
1502
1503
1505{
1506 wxCHECK( aLibSymbol, /* void */ );
1507
1508 wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1509
1510 auto it = m_libSymbols.find( libSymbolName );
1511
1512 if( it != m_libSymbols.end() )
1513 {
1514 delete it->second;
1515 m_libSymbols.erase( it );
1516 }
1517
1518 m_libSymbols[libSymbolName] = aLibSymbol;
1519}
1520
1521
1522void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1523{
1524 m_aliases.insert( aAlias );
1525}
1526
1527
1529{
1530 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1531 {
1532 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1533
1534 // Add missing value and footprint instance data for legacy schematics.
1535 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstanceReferences() )
1536 {
1537 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1538 instance.m_Unit );
1539 }
1540 }
1541}
1542
1543
1544#if defined(DEBUG)
1545void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1546{
1547 // for now, make it look like XML, expand on this later.
1548 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1549
1550 for( const SCH_ITEM* item : Items() )
1551 item->Show( nestLevel + 1, os );
1552
1553 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1554}
1555#endif
1556
1557
1559{
1560 m_index = 0;
1561 buildScreenList( aSheet );
1562}
1563
1564
1566{
1567}
1568
1569
1571{
1572 m_index = 0;
1573
1574 if( m_screens.size() > 0 )
1575 return m_screens[0];
1576
1577 return nullptr;
1578}
1579
1580
1582{
1583 if( m_index < m_screens.size() )
1584 m_index++;
1585
1586 return GetScreen( m_index );
1587}
1588
1589
1590SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1591{
1592 if( aIndex < m_screens.size() )
1593 return m_screens[ aIndex ];
1594
1595 return nullptr;
1596}
1597
1598
1599SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1600{
1601 if( aIndex < m_sheets.size() )
1602 return m_sheets[ aIndex ];
1603
1604 return nullptr;
1605}
1606
1607
1609{
1610 if( aScreen == nullptr )
1611 return;
1612
1613 for( const SCH_SCREEN* screen : m_screens )
1614 {
1615 if( screen == aScreen )
1616 return;
1617 }
1618
1619 m_screens.push_back( aScreen );
1620 m_sheets.push_back( aSheet );
1621}
1622
1623
1625{
1626 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1627 {
1628 SCH_SCREEN* screen = aSheet->GetScreen();
1629
1630 wxCHECK_RET( screen, "No screen for aSheet" );
1631
1632 addScreenToList( screen, aSheet );
1633
1634 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1635 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1636 }
1637}
1638
1639
1641{
1642 SCH_SCREEN* first = GetFirst();
1643
1644 if( !first )
1645 return;
1646
1647 SCHEMATIC* sch = first->Schematic();
1648
1649 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1650
1651 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1652 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1653 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1654
1655 // Search for new sheet paths, not existing in aInitialSheetPathList
1656 // and existing in sheetpathList
1657 for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1658 {
1659 bool path_exists = false;
1660
1661 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1662 {
1663 if( existing_sheetpath.Path() == sheetpath.Path() )
1664 {
1665 path_exists = true;
1666 break;
1667 }
1668 }
1669
1670 if( !path_exists )
1671 {
1672 // A new sheet path is found: clear the annotation corresponding to this new path:
1673 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1674
1675 // Clear annotation and create the AR for this path, if not exists,
1676 // when the screen is shared by sheet paths.
1677 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1678 // reference default value and takes the latest displayed value
1679 curr_screen->EnsureAlternateReferencesExist();
1680 curr_screen->ClearAnnotation( &sheetpath, false );
1681 }
1682 }
1683}
1684
1685
1687{
1688 std::vector<SCH_ITEM*> items;
1689 int count = 0;
1690
1691 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1692 {
1693 return a->m_Uuid < b->m_Uuid;
1694 };
1695
1696 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1697
1698 for( SCH_SCREEN* screen : m_screens )
1699 screen->GetHierarchicalItems( &items );
1700
1701 if( items.size() < 2 )
1702 return 0;
1703
1704 for( EDA_ITEM* item : items )
1705 {
1706 if( !unique_stamps.insert( item ).second )
1707 {
1708 // Reset to fully random UUID. This may lose reference, but better to be
1709 // deterministic about it rather than to have duplicate UUIDs with random
1710 // side-effects.
1711 const_cast<KIID&>( item->m_Uuid ) = KIID();
1712 count++;
1713
1714 // @todo If the item is a sheet, we need to decend the heirarchy from the sheet
1715 // and repace all instances of the changed UUID in sheet paths. Otherwise,
1716 // all instance paths with the sheet's UUID will get clobbered.
1717 }
1718 }
1719
1720 return count;
1721}
1722
1723
1725{
1726 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1727 {
1728 for( SCH_ITEM* item : screen->Items() )
1729 item->ClearEditFlags();
1730 }
1731}
1732
1733
1735{
1736 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1737 {
1738 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1739 {
1740 if( item == aMarker )
1741 {
1742 screen->DeleteItem( item );
1743 return;
1744 }
1745 }
1746 }
1747}
1748
1749
1750void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::TYPEMARKER aMarkerType, int aErrorCode,
1751 bool aIncludeExclusions )
1752{
1753 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1754 {
1755 std::vector<SCH_ITEM*> markers;
1756
1757 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1758 {
1759 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1760 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1761
1762 if( marker->GetMarkerType() == aMarkerType
1763 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1764 && ( !marker->IsExcluded() || aIncludeExclusions ) )
1765 {
1766 markers.push_back( item );
1767 }
1768 }
1769
1770 for( SCH_ITEM* marker : markers )
1771 screen->DeleteItem( marker );
1772 }
1773}
1774
1775
1777 bool aIncludeExclusions )
1778{
1779 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1780}
1781
1782
1784{
1785 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1786 screen->UpdateSymbolLinks( aReporter );
1787
1788 SCH_SCREEN* first = GetFirst();
1789
1790 if( !first )
1791 return;
1792
1793 SCHEMATIC* sch = first->Schematic();
1794
1795 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1796
1797 SCH_SHEET_LIST sheets = sch->GetSheets();
1798
1799 // All of the library symbols have been replaced with copies so the connection graph
1800 // pointers are stale.
1801 if( sch->ConnectionGraph() )
1802 sch->ConnectionGraph()->Recalculate( sheets, true );
1803}
1804
1805
1807{
1808 bool has_symbols = false;
1809
1810 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1811 {
1812 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1813 {
1814 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1815 has_symbols = true;
1816
1817 if( !symbol->GetLibId().GetLibNickname().empty() )
1818 return false;
1819 }
1820 }
1821
1822 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
1823 return has_symbols ? true : false;
1824}
1825
1826
1827size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
1828{
1829 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1830 {
1831 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1832 {
1833 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1834 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
1835
1836 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
1837 aLibNicknames.Add( nickname );
1838 }
1839 }
1840
1841 return aLibNicknames.GetCount();
1842}
1843
1844
1845int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
1846{
1847 SCH_SCREEN* screen;
1848 int cnt = 0;
1849
1850 for( screen = GetFirst(); screen; screen = GetNext() )
1851 {
1852 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1853 {
1854 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1855
1856 if( symbol->GetLibId().GetLibNickname() != aFrom )
1857 continue;
1858
1859 LIB_ID id = symbol->GetLibId();
1860 id.SetLibNickname( aTo );
1861 symbol->SetLibId( id );
1862 cnt++;
1863 }
1864 }
1865
1866 return cnt;
1867}
1868
1869
1870bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
1871{
1872 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1873 {
1874 if( screen->GetFileName() == aSchematicFileName )
1875 return true;
1876 }
1877
1878 return false;
1879}
1880
1881
1882bool SCH_SCREENS::CanCauseCaseSensitivityIssue( const wxString& aSchematicFileName ) const
1883{
1884 wxString lhsLower;
1885 wxString rhsLower;
1886 wxFileName lhs;
1887 wxFileName rhs = aSchematicFileName;
1888
1889 wxCHECK( rhs.IsAbsolute(), false );
1890
1891 for( const SCH_SCREEN* screen : m_screens )
1892 {
1893 lhs = screen->GetFileName();
1894
1895 if( lhs.GetPath() != rhs.GetPath() )
1896 continue;
1897
1898 lhsLower = lhs.GetFullName().Lower();
1899 rhsLower = rhs.GetFullName().Lower();
1900
1901 if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
1902 return true;
1903 }
1904
1905 return false;
1906}
1907
1908
1910{
1911 SCH_SCREEN* first = GetFirst();
1912
1913 if( !first )
1914 return;
1915
1916 SCHEMATIC* sch = first->Schematic();
1917
1918 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
1919
1920 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1921 curr_screen->GetClientSheetPaths().clear();
1922
1923 for( SCH_SHEET_PATH& sheetpath : sch->GetSheets() )
1924 {
1925 SCH_SCREEN* used_screen = sheetpath.LastScreen();
1926
1927 // Search for the used_screen in list and add this unique sheet path:
1928 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
1929 {
1930 if( used_screen == curr_screen )
1931 {
1932 curr_screen->GetClientSheetPaths().push_back( sheetpath );
1933 break;
1934 }
1935 }
1936 }
1937}
1938
1939
1941{
1942 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1943 screen->SetLegacySymbolInstanceData();
1944}
1945
1946
1948{
1949 LOCALE_IO toggle;
1950
1951 // V6 schematics may specify model names in Value fields, which we don't do in V7.
1952 // Migrate by adding an equivalent model for these symbols.
1953
1954 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1955 {
1956 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1957 SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( *symbol, &Schematic()->Prj() );
1958 }
1959}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
Handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:41
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
Definition: base_screen.h:119
bool m_Center
Center on screen.
Definition: base_screen.h:96
int m_pageCount
The number of BASE_SCREEN objects in this design.
Definition: base_screen.h:111
void InitDataPoints(const wxSize &aPageSizeInternalUnits)
Definition: base_screen.cpp:46
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
void SetOrigin(const Vec &pos)
Definition: box2.h:202
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr)
Updates the connection graph for the given list of sheets.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:139
const KIID m_Uuid
Definition: eda_item.h:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
bool IsSelected() const
Definition: eda_item.h:106
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EDA_ITEM * GetParent() const
Definition: eda_item.h:99
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:143
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:243
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition: sch_rtree.h:78
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition: sch_rtree.h:59
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition: sch_rtree.h:125
iterator end()
Returns a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:285
iterator begin()
Returns a read/write iterator that points to the first element in the EE_RTREE N.B.
Definition: sch_rtree.h:276
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
void clear()
Remove all items from the RTree.
Definition: sch_rtree.h:111
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
int GetDefaultPenWidth() const
Definition: kiid.h:48
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
UTF8 Format() const
Definition: lib_id.cpp:117
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition: lib_id.h:112
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Define a library symbol object.
Definition: lib_symbol.h:99
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:508
LIB_ID GetLibId() const override
Definition: lib_symbol.h:141
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:456
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:142
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:437
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
bool IsExcluded() const
Definition: marker_base.h:97
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:105
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:95
void sort()
Definition: multivector.h:247
const wxSize GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:162
Base plotter engine class.
Definition: plotter.h:110
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:141
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:99
Holds all the data relating to one schematic.
Definition: schematic.h:61
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:130
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:86
SCH_SHEET & Root() const
Definition: schematic.h:91
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:76
Class for a wire to bus entry.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
virtual bool IsConnectable() const
Definition: sch_item.h:349
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:246
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:137
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:364
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: sch_line.cpp:776
int GetAngleFrom(const VECTOR2I &aPoint) const
Definition: sch_line.cpp:401
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
bool IsEndPoint(const VECTOR2I &aPoint) const
Definition: sch_line.h:92
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:638
SCH_SCREEN * GetNext()
unsigned int m_index
Definition: sch_screen.h:773
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:772
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
void DeleteMarker(SCH_MARKER *aMarker)
Delete a specific marker.
void buildScreenList(SCH_SHEET *aSheet)
void DeleteMarkers(enum MARKER_BASE::TYPEMARKER aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
SCH_SCREEN * GetFirst()
int ChangeSymbolLibNickname(const wxString &aFrom, const wxString &aTo)
Change all of the symbol library nicknames.
SCH_SCREENS(SCH_SHEET *aSheet)
void BuildClientSheetPathList()
built the list of sheet paths sharing a screen for each screen in use
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the symbols inside new sheetpaths when a complex hierarchy is modified and n...
bool CanCauseCaseSensitivityIssue(const wxString &aSchematicFileName) const
Check aSchematicFileName for a potential file name case sensitivity issue.
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
void ClearEditFlags()
SCH_SHEET * GetSheet(unsigned int aIndex) const
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
void DeleteAllMarkers(enum MARKER_BASE::TYPEMARKER aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
std::vector< SCH_SCREEN * > m_screens
Definition: sch_screen.h:771
bool HasSchematic(const wxString &aSchematicFileName)
Check if one of the schematics in the list of screens is aSchematicFileName.
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nicknames into aLibNicknames.
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
void addScreenToList(SCH_SCREEN *aScreen, SCH_SHEET *aSheet)
std::map< wxString, LIB_SYMBOL * > m_libSymbols
Library symbols required for this schematic.
Definition: sch_screen.h:599
void ClearDrawingState()
Clear the state flags of all the items in the screen.
SCH_LINE * GetLine(const VECTOR2I &aPosition, int aAccuracy=0, int aLayer=LAYER_NOTES, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Return a line item located at aPosition.
void Update(SCH_ITEM *aItem)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:265
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
bool HasItems(KICAD_T aItemType) const
Definition: sch_screen.cpp:131
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:227
LIB_PIN * GetPin(const VECTOR2I &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
bool Remove(SCH_ITEM *aItem)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:272
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition: sch_screen.h:178
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project SYMB...
Definition: sch_screen.cpp:847
SCH_LINE * GetWire(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:427
int m_refCount
Definition: sch_screen.h:567
TITLE_BLOCK m_titles
Definition: sch_screen.h:580
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
void EnsureAlternateReferencesExist()
For screens shared by many sheetpaths (complex hierarchies): to be able to clear or modify any refere...
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
int m_modification_sync
Definition: sch_screen.h:584
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition: sch_screen.h:562
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicates that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:433
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
void Print(const RENDER_SETTINGS *aSettings)
Print all the items in the screen to aDC.
void DecRefCount()
Definition: sch_screen.cpp:124
std::set< SCH_ITEM * > MarkConnections(SCH_LINE *aSegment, bool aSecondPass)
Return all wires and junctions connected to aSegment which are not connected any symbol pin.
Definition: sch_screen.cpp:357
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:341
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:670
void clearLibSymbols()
Definition: sch_screen.cpp:101
wxString m_fileName
Definition: sch_screen.h:565
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:782
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void IncRefCount()
Definition: sch_screen.cpp:118
std::set< std::shared_ptr< BUS_ALIAS > > m_aliases
List of bus aliases stored in this screen.
Definition: sch_screen.h:596
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:110
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_screen.cpp:139
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition: sch_screen.h:433
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
Definition: sch_screen.cpp:66
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:92
EE_RTREE m_rtree
Definition: sch_screen.h:582
void GetHierarchicalItems(std::vector< SCH_ITEM * > *aItems) const
Add all schematic sheet and symbol objects in the screen to aItems.
bool IsExplicitJunctionNeeded(const VECTOR2I &aPosition) const
Indicates that a junction dot is necessary at the given location, and does not yet exist.
Definition: sch_screen.cpp:443
SCH_SHEET_PIN * GetSheetPin(const VECTOR2I &aPosition) const
Test the screen if aPosition is a sheet label object.
void Plot(PLOTTER *aPlotter) const
Plot all the schematic objects to aPlotter.
void FreeDrawList()
Free all the items from the schematic associated with the screen.
Definition: sch_screen.cpp:246
virtual wxString GetClass() const override
Return the class name.
Definition: sch_screen.h:123
void SetConnectivityDirty()
bool m_zoomInitialized
Definition: sch_screen.h:587
std::vector< VECTOR2I > GetNeededJunctions(const std::deque< EDA_ITEM * > &aItems) const
Return the unique set of points belonging to aItems where a junction is needed.
PAGE_INFO m_paper
Definition: sch_screen.h:579
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:423
TEXT_SPIN_STYLE GetLabelOrientationForPoint(const VECTOR2I &aPosition, TEXT_SPIN_STYLE aDefaultOrientation, const SCH_SHEET_PATH *aSheet) const
Definition: sch_screen.cpp:452
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:335
std::vector< VECTOR2I > GetConnections() const
Collect a unique list of all possible connection points in the schematic.
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear the annotation for the symbols in aSheetPath on the screen.
bool doIsJunction(const VECTOR2I &aPosition, bool aBreakCrossings, bool *aHasExplicitJunctionDot, bool *aHasBusEntry) const
Definition: sch_screen.cpp:681
size_t CountConnectedItems(const VECTOR2I &aPos, bool aTestJunctions) const
void MigrateSimModels()
Migrate any symbols having V6 simulation models to their V7 equivalents.
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:145
void DeleteItem(SCH_ITEM *aItem)
Removes aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:310
SCH_LABEL_BASE * GetLabel(const VECTOR2I &aPosition, int aAccuracy=0) const
Return a label item located at aPosition.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:578
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:376
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:106
Schematic symbol object.
Definition: sch_symbol.h:81
void GetLibPins(std::vector< LIB_PIN * > &aPinsList) const
Populate a vector with all the pins from the library object.
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:280
LIB_ITEM * GetDrawItem(const VECTOR2I &aPosition, KICAD_T aType=TYPE_NOT_INIT)
Return the symbol library item at aPosition that is part of this symbol.
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstanceReferences()
Definition: sch_symbol.h:140
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:290
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
VECTOR2I GetPinPhysicalPosition(const LIB_PIN *Pin) const
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
Definition: sch_symbol.cpp:550
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:188
int GetOrientation() const
Get the display symbol orientation.
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:175
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:192
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:299
A collection of SYMBOL_LIB objects.
int GetLibraryCount()
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
Object used to load, save, search, and otherwise manipulate symbol library files.
bool IsCache() const
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
void Clear()
Definition: title_block.h:113
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:71
bool empty() const
Definition: utf8.h:103
wxString wx_str() const
Definition: utf8.cpp:46
#define _(s)
#define IS_DELETED
#define STRUCT_DELETED
flag indication structures to be erased
#define IS_MOVING
Item being moved.
@ ERCE_UNSPECIFIED
Definition: erc_settings.h:38
PROJECT & Prj()
Definition: kicad.cpp:573
@ LAYER_WIRE
Definition: layer_ids.h:344
@ LAYER_NOTES
Definition: layer_ids.h:358
@ LAYER_BUS
Definition: layer_ids.h:345
@ PIN_LEFT
Definition: lib_pin.h:46
@ PIN_RIGHT
Definition: lib_pin.h:45
@ PIN_UP
Definition: lib_pin.h:47
@ PIN_DOWN
Definition: lib_pin.h:48
boost::ptr_vector< WIRE > WIRES
Definition: specctra.h:2983
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
SYMBOL_ORIENTATION_T
enum used in RotationMiroir()
@ SYM_ORIENT_270
@ SYM_ROTATE_CLOCKWISE
@ SYM_ROTATE_COUNTERCLOCKWISE
@ SYM_MIRROR_Y
@ SYM_ORIENT_180
@ SYM_MIRROR_X
@ SYM_NORMAL
@ SYM_ORIENT_90
@ SYM_ORIENT_0
#define PROCESSED
SCH_LINE_TEST_T
Definition: sch_screen.h:71
@ ENTIRE_LENGTH_T
Definition: sch_screen.h:72
@ EXCLUDE_END_POINTS_T
Definition: sch_screen.h:74
@ END_POINTS_ONLY_T
Definition: sch_screen.h:73
wxString UnescapeString(const wxString &aSource)
const double IU_PER_MILS
Definition: base_units.h:78
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition: sch_rtree.h:192
iterator begin()
Definition: sch_rtree.h:222
iterator end()
Definition: sch_rtree.h:227
A simple container for schematic symbol instance information.
Definition for symbol library class.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
bool IsPointOnSegment(const VECTOR2I &aSegStart, const VECTOR2I &aSegEnd, const VECTOR2I &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
Definition: trigo.cpp:42
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_LINE_T
Definition: typeinfo.h:146
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:154
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ SCH_SHEET_T
Definition: typeinfo.h:158
@ SCH_MARKER_T
Definition: typeinfo.h:141
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ LIB_PIN_T
Definition: typeinfo.h:202
@ SCH_SCREEN_T
Definition: typeinfo.h:186
@ SCHEMATIC_T
Definition: typeinfo.h:188
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:157
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:144
@ SCH_BITMAP_T
Definition: typeinfo.h:148
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152
@ SCH_JUNCTION_T
Definition: typeinfo.h:142
@ SCH_PIN_T
Definition: typeinfo.h:159
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618