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