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 The 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 <stack>
28#include <wx/filefn.h>
29#include <wx/log.h>
30
31#include <eda_item.h>
32#include <id.h>
33#include <string_utils.h>
34#include <kiway.h>
35#include <plotters/plotter.h>
36#include <sch_plotter.h>
37#include <project.h>
38#include <project_sch.h>
39#include <reporter.h>
40#include <trace_helpers.h>
41#include <sch_edit_frame.h>
42#include <sch_item.h>
43
44#include <symbol_library.h>
45#include <connection_graph.h>
46#include <junction_helpers.h>
47#include <sch_pin.h>
48#include <sch_symbol.h>
49#include <sch_group.h>
50#include <sch_junction.h>
51#include <sch_line.h>
52#include <sch_marker.h>
53#include <sch_sheet.h>
54#include <sch_sheet_pin.h>
55#include <sch_text.h>
56#include <schematic.h>
58#include <symbol_lib_table.h>
59#include <tool/common_tools.h>
60#include <sim/sim_model.h> // For V6 to V7 simulation model migration.
61#include <locale_io.h>
62
63#include <algorithm>
64
65// TODO(JE) Debugging only
66#include <core/profile.h>
67#include "sch_bus_entry.h"
68
74static const wxChar DanglingProfileMask[] = wxT( "DANGLING_PROFILE" );
75
76
78 BASE_SCREEN( aParent, SCH_SCREEN_T ),
79 m_fileFormatVersionAtLoad( 0 ),
80 m_paper( wxT( "A4" ) ),
81 m_isReadOnly( false ),
82 m_fileExists( false )
83{
85 m_refCount = 0;
86 m_zoomInitialized = false;
87 m_LastZoomLevel = 1.0;
88
89 // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
90 m_Center = false;
91
93}
94
95
97{
100}
101
102
104{
105 wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
106 wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
107
108 return static_cast<SCHEMATIC*>( GetParent() );
109}
110
111
113{
114 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : m_libSymbols )
115 delete libSymbol.second;
116
117 m_libSymbols.clear();
118}
119
120
121void SCH_SCREEN::SetFileName( const wxString& aFileName )
122{
123 wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
124
125 m_fileName = aFileName;
126}
127
128
130{
131 m_refCount++;
132}
133
134
136{
137 wxCHECK_RET( m_refCount != 0, wxT( "Screen reference count already zero. Bad programmer!" ) );
138 m_refCount--;
139}
140
141
142bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
143{
144 EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
145
146 return sheets.begin() != sheets.end();
147}
148
149
150bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
151{
152 return aItem && SCH_SCREEN_T == aItem->Type();
153}
154
155
156void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
157{
158 if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
159 {
160 // Ensure the item can reach the SCHEMATIC through this screen
161 aItem->SetParent( this );
162
163 if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
164 {
165 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
166
167 if( symbol->GetLibSymbolRef() )
168 {
169 symbol->GetLibSymbolRef()->GetDrawItems().sort();
170
171 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
172
173 if( it == m_libSymbols.end() || !it->second )
174 {
176 new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
177 }
178 else
179 {
180 // The original library symbol may have changed since the last time
181 // it was added to the schematic. If it has changed, then a new name
182 // must be created for the library symbol list to prevent all of the
183 // other schematic symbols referencing that library symbol from changing.
184 LIB_SYMBOL* foundSymbol = it->second;
185
186 foundSymbol->GetDrawItems().sort();
187
188 if( *foundSymbol != *symbol->GetLibSymbolRef() )
189 {
190 wxString newName;
191 std::vector<wxString> matches;
192
193 getLibSymbolNameMatches( *symbol, matches );
194 foundSymbol = nullptr;
195
196 for( const wxString& libSymbolName : matches )
197 {
198 it = m_libSymbols.find( libSymbolName );
199
200 if( it == m_libSymbols.end() )
201 continue;
202
203 foundSymbol = it->second;
204
205 wxCHECK2( foundSymbol, continue );
206
207 wxString tmp = symbol->GetLibSymbolRef()->GetName();
208
209 // Temporarily update the new symbol library symbol name so it
210 // doesn't fail on the name comparison below.
211 symbol->GetLibSymbolRef()->SetName( foundSymbol->GetName() );
212
213 if( *foundSymbol == *symbol->GetLibSymbolRef() )
214 {
215 newName = libSymbolName;
216 symbol->GetLibSymbolRef()->SetName( tmp );
217 break;
218 }
219
220 symbol->GetLibSymbolRef()->SetName( tmp );
221 foundSymbol = nullptr;
222 }
223
224 if( !foundSymbol )
225 {
226 int cnt = 1;
227
228 newName.Printf( wxT( "%s_%d" ),
230 cnt );
231
232 while( m_libSymbols.find( newName ) != m_libSymbols.end() )
233 {
234 cnt += 1;
235 newName.Printf( wxT( "%s_%d" ),
237 cnt );
238 }
239 }
240
241 // Update the schematic symbol library link as this symbol only exists
242 // in the schematic.
243 symbol->SetSchSymbolLibraryName( newName );
244
245 if( !foundSymbol )
246 {
247 // Update the schematic symbol library link as this symbol does not
248 // exist in any symbol library.
249 LIB_ID newLibId( wxEmptyString, newName );
250 LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
251
252 newLibSymbol->SetLibId( newLibId );
253 newLibSymbol->SetName( newName );
254 symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
255 m_libSymbols[newName] = newLibSymbol;
256 }
257 }
258 }
259 }
260 }
261
262 m_rtree.insert( aItem );
264 }
265}
266
267
269{
270 wxCHECK_RET( aScreen, "Invalid screen object." );
271
272 // No need to descend the hierarchy. Once the top level screen is copied, all of its
273 // children are copied as well.
274 for( SCH_ITEM* aItem : aScreen->m_rtree )
275 Append( aItem );
276
277 aScreen->Clear( false );
278}
279
280
281void SCH_SCREEN::Clear( bool aFree )
282{
283 if( aFree )
284 {
285 FreeDrawList();
287 }
288 else
289 {
290 m_rtree.clear();
291 }
292
293 // Clear the project settings
295
296 m_titles.Clear();
297}
298
299
301{
302 // We don't know which order we will encounter dependent items (e.g. pins or fields), so
303 // we store the items to be deleted until we've fully cleared the tree before deleting
304 std::vector<SCH_ITEM*> delete_list;
305
306 std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
307 []( SCH_ITEM* aItem )
308 {
309 // Untangle group parents before doing any deleting
310 if( aItem->Type() == SCH_GROUP_T )
311 {
312 for( EDA_ITEM* item : static_cast<SCH_GROUP*>(aItem)->GetItems() )
313 item->SetParentGroup( nullptr );
314 }
315
316 return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
317 } );
318
319 m_rtree.clear();
320
321 for( SCH_ITEM* item : delete_list )
322 delete item;
323}
324
325
326void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
327{
328 if( Remove( aItem, aUpdateLibSymbol ) )
329 Append( aItem, aUpdateLibSymbol );
330}
331
332
333bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
334{
335 bool retv = m_rtree.remove( aItem );
336
337 // Check if the library symbol for the removed schematic symbol is still required.
338 if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
339 {
340 SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
341
342 bool removeUnusedLibSymbol = true;
343
344 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
345 {
346 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
347
348 if( removedSymbol->GetSchSymbolLibraryName() == symbol->GetSchSymbolLibraryName() )
349 {
350 removeUnusedLibSymbol = false;
351 break;
352 }
353 }
354
355 if( removeUnusedLibSymbol )
356 {
357 auto it = m_libSymbols.find( removedSymbol->GetSchSymbolLibraryName() );
358
359 if( it != m_libSymbols.end() )
360 {
361 delete it->second;
362 m_libSymbols.erase( it );
363 }
364 }
365 }
366
367 return retv;
368}
369
370
372{
373 wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
374
375 // Markers are not saved in the file, no need to flag as modified.
376 // TODO: Maybe we should have a listing somewhere of items that aren't saved?
377 if( aItem->Type() != SCH_MARKER_T )
379
380 Remove( aItem );
381
382 if( aItem->Type() == SCH_SHEET_PIN_T )
383 {
384 // This structure is attached to a sheet, get the parent sheet object.
385 SCH_SHEET_PIN* sheetPin = (SCH_SHEET_PIN*) aItem;
386 SCH_SHEET* sheet = sheetPin->GetParent();
387 wxCHECK_RET( sheet, wxT( "Sheet pin parent not properly set, bad programmer!" ) );
388 sheet->RemovePin( sheetPin );
389 return;
390 }
391
392 delete aItem;
393}
394
395
396bool SCH_SCREEN::CheckIfOnDrawList( const SCH_ITEM* aItem ) const
397{
398 return m_rtree.contains( aItem, true );
399}
400
401
402SCH_ITEM* SCH_SCREEN::GetItem( const VECTOR2I& aPosition, int aAccuracy, KICAD_T aType ) const
403{
404 BOX2I bbox;
405 bbox.SetOrigin( aPosition );
406 bbox.Inflate( aAccuracy );
407
408 for( SCH_ITEM* item : Items().Overlapping( aType, bbox ) )
409 {
410 if( item->HitTest( aPosition, aAccuracy ) )
411 return item;
412 }
413
414 return nullptr;
415}
416
417
418std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecondPass )
419{
420#define PROCESSED CANDIDATE // Don't use SKIP_STRUCT; IsConnected() returns false if it's set.
421
422 std::set<SCH_ITEM*> retval;
423 std::stack<SCH_LINE*> to_search;
424
425 wxCHECK_MSG( aSegment && aSegment->Type() == SCH_LINE_T, retval, wxT( "Invalid pointer." ) );
426
427 to_search.push( aSegment );
428
429 while( !to_search.empty() )
430 {
431 SCH_ITEM* item = to_search.top();
432 to_search.pop();
433
434 if( item->HasFlag( PROCESSED ) )
435 continue;
436
437 item->SetFlags( PROCESSED );
438
439 for( SCH_ITEM* candidate : Items().Overlapping( SCH_LINE_T, item->GetBoundingBox() ) )
440 {
441 SCH_LINE* line = static_cast<SCH_LINE*>( candidate );
442
443 if( line->HasFlag( PROCESSED ) )
444 continue;
445
446 // Skip connecting lines on different layers (e.g. buses)
447 if( item->GetLayer() != line->GetLayer() )
448 continue;
449
450 for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } )
451 {
452 if( item->IsConnected( pt ) )
453 {
454 SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
455 SCH_ITEM* pin = GetItem( pt, 0, SCH_PIN_T );
456
457 if( item->IsSelected() && aSecondPass )
458 {
459 if( junction )
460 retval.insert( junction );
461
462 retval.insert( line );
463 to_search.push( line );
464 }
465 else if( !junction && !pin )
466 {
467 retval.insert( line );
468 to_search.push( line );
469 }
470
471 break;
472 }
473 else if( line->GetLayer() == LAYER_NOTES && item->GetLayer() == LAYER_NOTES )
474 {
475 retval.insert( line );
476 to_search.push( line );
477 }
478 }
479 }
480 }
481
482 for( SCH_ITEM* item : Items() )
483 item->ClearTempFlags();
484
485 return retval;
486}
487
488
489bool SCH_SCREEN::IsJunction( const VECTOR2I& aPosition ) const
490{
492 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
493 return info.isJunction;
494}
495
496
497bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
498{
500 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
501
502 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires );
503}
504
505
506bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
507{
509 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
510
511 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires )
512 && !info.hasExplicitJunctionDot;
513}
514
515
517{
519 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, true );
520
521 return info.isJunction && (!info.hasBusEntry || info.hasBusEntryToMultipleWires );
522}
523
524
526 SPIN_STYLE aDefaultOrientation,
527 const SCH_SHEET_PATH* aSheet ) const
528{
529 auto ret = aDefaultOrientation;
530
531 for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
532 {
533 if( item->GetEditFlags() & STRUCT_DELETED )
534 continue;
535
536 switch( item->Type() )
537 {
539 {
540 auto busEntry = static_cast<const SCH_BUS_WIRE_ENTRY*>( item );
541 if( busEntry->m_connected_bus_item )
542 {
543 // bus connected, take the bus direction into consideration only if it is
544 // vertical or horizontal
545 auto bus = static_cast<const SCH_LINE*>( busEntry->m_connected_bus_item );
546 if( bus->Angle().AsDegrees() == 90.0 )
547 {
548 // bus is vertical -> label shall be horizontal and
549 // shall be placed to the side where the bus entry is
550 if( aPosition.x < bus->GetPosition().x )
551 ret = SPIN_STYLE::LEFT;
552 else if( aPosition.x > bus->GetPosition().x )
553 ret = SPIN_STYLE::RIGHT;
554 }
555 else if( bus->Angle().AsDegrees() == 0.0 )
556 {
557 // bus is horizontal -> label shall be vertical and
558 // shall be placed to the side where the bus entry is
559 if( aPosition.y < bus->GetPosition().y )
560 ret = SPIN_STYLE::UP;
561 else if( aPosition.y > bus->GetPosition().y )
562 ret = SPIN_STYLE::BOTTOM;
563 }
564 }
565 }
566 break;
567
568 case SCH_LINE_T:
569 {
570 auto line = static_cast<const SCH_LINE*>( item );
571 // line angles goes between -90 and 90 degrees, but normalize
572 auto angle = line->Angle().Normalize90().AsDegrees();
573
574 if( -45 < angle && angle <= 45 )
575 {
576 if( line->GetStartPoint().x <= line->GetEndPoint().x )
577 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::RIGHT : SPIN_STYLE::LEFT;
578 else
579 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::LEFT : SPIN_STYLE::RIGHT;
580 }
581 else
582 {
583 if( line->GetStartPoint().y <= line->GetEndPoint().y )
584 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::BOTTOM : SPIN_STYLE::UP;
585 else
586 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::UP : SPIN_STYLE::BOTTOM;
587 }
588 }
589 break;
590
591 case SCH_SYMBOL_T:
592 {
593 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
594
595 for( SCH_PIN* pin : symbol->GetPins( aSheet ) )
596 {
597 if( pin->GetPosition() == aPosition )
598 {
599 ret = GetPinSpinStyle( *pin, *symbol );
600 break;
601 }
602 }
603 }
604 break;
605
606 default: break;
607 }
608 }
609
610 return ret;
611}
612
613
614bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
615{
616 wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
617 wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
618
619 SCH_SHEET_PIN* sheetPin;
620 SCH_LABEL_BASE* label;
621
622 switch( aLayer )
623 {
624 case LAYER_BUS:
625 if( GetBus( aPosition ) )
626 return true;
627
628 sheetPin = GetSheetPin( aPosition );
629
630 if( sheetPin && sheetPin->IsConnected( aPosition ) )
631 return true;
632
633 label = GetLabel( aPosition );
634
635 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
636 return true;
637
638 break;
639
640 case LAYER_NOTES:
641 if( GetLine( aPosition ) )
642 return true;
643
644 break;
645
646 case LAYER_WIRE:
647 if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T ) )
648 return true;
649
650 if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
651 return true;
652
653 if( GetPin( aPosition, nullptr, true ) )
654 return true;
655
656 if( GetWire( aPosition ) )
657 return true;
658
659 label = GetLabel( aPosition, 1 );
660
661 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
662 return true;
663
664 sheetPin = GetSheetPin( aPosition );
665
666 if( sheetPin && sheetPin->IsConnected( aPosition ) )
667 return true;
668
669 break;
670
671 default:
672 break;
673 }
674
675 return false;
676}
677
678
680{
681 wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
682
683 wxString msg;
684 std::unique_ptr< LIB_SYMBOL > libSymbol;
685 std::vector<SCH_SYMBOL*> symbols;
687
688 // This will be a nullptr if an s-expression schematic is loaded.
689 SYMBOL_LIBS* legacyLibs = PROJECT_SCH::SchLibs( &Schematic()->Prj() );
690
691 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
692 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
693
694 // Remove them from the R tree. There bounding box size may change.
695 for( SCH_SYMBOL* symbol : symbols )
696 Remove( symbol );
697
698 // Clear all existing symbol links.
700
701 for( SCH_SYMBOL* symbol : symbols )
702 {
703 LIB_SYMBOL* tmp = nullptr;
704 libSymbol.reset();
705
706 // If the symbol is already in the internal library, map the symbol to it.
707 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
708
709 if( ( it != m_libSymbols.end() ) )
710 {
711 if( aReporter )
712 {
713 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
714 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
715 symbol->GetField( FIELD_T::VALUE )->GetText(),
716 UnescapeString( symbol->GetLibId().Format() ) );
717 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
718 }
719
720 // Internal library symbols are already flattened so just make a copy.
721 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
722 continue;
723 }
724
725 if( !symbol->GetLibId().IsValid() )
726 {
727 if( aReporter )
728 {
729 msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
730 "Unable to link library symbol." ),
731 UnescapeString( symbol->GetLibId().Format() ) );
732 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
733 }
734
735 continue;
736 }
737
738 // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
739 // is not found in the table so check if the library still exists in the table
740 // before attempting to load the symbol.
741 if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
742 {
743 if( aReporter )
744 {
745 msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
746 "available. Unable to link library symbol." ),
747 symbol->GetLibId().GetLibNickname().wx_str() );
748 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
749 }
750
751 continue;
752 }
753
754 if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
755 {
756 try
757 {
758 tmp = libs->LoadSymbol( symbol->GetLibId() );
759 }
760 catch( const IO_ERROR& ioe )
761 {
762 if( aReporter )
763 {
764 msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
765 UnescapeString( symbol->GetLibId().Format() ) );
766 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
767 }
768 }
769 }
770
771 if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
772 {
773 SYMBOL_LIB& legacyCacheLib = legacyLibs->back();
774
775 // It better be the cache library.
776 wxCHECK2( legacyCacheLib.IsCache(), continue );
777
778 wxString id = symbol->GetLibId().Format();
779
780 id.Replace( ':', '_' );
781
782 if( aReporter )
783 {
784 msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
785 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
786 symbol->GetField( FIELD_T::VALUE )->GetText(),
787 UnescapeString( id ) );
788 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
789 }
790
791 tmp = legacyCacheLib.FindSymbol( id );
792 }
793
794 if( tmp )
795 {
796 // We want a full symbol not just the top level child symbol.
797 libSymbol = tmp->Flatten();
798 libSymbol->SetParent();
799
800 m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
801 new LIB_SYMBOL( *libSymbol.get() ) } );
802
803 if( aReporter )
804 {
805 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
806 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
807 symbol->GetField( FIELD_T::VALUE )->GetText(),
808 UnescapeString( symbol->GetLibId().Format() ) );
809 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
810 }
811 }
812 else
813 {
814 if( aReporter )
815 {
816 msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
817 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
818 symbol->GetField( FIELD_T::VALUE )->GetText() );
819 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
820 }
821 }
822
823 if( libSymbol.get() ) // Only change the old link if the new link exists
824 symbol->SetLibSymbol( libSymbol.release() );
825 }
826
827 // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
828 // item with the new bbox
829 for( SCH_SYMBOL* symbol : symbols )
830 Append( symbol );
831}
832
833
835{
836 std::vector<SCH_SYMBOL*> symbols;
837
838 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
839 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
840
841 for( SCH_SYMBOL* symbol : symbols )
842 {
843 // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
844 m_rtree.remove( symbol );
845
846 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
847
848 LIB_SYMBOL* libSymbol = nullptr;
849
850 if( it != m_libSymbols.end() )
851 libSymbol = new LIB_SYMBOL( *it->second );
852
853 symbol->SetLibSymbol( libSymbol );
854
855 m_rtree.insert( symbol );
856 }
857}
858
859
861{
862 for( SCH_ITEM* item : Items() )
863 item->SetConnectivityDirty( true );
864}
865
866
867void SCH_SCREEN::Plot( PLOTTER* aPlotter, const SCH_PLOT_OPTS& aPlotOpts ) const
868{
869 // Ensure links are up to date, even if a library was reloaded for some reason:
870 std::vector<SCH_ITEM*> junctions;
871 std::vector<SCH_ITEM*> bitmaps;
872 std::vector<SCH_SYMBOL*> symbols;
873 std::vector<SCH_ITEM*> other;
874
875 for( SCH_ITEM* item : Items() )
876 {
877 if( item->IsMoving() )
878 continue;
879
880 if( item->Type() == SCH_JUNCTION_T )
881 junctions.push_back( item );
882 else if( item->Type() == SCH_BITMAP_T )
883 bitmaps.push_back( item );
884 else
885 other.push_back( item );
886
887 // Where the symbols overlap each other, we need to plot the text items a second
888 // time to get them on top of the overlapping element. This collection is in addition
889 // to the symbols already collected in `other`
890 if( item->Type() == SCH_SYMBOL_T )
891 {
892 for( SCH_ITEM* sym : m_rtree.Overlapping( SCH_SYMBOL_T, item->GetBoundingBox() ) )
893 {
894 if( sym != item )
895 {
896 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
897 break;
898 }
899 }
900 }
901 }
902
904 std::sort( other.begin(), other.end(),
905 []( const SCH_ITEM* a, const SCH_ITEM* b )
906 {
907 if( a->Type() == b->Type() )
908 return a->GetLayer() > b->GetLayer();
909
910 return a->Type() > b->Type();
911 } );
912
913 auto* renderSettings = static_cast<SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
914 constexpr bool background = true;
915
916 // Bitmaps are drawn first to ensure they are in the background
917 // This is particularly important for the wxPostscriptDC (used in *nix printers) as
918 // the bitmap PS command clears the screen
919 for( SCH_ITEM* item : bitmaps )
920 {
921 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
922 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
923 }
924
925 // Plot the background items
926 for( SCH_ITEM* item : other )
927 {
928 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
929 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
930 }
931
932 // Plot the foreground items
933 for( SCH_ITEM* item : other )
934 {
935 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
936 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
937 }
938
939 // After plotting the symbols as a group above (in `other`), we need to overplot the pins
940 // and symbols to ensure that they are always visible
941 TRANSFORM savedTransform = renderSettings->m_Transform;
942
943 for( const SCH_SYMBOL* sym :symbols )
944 {
945 renderSettings->m_Transform = sym->GetTransform();
946 aPlotter->SetCurrentLineWidth( sym->GetEffectivePenWidth( renderSettings ) );
947
948 for( SCH_FIELD field : sym->GetFields() )
949 {
950 field.ClearRenderCache();
951 field.Plot( aPlotter, false, aPlotOpts, sym->GetUnit(), sym->GetBodyStyle(), { 0, 0 },
952 sym->GetDNP() );
953 }
954
955 sym->PlotPins( aPlotter );
956
957 if( sym->GetDNP() )
958 sym->PlotDNP( aPlotter );
959 }
960
961 renderSettings->m_Transform = savedTransform;
962
963 for( SCH_ITEM* item : junctions )
964 {
965 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
966 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
967 }
968}
969
970
972{
973 for( SCH_ITEM* item : Items() )
974 item->ClearTempFlags();
975}
976
977
978SCH_PIN* SCH_SCREEN::GetPin( const VECTOR2I& aPosition, SCH_SYMBOL** aSymbol,
979 bool aEndPointOnly ) const
980{
981 SCH_SYMBOL* candidate = nullptr;
982 SCH_PIN* pin = nullptr;
983
984 for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
985 {
986 candidate = static_cast<SCH_SYMBOL*>( item );
987
988 if( aEndPointOnly )
989 {
990 pin = nullptr;
991
992 if( !candidate->GetLibSymbolRef() )
993 continue;
994
995 for( SCH_PIN* test_pin : candidate->GetLibPins() )
996 {
997 if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
998 {
999 pin = test_pin;
1000 break;
1001 }
1002 }
1003
1004 if( pin )
1005 break;
1006 }
1007 else
1008 {
1009 pin = static_cast<SCH_PIN*>( candidate->GetDrawItem( aPosition, SCH_PIN_T ) );
1010
1011 if( pin )
1012 break;
1013 }
1014 }
1015
1016 if( pin && aSymbol )
1017 *aSymbol = candidate;
1018
1019 return pin;
1020}
1021
1022
1024{
1025 SCH_SHEET_PIN* sheetPin = nullptr;
1026
1027 for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
1028 {
1029 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1030
1031 sheetPin = sheet->GetPin( aPosition );
1032
1033 if( sheetPin )
1034 break;
1035 }
1036
1037 return sheetPin;
1038}
1039
1040
1041size_t SCH_SCREEN::CountConnectedItems( const VECTOR2I& aPos, bool aTestJunctions ) const
1042{
1043 size_t count = 0;
1044
1045 for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
1046 {
1047 if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
1048 count++;
1049 }
1050
1051 return count;
1052}
1053
1054
1055void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1056{
1057
1058 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1059 {
1060 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1061
1062 symbol->ClearAnnotation( aSheetPath, aResetPrefix );
1063 }
1064}
1065
1066
1068{
1069 if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
1070 return;
1071
1072 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1073 {
1074 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1075
1076 // Add (when not existing) all sheet path entries
1077 for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1078 symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1079 }
1080}
1081
1082
1083void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1084{
1085 static const std::vector<KICAD_T> hierarchicalTypes = { SCH_SYMBOL_T,
1088
1089 for( SCH_ITEM* item : Items() )
1090 {
1091 if( item->IsType( hierarchicalTypes ) )
1092 aItems->push_back( item );
1093 }
1094}
1095
1096
1097void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1098{
1099 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1100 aItems->push_back( item );
1101
1102 std::sort( aItems->begin(), aItems->end(),
1103 []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1104 {
1105 if( a->GetPosition().x == b->GetPosition().x )
1106 {
1107 // Ensure deterministic sort
1108 if( a->GetPosition().y == b->GetPosition().y )
1109 return a->m_Uuid < b->m_Uuid;
1110
1111 return a->GetPosition().y < b->GetPosition().y;
1112 }
1113 else
1114 {
1115 return a->GetPosition().x < b->GetPosition().x;
1116 }
1117 } );
1118}
1119
1120
1122 std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1123{
1124 PROF_TIMER timer( __FUNCTION__ );
1125
1126 std::vector<DANGLING_END_ITEM> endPointsByPos;
1127 std::vector<DANGLING_END_ITEM> endPointsByType;
1128
1129 auto get_ends =
1130 [&]( SCH_ITEM* item )
1131 {
1132 if( item->IsConnectable() )
1133 item->GetEndPoints( endPointsByType );
1134 };
1135
1136 auto update_state =
1137 [&]( SCH_ITEM* item )
1138 {
1139 if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
1140 {
1141 if( aChangedHandler )
1142 ( *aChangedHandler )( item );
1143 }
1144 };
1145
1146 for( SCH_ITEM* item : Items() )
1147 {
1148 get_ends( item );
1149 item->RunOnChildren( get_ends, RECURSE_MODE::NO_RECURSE );
1150 }
1151
1152 PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
1153 endPointsByPos = endPointsByType;
1154 DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
1155 sortTimer.Stop();
1156
1157 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1158 sortTimer.Show();
1159
1160 for( SCH_ITEM* item : Items() )
1161 {
1162 update_state( item );
1163 item->RunOnChildren( update_state, RECURSE_MODE::NO_RECURSE );
1164 }
1165
1166 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1167 timer.Show();
1168}
1169
1170
1171SCH_LINE* SCH_SCREEN::GetLine( const VECTOR2I& aPosition, int aAccuracy, int aLayer,
1172 SCH_LINE_TEST_T aSearchType ) const
1173{
1174 // an accuracy of 0 had problems with rounding errors; use at least 1
1175 aAccuracy = std::max( aAccuracy, 1 );
1176
1177 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1178 {
1179 if( item->Type() != SCH_LINE_T )
1180 continue;
1181
1182 if( item->GetLayer() != aLayer )
1183 continue;
1184
1185 if( !item->HitTest( aPosition, aAccuracy ) )
1186 continue;
1187
1188 switch( aSearchType )
1189 {
1190 case ENTIRE_LENGTH_T:
1191 return (SCH_LINE*) item;
1192
1194 if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1195 return (SCH_LINE*) item;
1196 break;
1197
1198 case END_POINTS_ONLY_T:
1199 if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1200 return (SCH_LINE*) item;
1201 }
1202 }
1203
1204 return nullptr;
1205}
1206
1207
1208std::vector<SCH_LINE*> SCH_SCREEN::GetBusesAndWires( const VECTOR2I& aPosition,
1209 bool aIgnoreEndpoints ) const
1210{
1211 std::vector<SCH_LINE*> retVal;
1212
1213 for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, aPosition ) )
1214 {
1215 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1216 {
1217 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
1218
1219 if( aIgnoreEndpoints && wire->IsEndPoint( aPosition ) )
1220 continue;
1221
1222 if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), aPosition ) )
1223 retVal.push_back( wire );
1224 }
1225 }
1226
1227 return retVal;
1228}
1229
1230
1231std::vector<VECTOR2I> SCH_SCREEN::GetConnections() const
1232{
1233 std::vector<VECTOR2I> retval;
1234
1235 for( SCH_ITEM* item : Items() )
1236 {
1237 // Avoid items that are changing
1238 if( !( item->GetEditFlags() & ( IS_MOVING | IS_DELETED ) ) )
1239 {
1240 std::vector<VECTOR2I> pts = item->GetConnectionPoints();
1241 retval.insert( retval.end(), pts.begin(), pts.end() );
1242 }
1243 }
1244
1245 // We always have some overlapping connection points. Drop duplicates here
1246 std::sort( retval.begin(), retval.end(),
1247 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1248 {
1249 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1250 } );
1251
1252 retval.erase( std::unique( retval.begin(), retval.end() ), retval.end() );
1253
1254 return retval;
1255}
1256
1257
1258std::vector<VECTOR2I> SCH_SCREEN::GetNeededJunctions( const std::deque<EDA_ITEM*>& aItems ) const
1259{
1260 std::vector<VECTOR2I> pts;
1261 std::vector<VECTOR2I> connections = GetConnections();
1262
1263 for( const EDA_ITEM* edaItem : aItems )
1264 {
1265 const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( edaItem );
1266
1267 if( !item || !item->IsConnectable() )
1268 continue;
1269
1270 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
1271 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
1272
1273 // If the item is a line, we also add any connection points from the rest of the schematic
1274 // that terminate on the line after it is moved.
1275 if( item->Type() == SCH_LINE_T )
1276 {
1277 SCH_LINE* line = (SCH_LINE*) item;
1278
1279 for( const VECTOR2I& pt : connections )
1280 {
1281 if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
1282 pts.push_back( pt );
1283 }
1284 }
1285 }
1286
1287 // We always have some overlapping connection points. Drop duplicates here
1288 std::sort( pts.begin(), pts.end(),
1289 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1290 {
1291 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1292 } );
1293
1294 pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1295
1296 // We only want the needed junction points, remove all the others
1297 pts.erase( std::remove_if( pts.begin(), pts.end(),
1298 [this]( const VECTOR2I& a ) -> bool
1299 {
1300 return !IsExplicitJunctionNeeded( a );
1301 } ),
1302 pts.end() );
1303
1304 return pts;
1305}
1306
1307
1308SCH_LABEL_BASE* SCH_SCREEN::GetLabel( const VECTOR2I& aPosition, int aAccuracy ) const
1309{
1310 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1311 {
1312 switch( item->Type() )
1313 {
1314 case SCH_LABEL_T:
1315 case SCH_GLOBAL_LABEL_T:
1316 case SCH_HIER_LABEL_T:
1318 if( item->HitTest( aPosition, aAccuracy ) )
1319 return static_cast<SCH_LABEL_BASE*>( item );
1320
1321 break;
1322
1323 default:
1324 ;
1325 }
1326 }
1327
1328 return nullptr;
1329}
1330
1331
1333{
1334 wxCHECK( aLibSymbol, /* void */ );
1335
1336 wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1337
1338 auto it = m_libSymbols.find( libSymbolName );
1339
1340 if( it != m_libSymbols.end() )
1341 {
1342 delete it->second;
1343 m_libSymbols.erase( it );
1344 }
1345
1346 m_libSymbols[libSymbolName] = aLibSymbol;
1347}
1348
1349
1351{
1352 SCHEMATIC* schematic = Schematic();
1353
1354 const std::vector<wxString>* embeddedFonts = schematic->GetEmbeddedFiles()->UpdateFontFiles();
1355
1356 for( auto& [name, libSym] : m_libSymbols )
1357 {
1358 for( auto& [filename, embeddedFile] : libSym->EmbeddedFileMap() )
1359 {
1360 EMBEDDED_FILES::EMBEDDED_FILE* file = schematic->GetEmbeddedFile( filename );
1361
1362 if( file )
1363 {
1364 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1365 embeddedFile->decompressedData = file->decompressedData;
1366 embeddedFile->data_hash = file->data_hash;
1367 embeddedFile->is_valid = file->is_valid;
1368 }
1369 }
1370
1371 libSym->RunOnChildren(
1372 [&]( SCH_ITEM* aChild )
1373 {
1374 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1375 textItem->ResolveFont( embeddedFonts );
1376 },
1377 RECURSE_MODE::NO_RECURSE );
1378 }
1379
1380 std::vector<SCH_ITEM*> items_to_update;
1381
1382 for( SCH_ITEM* item : Items() )
1383 {
1384 bool update = false;
1385
1386 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( item ) )
1387 update |= textItem->ResolveFont( embeddedFonts );
1388
1389 item->RunOnChildren(
1390 [&]( SCH_ITEM* aChild )
1391 {
1392 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1393 update |= textItem->ResolveFont( embeddedFonts );
1394 },
1395 RECURSE_MODE::NO_RECURSE );
1396
1397 if( update )
1398 items_to_update.push_back( item );
1399 }
1400
1401 for( SCH_ITEM* item : items_to_update )
1402 Update( item );
1403}
1404
1405
1406void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1407{
1408 m_aliases.insert( aAlias );
1409}
1410
1411
1413{
1414 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1415 {
1416 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1417
1418 // Add missing value and footprint instance data for legacy schematics.
1419 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1420 {
1421 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1422 instance.m_Unit );
1423 }
1424 }
1425}
1426
1427
1429{
1430 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1431 {
1432 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1433
1434 // Fix pre-8.0 legacy power symbols with invisible pins
1435 // that have mismatched pin names and value fields
1436 if( symbol->GetLibSymbolRef()
1437 && symbol->GetLibSymbolRef()->IsGlobalPower()
1438 && symbol->GetAllLibPins().size() > 0
1439 && symbol->GetAllLibPins()[0]->IsGlobalPower()
1440 && !symbol->GetAllLibPins()[0]->IsVisible() )
1441 {
1442 symbol->SetValueFieldText( symbol->GetAllLibPins()[0]->GetName() );
1443 }
1444 }
1445}
1446
1447
1449 std::vector<wxString>& aMatches )
1450{
1451 wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
1452
1453 if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
1454 aMatches.emplace_back( searchName );
1455
1456 searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
1457
1458 long tmp;
1459 wxString suffix;
1460
1461 for( auto& pair : m_libSymbols )
1462 {
1463 if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
1464 aMatches.emplace_back( pair.first );
1465 }
1466
1467 return aMatches.size();
1468}
1469
1470
1471void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1472 const SCH_SHEET_LIST& aValidSheetPaths )
1473{
1474 // The project name cannot be empty. Projects older than 7.0 did not save project names
1475 // when saving instance data. Running this algorithm with an empty project name would
1476 // clobber all instance data for projects other than the current one when a schematic
1477 // file is shared across multiple projects. Because running the schematic editor in
1478 // stand alone mode can result in an empty project name, do not assert here.
1479 if( aProjectName.IsEmpty() )
1480 return;
1481
1482 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1483 {
1484 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1485
1486 wxCHECK2( symbol, continue );
1487
1488 std::set<KIID_PATH> pathsToPrune;
1489 const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstances();
1490
1491 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1492 {
1493 // Ignore instance paths from other projects.
1494 if( aProjectName != instance.m_ProjectName )
1495 continue;
1496
1497 std::optional<SCH_SHEET_PATH> pathFound =
1498 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1499
1500 // Check for paths that do not exist in the current project and paths that do
1501 // not contain the current symbol.
1502 if( !pathFound )
1503 pathsToPrune.emplace( instance.m_Path );
1504 else if( pathFound.value().LastScreen() != this )
1505 pathsToPrune.emplace( pathFound.value().Path() );
1506 }
1507
1508 for( const KIID_PATH& sheetPath : pathsToPrune )
1509 {
1510 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
1511 aProjectName, sheetPath.AsString() );
1512 symbol->RemoveInstance( sheetPath );
1513 }
1514 }
1515}
1516
1517
1518void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
1519 const SCH_SHEET_LIST& aValidSheetPaths )
1520{
1521 // The project name cannot be empty. Projects older than 7.0 did not save project names
1522 // when saving instance data. Running this algorithm with an empty project name would
1523 // clobber all instance data for projects other than the current one when a schematic
1524 // file is shared across multiple projects. Because running the schematic editor in
1525 // stand alone mode can result in an empty project name, do not assert here.
1526 if( aProjectName.IsEmpty() )
1527 return;
1528
1529 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1530 {
1531 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1532
1533 wxCHECK2( sheet, continue );
1534
1535 std::set<KIID_PATH> pathsToPrune;
1536 const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
1537
1538 for( const SCH_SHEET_INSTANCE& instance : instances )
1539 {
1540 // Ignore instance paths from other projects.
1541 if( aProjectName != instance.m_ProjectName )
1542 continue;
1543
1544 std::optional<SCH_SHEET_PATH> pathFound =
1545 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1546
1547 // Check for paths that do not exist in the current project and paths that do
1548 // not contain the current symbol.
1549 if( !pathFound )
1550 pathsToPrune.emplace( instance.m_Path );
1551 else if( pathFound.value().LastScreen() != this )
1552 pathsToPrune.emplace( pathFound.value().Path() );
1553 }
1554
1555 for( const KIID_PATH& sheetPath : pathsToPrune )
1556 {
1557 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
1558 aProjectName, sheetPath.AsString() );
1559 sheet->RemoveInstance( sheetPath );
1560 }
1561 }
1562}
1563
1564
1566{
1567 wxString trimmedFieldName;
1568
1569 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1570 {
1571 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1572
1573 wxCHECK2( symbol, continue );
1574
1575 for( const SCH_FIELD& field : symbol->GetFields() )
1576 {
1577 trimmedFieldName = field.GetName();
1578 trimmedFieldName.Trim();
1579 trimmedFieldName.Trim( false );
1580
1581 if( field.GetName() != trimmedFieldName )
1582 return true;
1583 }
1584 }
1585
1586 return false;
1587}
1588
1589
1590std::set<wxString> SCH_SCREEN::GetSheetNames() const
1591{
1592 std::set<wxString> retv;
1593
1594 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1595 {
1596 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1597
1598 wxCHECK2( sheet, continue );
1599
1600 retv.emplace( sheet->GetName() );
1601 }
1602
1603 return retv;
1604}
1605
1606
1608{
1609 wxCHECK( Schematic(), false );
1610
1611 SCH_SHEET_LIST hierarchy = Schematic()->Hierarchy();
1612
1613 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1614 {
1615 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1616
1617 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1618
1619 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1620 {
1621 if( !hierarchy.HasPath( instance.m_Path ) )
1622 return true;
1623 }
1624 }
1625
1626 return false;
1627}
1628
1629
1630wxString SCH_SCREEN::GroupsSanityCheck( bool repair )
1631{
1632 if( repair )
1633 {
1634 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
1635 {
1636 };
1637
1638 return wxEmptyString;
1639 }
1640 return GroupsSanityCheckInternal( repair );
1641}
1642
1643
1645{
1646 // Cycle detection
1647 //
1648 // Each group has at most one parent group.
1649 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
1650 // If we ever see a group that we've already marked, that's a cycle.
1651 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
1652 //
1653 // Algorithm below is linear in the # of groups because each group is visited only once.
1654 // There may be extra time taken due to the container access calls and iterators.
1655 //
1656 // Groups we know are cycle free
1657 std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
1658 // Groups in the current chain we're exploring.
1659 std::unordered_set<EDA_GROUP*> currentChainGroups;
1660 // Groups we haven't checked yet.
1661 std::unordered_set<EDA_GROUP*> toCheckGroups;
1662
1663 // Initialize set of groups and generators to check that could participate in a cycle.
1664 for( SCH_ITEM* item : Items().OfType( SCH_GROUP_T ) )
1665 toCheckGroups.insert( static_cast<SCH_GROUP*>( item ) );
1666
1667 while( !toCheckGroups.empty() )
1668 {
1669 currentChainGroups.clear();
1670 EDA_GROUP* group = *toCheckGroups.begin();
1671
1672 while( true )
1673 {
1674 if( currentChainGroups.find( group ) != currentChainGroups.end() )
1675 {
1676 if( repair )
1677 Remove( static_cast<SCH_ITEM*>( group->AsEdaItem() ) );
1678
1679 return "Cycle detected in group membership";
1680 }
1681 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
1682 {
1683 // Parent is a group we know does not lead to a cycle
1684 break;
1685 }
1686
1687 currentChainGroups.insert( group );
1688 // We haven't visited currIdx yet, so it must be in toCheckGroups
1689 toCheckGroups.erase( group );
1690
1691 group = group->AsEdaItem()->GetParentGroup();
1692
1693 if( !group )
1694 {
1695 // end of chain and no cycles found in this chain
1696 break;
1697 }
1698 }
1699
1700 // No cycles found in chain, so add it to set of groups we know don't participate
1701 // in a cycle.
1702 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
1703 }
1704
1705 // Success
1706 return "";
1707}
1708
1709
1711{
1712 wxCHECK( Schematic() && !m_fileName.IsEmpty(), false );
1713
1714 wxFileName thisScreenFn( m_fileName );
1715 wxFileName thisProjectFn( Schematic()->Prj().GetProjectFullName() );
1716
1717 wxCHECK( thisProjectFn.IsAbsolute(), false );
1718
1719 if( thisScreenFn.GetDirCount() < thisProjectFn.GetDirCount() )
1720 return false;
1721
1722 while( thisProjectFn.GetDirCount() != thisScreenFn.GetDirCount() )
1723 thisScreenFn.RemoveLastDir();
1724
1725 return thisScreenFn.GetPath() == thisProjectFn.GetPath();
1726}
1727
1728
1729#if defined(DEBUG)
1730void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1731{
1732 // for now, make it look like XML, expand on this later.
1733 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1734
1735 for( const SCH_ITEM* item : Items() )
1736 item->Show( nestLevel + 1, os );
1737
1738 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1739}
1740#endif
1741
1742
1744{
1745 m_index = 0;
1746 buildScreenList( aSheet );
1747}
1748
1749
1751{
1752}
1753
1754
1756{
1757 m_index = 0;
1758
1759 if( m_screens.size() > 0 )
1760 return m_screens[0];
1761
1762 return nullptr;
1763}
1764
1765
1767{
1768 if( m_index < m_screens.size() )
1769 m_index++;
1770
1771 return GetScreen( m_index );
1772}
1773
1774
1775SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1776{
1777 if( aIndex < m_screens.size() )
1778 return m_screens[ aIndex ];
1779
1780 return nullptr;
1781}
1782
1783
1784SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1785{
1786 if( aIndex < m_sheets.size() )
1787 return m_sheets[ aIndex ];
1788
1789 return nullptr;
1790}
1791
1792
1794{
1795 if( aScreen == nullptr )
1796 return;
1797
1798 for( const SCH_SCREEN* screen : m_screens )
1799 {
1800 if( screen == aScreen )
1801 return;
1802 }
1803
1804 m_screens.push_back( aScreen );
1805 m_sheets.push_back( aSheet );
1806}
1807
1808
1810{
1811 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1812 {
1813 SCH_SCREEN* screen = aSheet->GetScreen();
1814
1815 wxCHECK_RET( screen, "No screen for aSheet" );
1816
1817 addScreenToList( screen, aSheet );
1818
1819 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1820 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1821 }
1822}
1823
1824
1826{
1827 SCH_SCREEN* first = GetFirst();
1828
1829 if( !first )
1830 return;
1831
1832 SCHEMATIC* sch = first->Schematic();
1833
1834 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1835
1836 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1837 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1838 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1839
1840 // Search for new sheet paths, not existing in aInitialSheetPathList
1841 // and existing in sheetpathList
1842 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1843 {
1844 bool path_exists = false;
1845
1846 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
1847 {
1848 if( existing_sheetpath.Path() == sheetpath.Path() )
1849 {
1850 path_exists = true;
1851 break;
1852 }
1853 }
1854
1855 if( !path_exists )
1856 {
1857 // A new sheet path is found: clear the annotation corresponding to this new path:
1858 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
1859
1860 // Clear annotation and create the AR for this path, if not exists,
1861 // when the screen is shared by sheet paths.
1862 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
1863 // reference default value and takes the latest displayed value
1864 curr_screen->EnsureAlternateReferencesExist();
1865 curr_screen->ClearAnnotation( &sheetpath, false );
1866 }
1867 }
1868}
1869
1870
1872{
1873 std::vector<SCH_ITEM*> items;
1874 int count = 0;
1875
1876 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
1877 {
1878 return a->m_Uuid < b->m_Uuid;
1879 };
1880
1881 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
1882
1883 for( SCH_SCREEN* screen : m_screens )
1884 screen->GetHierarchicalItems( &items );
1885
1886 if( items.size() < 2 )
1887 return 0;
1888
1889 for( EDA_ITEM* item : items )
1890 {
1891 if( !unique_stamps.insert( item ).second )
1892 {
1893 // Reset to fully random UUID. This may lose reference, but better to be
1894 // deterministic about it rather than to have duplicate UUIDs with random
1895 // side-effects.
1896 const_cast<KIID&>( item->m_Uuid ) = KIID();
1897 count++;
1898
1899 // @todo If the item is a sheet, we need to descend the hierarchy from the sheet
1900 // and replace all instances of the changed UUID in sheet paths. Otherwise,
1901 // all instance paths with the sheet's UUID will get clobbered.
1902 }
1903 }
1904
1905 return count;
1906}
1907
1908
1910{
1911 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1912 {
1913 for( SCH_ITEM* item : screen->Items() )
1914 item->ClearEditFlags();
1915 }
1916}
1917
1918
1920{
1921 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1922 {
1923 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1924 {
1925 if( item == aMarker )
1926 {
1927 screen->DeleteItem( item );
1928 return;
1929 }
1930 }
1931 }
1932}
1933
1934
1935void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::MARKER_T aMarkerType, int aErrorCode,
1936 bool aIncludeExclusions )
1937{
1938 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1939 {
1940 std::vector<SCH_ITEM*> markers;
1941
1942 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
1943 {
1944 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
1945 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
1946
1947 if( marker->GetMarkerType() == aMarkerType
1948 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
1949 && ( !marker->IsExcluded() || aIncludeExclusions ) )
1950 {
1951 markers.push_back( item );
1952 }
1953 }
1954
1955 for( SCH_ITEM* marker : markers )
1956 screen->DeleteItem( marker );
1957 }
1958}
1959
1960
1962 bool aIncludeExclusions )
1963{
1964 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
1965}
1966
1967
1969{
1970 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1971 screen->UpdateSymbolLinks( aReporter );
1972
1973 SCH_SCREEN* first = GetFirst();
1974
1975 if( !first )
1976 return;
1977
1978 SCHEMATIC* sch = first->Schematic();
1979
1980 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
1981
1982 SCH_SHEET_LIST sheets = sch->Hierarchy();
1983
1984 // All of the library symbols have been replaced with copies so the connection graph
1985 // pointers are stale.
1986 if( sch->ConnectionGraph() )
1987 sch->ConnectionGraph()->Recalculate( sheets, true );
1988}
1989
1990
1992{
1993 bool has_symbols = false;
1994
1995 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
1996 {
1997 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
1998 {
1999 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2000 has_symbols = true;
2001
2002 if( !symbol->GetLibId().GetLibNickname().empty() )
2003 return false;
2004 }
2005 }
2006
2007 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
2008 return has_symbols ? true : false;
2009}
2010
2011
2012size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
2013{
2014 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2015 {
2016 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2017 {
2018 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2019 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
2020
2021 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
2022 aLibNicknames.Add( nickname );
2023 }
2024 }
2025
2026 return aLibNicknames.GetCount();
2027}
2028
2029
2030int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
2031{
2032 SCH_SCREEN* screen;
2033 int cnt = 0;
2034
2035 for( screen = GetFirst(); screen; screen = GetNext() )
2036 {
2037 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2038 {
2039 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2040
2041 if( symbol->GetLibId().GetLibNickname().wx_str() != aFrom )
2042 continue;
2043
2044 LIB_ID id = symbol->GetLibId();
2045 id.SetLibNickname( aTo );
2046 symbol->SetLibId( id );
2047 cnt++;
2048 }
2049 }
2050
2051 return cnt;
2052}
2053
2054
2055bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
2056{
2057 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2058 {
2059 if( screen->GetFileName() == aSchematicFileName )
2060 return true;
2061 }
2062
2063 return false;
2064}
2065
2066
2068{
2069 SCH_SCREEN* first = GetFirst();
2070
2071 if( !first )
2072 return;
2073
2074 SCHEMATIC* sch = first->Schematic();
2075
2076 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
2077
2078 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2079 curr_screen->GetClientSheetPaths().clear();
2080
2081 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
2082 {
2083 SCH_SCREEN* used_screen = sheetpath.LastScreen();
2084
2085 // Search for the used_screen in list and add this unique sheet path:
2086 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2087 {
2088 if( used_screen == curr_screen )
2089 {
2090 curr_screen->GetClientSheetPaths().push_back( sheetpath );
2091 break;
2092 }
2093 }
2094 }
2095}
2096
2097
2099{
2100 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2101 screen->SetLegacySymbolInstanceData();
2102}
2103
2104
2106{
2107 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2108 screen->FixLegacyPowerSymbolMismatches();
2109}
2110
2111
2113{
2114 LOCALE_IO toggle;
2115
2116 // V6 schematics may specify model names in Value fields, which we don't do in V7.
2117 // Migrate by adding an equivalent model for these symbols.
2118
2119 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
2120 {
2121 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2122 SIM_MODEL::MigrateSimModel<SCH_SYMBOL>( *symbol, &Schematic()->Prj() );
2123 }
2124}
2125
2126
2127void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
2128 const SCH_SHEET_LIST& aValidSheetPaths )
2129{
2130 if( aProjectName.IsEmpty() )
2131 return;
2132
2133 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2134 screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
2135}
2136
2137
2138void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
2139 const SCH_SHEET_LIST& aValidSheetPaths )
2140{
2141 if( aProjectName.IsEmpty() )
2142 return;
2143
2144 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2145 screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
2146}
2147
2148
2150{
2151 for( const SCH_SCREEN* screen : m_screens )
2152 {
2153 if( screen->HasSymbolFieldNamesWithWhiteSpace() )
2154 return true;
2155 }
2156
2157 return false;
2158}
const char * name
Definition: DXF_plotter.cpp:59
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:112
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
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr void SetOrigin(const Vec &pos)
Definition: box2.h:237
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr)
Update the connection graph for the given list of sheets.
static void sort_dangling_end_items(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos)
Both contain the same information.
Definition: sch_item.cpp:664
EDA_ANGLE Normalize90()
Definition: eda_angle.h:252
double AsDegrees() const
Definition: eda_angle.h:116
A set of EDA_ITEMs (i.e., without duplicates).
Definition: eda_group.h:45
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:96
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:84
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:138
const KIID m_Uuid
Definition: eda_item.h:501
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:108
bool IsSelected() const
Definition: eda_item.h:123
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:111
EDA_ITEM * GetParent() const
Definition: eda_item.h:110
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:142
bool IsNew() const
Definition: eda_item.h:120
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:246
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition: sch_rtree.h:79
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:128
iterator end()
Return a read/write iterator that points to one past the last element in the EE_RTREE.
Definition: sch_rtree.h:289
iterator begin()
Return a read/write iterator that points to the first.
Definition: sch_rtree.h:281
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
void clear()
Remove all items from the RTree.
Definition: sch_rtree.h:112
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
Definition: kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition: lib_id.cpp:100
wxString GetUniStringLibId() const
Definition: lib_id.h:148
UTF8 Format() const
Definition: lib_id.cpp:119
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition: lib_id.h:112
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:85
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:155
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:519
wxString GetName() const override
Definition: lib_symbol.h:149
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:345
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:156
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:329
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:49
bool IsExcluded() const
Definition: marker_base.h:93
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:107
enum MARKER_T GetMarkerType() const
Definition: marker_base.h:91
void sort()
Definition: multivector.h:248
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
Base plotter engine class.
Definition: plotter.h:105
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:136
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
A small class to help profiling.
Definition: profile.h:49
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition: profile.h:105
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:88
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SYMBOL_LIBS * SchLibs(PROJECT *aProject)
These are all prefaced with "Sch".
Definition: project_sch.cpp:90
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:73
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:112
Holds all the data relating to one schematic.
Definition: schematic.h:69
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:208
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: schematic.cpp:871
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:158
SCH_SHEET & Root() const
Definition: schematic.h:117
Class for a wire to bus entry.
A set of SCH_ITEMs (i.e., without duplicates).
Definition: sch_group.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
virtual bool IsConnectable() const
Definition: sch_item.h:461
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:290
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:232
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:476
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
EDA_ANGLE Angle() const
Get the angle between the start and end lines.
Definition: sch_line.h:103
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:90
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:749
SCH_SCREEN * GetNext()
unsigned int m_index
Definition: sch_screen.h:885
std::vector< SCH_SHEET * > m_sheets
Definition: sch_screen.h:884
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 DeleteMarkers(enum MARKER_BASE::MARKER_T aMarkerTyp, int aErrorCode, bool aIncludeExclusions=true)
Delete all markers of a particular type and error code.
void buildScreenList(SCH_SHEET *aSheet)
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
SCH_SCREEN * GetFirst()
void DeleteAllMarkers(enum MARKER_BASE::MARKER_T aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
int ChangeSymbolLibNickname(const wxString &aFrom, const wxString &aTo)
Change all of the symbol library nicknames.
SCH_SCREENS(SCH_SHEET *aSheet)
void BuildClientSheetPathList()
Build the list of sheet paths sharing a screen for each screen in use.
bool HasSymbolFieldNamesWithWhiteSpace() const
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the symbols inside new sheetpaths when a complex hierarchy is modified and n...
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
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...
std::vector< SCH_SCREEN * > m_screens
Definition: sch_screen.h:883
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:710
SCH_PIN * GetPin(const VECTOR2I &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
Definition: sch_screen.cpp:978
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:971
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:156
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
bool HasSymbolFieldNamesWithWhiteSpace() const
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:142
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
Definition: sch_screen.cpp:281
bool HasInstanceDataFromOtherProjects() const
Check symbols for instance data from other projects.
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
Remove all invalid symbol instance data in this screen object for the project defined by aProjectName...
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition: sch_screen.h:181
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:679
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:678
std::set< wxString > GetSheetNames() const
TITLE_BLOCK m_titles
Definition: sch_screen.h:691
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...
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
Remove all invalid sheet instance data in this screen object for the project defined by aProjectName ...
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
wxString GroupsSanityCheckInternal(bool repair)
int m_modification_sync
Definition: sch_screen.h:695
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition: sch_screen.h:673
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicate that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:497
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:112
void DecRefCount()
Definition: sch_screen.cpp:135
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:418
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:402
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicate that a junction dot may be placed at the given location.
Definition: sch_screen.cpp:516
void clearLibSymbols()
Definition: sch_screen.cpp:112
wxString m_fileName
Definition: sch_screen.h:676
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:614
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
Definition: sch_screen.cpp:834
void IncRefCount()
Definition: sch_screen.cpp:129
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:121
static bool ClassOf(const EDA_ITEM *aItem)
Definition: sch_screen.cpp:150
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
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:333
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
Definition: sch_screen.cpp:77
SCHEMATIC * Schematic() const
Definition: sch_screen.cpp:103
EE_RTREE m_rtree
Definition: sch_screen.h:693
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
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
Indicate that a junction dot is necessary at the given location, and does not yet exist.
Definition: sch_screen.cpp:506
SCH_SHEET_PIN * GetSheetPin(const VECTOR2I &aPosition) const
Test the screen if aPosition is a sheet label object.
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
bool InProjectPath() const
Check if the schematic file is in the current project path.
void FreeDrawList()
Free all the items from the schematic associated with the screen.
Definition: sch_screen.cpp:300
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
Definition: sch_screen.cpp:867
virtual wxString GetClass() const override
Return the class name.
Definition: sch_screen.h:126
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:326
void SetConnectivityDirty()
Definition: sch_screen.cpp:860
bool m_zoomInitialized
Definition: sch_screen.h:698
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:690
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:489
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:396
std::vector< VECTOR2I > GetConnections() const
Collect a unique list of all possible connection points in the schematic.
SPIN_STYLE GetLabelOrientationForPoint(const VECTOR2I &aPosition, SPIN_STYLE aDefaultOrientation, const SCH_SHEET_PATH *aSheet) const
Definition: sch_screen.cpp:525
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear the annotation for the symbols in aSheetPath on the screen.
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)
Remove aItem from the linked list and deletes the object.
Definition: sch_screen.cpp:371
std::set< std::shared_ptr< BUS_ALIAS >, BusAliasCmp > m_aliases
List of bus aliases stored in this screen.
Definition: sch_screen.h:707
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.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
bool HasPath(const KIID_PATH &aPath) const
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:47
void RemoveInstance(const KIID_PATH &aInstancePath)
Definition: sch_sheet.cpp:1339
wxString GetName() const
Definition: sch_sheet.h:113
SCH_SHEET_PIN * GetPin(const VECTOR2I &aPosition)
Return the sheet pin item found at aPosition in the sheet.
Definition: sch_sheet.cpp:613
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:411
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:116
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition: sch_sheet.h:429
Schematic symbol object.
Definition: sch_symbol.h:75
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:236
SCH_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 > & GetInstances() const
Definition: sch_symbol.h:134
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
Definition: sch_symbol.cpp:483
void SetValueFieldText(const wxString &aValue)
Definition: sch_symbol.cpp:791
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:242
bool AddSheetPathReferenceEntryIfMissing(const KIID_PATH &aSheetPath)
Add an instance to the alternate references list (m_instanceReferences), if this entry does not alrea...
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
Definition: sch_symbol.cpp:841
std::vector< SCH_PIN * > GetAllLibPins() const
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
Definition: sch_symbol.cpp:511
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:164
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition: sch_symbol.h:179
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:183
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:251
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
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
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:46
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:72
bool empty() const
Definition: utf8.h:104
wxString wx_str() const
Definition: utf8.cpp:45
#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
static const wxChar DanglingProfileMask[]
Flag to enable profiling of the TestDanglingEnds() function.
Definition: sch_screen.cpp:74
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
Common command IDs shared by more than one of the KiCad applications.
PROJECT & Prj()
Definition: kicad.cpp:597
@ LAYER_WIRE
Definition: layer_ids.h:441
@ LAYER_NOTES
Definition: layer_ids.h:456
@ LAYER_BUS
Definition: layer_ids.h:442
POINT_INFO AnalyzePoint(const EE_RTREE &aItem, const VECTOR2I &aPosition, bool aBreakCrossings)
Check a tree of items for a confluence at a given point and work out what kind of junction it is,...
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
Class to handle a set of SCH_ITEMs.
#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:77
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition: sch_rtree.h:195
iterator begin()
Definition: sch_rtree.h:225
iterator end()
Definition: sch_rtree.h:230
std::vector< char > decompressedData
A selection of information about a point in the schematic that might be eligible for turning into a j...
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
SPIN_STYLE GetPinSpinStyle(const SCH_PIN &aPin, const SCH_SYMBOL &aSymbol)
Get the spin style for a pin's label, taking into account the pin's orientation, as well as the given...
Definition for symbol library class.
wxLogTrace helper definitions.
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:89
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_GROUP_T
Definition: typeinfo.h:173
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_SHEET_T
Definition: typeinfo.h:175
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SCREEN_T
Definition: typeinfo.h:202
@ SCH_LABEL_LOCATE_ANY_T
Definition: typeinfo.h:191
@ SCHEMATIC_T
Definition: typeinfo.h:204
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:174
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
@ SCH_PIN_T
Definition: typeinfo.h:153