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 <vector>
29#include <wx/filefn.h>
30#include <wx/log.h>
31
32#include <eda_item.h>
33#include <id.h>
34#include <string_utils.h>
35#include <kiway.h>
36#include <plotters/plotter.h>
37#include <sch_plotter.h>
38#include <project.h>
39#include <project_sch.h>
40#include <reporter.h>
41#include <trace_helpers.h>
42#include <sch_edit_frame.h>
43#include <sch_item.h>
44
46#include <connection_graph.h>
47#include <junction_helpers.h>
48#include <sch_pin.h>
49#include <sch_symbol.h>
50#include <sch_group.h>
51#include <sch_junction.h>
52#include <sch_line.h>
53#include <sch_marker.h>
54#include <sch_sheet.h>
55#include <sch_sheet_pin.h>
56#include <sch_text.h>
57#include <schematic.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#include <math/vector3.h>
65#include <memory>
66
67// TODO(JE) Debugging only
68#include <core/profile.h>
70
71#include "sch_bus_entry.h"
72#include "sch_shape.h"
73
79static const wxChar DanglingProfileMask[] = wxT( "DANGLING_PROFILE" );
80
81
83 BASE_SCREEN( aParent, SCH_SCREEN_T ),
86 m_isReadOnly( false ),
87 m_fileExists( false )
88{
90 m_refCount = 0;
91 m_zoomInitialized = false;
92 m_LastZoomLevel = 1.0;
93
94 // Suitable for schematic only. For symbol_editor and viewlib, must be set to true
95 m_Center = false;
96
97 InitDataPoints( m_paper.GetSizeIU( schIUScale.IU_PER_MILS ) );
98}
99
100
106
107
109{
110 wxCHECK_MSG( GetParent() && GetParent()->Type() == SCHEMATIC_T, nullptr,
111 wxT( "SCH_SCREEN must have a SCHEMATIC parent!" ) );
112
113 return static_cast<SCHEMATIC*>( GetParent() );
114}
115
116
118{
119 for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : m_libSymbols )
120 delete libSymbol.second;
121
122 m_libSymbols.clear();
123}
124
125
126void SCH_SCREEN::SetFileName( const wxString& aFileName )
127{
128 // Don't assert here. We still call this after failing to load a file in order to show the
129 // user what we *tried* to load.
130 // wxASSERT( aFileName.IsEmpty() || wxIsAbsolutePath( aFileName ) );
131
132 m_fileName = aFileName;
133}
134
135
137{
138 m_refCount++;
139}
140
141
143{
144 wxCHECK_RET( m_refCount != 0, wxT( "Screen reference count already zero. Bad programmer!" ) );
145 m_refCount--;
146}
147
148
149bool SCH_SCREEN::HasItems( KICAD_T aItemType ) const
150{
151 EE_RTREE::EE_TYPE sheets = m_rtree.OfType( aItemType );
152
153 return sheets.begin() != sheets.end();
154}
155
156
157bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
158{
159 return aItem && SCH_SCREEN_T == aItem->Type();
160}
161
162
163void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
164{
165 if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
166 {
167 // Ensure the item can reach the SCHEMATIC through this screen
168 aItem->SetParent( this );
169
170 if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
171 {
172 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
173
174 if( symbol->GetLibSymbolRef() )
175 {
176 symbol->GetLibSymbolRef()->GetDrawItems().sort();
177
178 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
179
180 if( it == m_libSymbols.end() || !it->second )
181 {
183 new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
184 }
185 else
186 {
187 // The original library symbol may have changed since the last time
188 // it was added to the schematic. If it has changed, then a new name
189 // must be created for the library symbol list to prevent all of the
190 // other schematic symbols referencing that library symbol from changing.
191 LIB_SYMBOL* foundSymbol = it->second;
192
193 foundSymbol->GetDrawItems().sort();
194
195 if( *foundSymbol != *symbol->GetLibSymbolRef() )
196 {
197 wxString newName;
198 std::vector<wxString> matches;
199
200 getLibSymbolNameMatches( *symbol, matches );
201 foundSymbol = nullptr;
202
203 for( const wxString& libSymbolName : matches )
204 {
205 it = m_libSymbols.find( libSymbolName );
206
207 if( it == m_libSymbols.end() )
208 continue;
209
210 foundSymbol = it->second;
211
212 wxCHECK2( foundSymbol, continue );
213
214 wxString tmp = symbol->GetLibSymbolRef()->GetName();
215
216 // Temporarily update the new symbol library symbol name so it
217 // doesn't fail on the name comparison below.
218 symbol->GetLibSymbolRef()->SetName( foundSymbol->GetName() );
219
220 if( *foundSymbol == *symbol->GetLibSymbolRef() )
221 {
222 newName = libSymbolName;
223 symbol->GetLibSymbolRef()->SetName( tmp );
224 break;
225 }
226
227 symbol->GetLibSymbolRef()->SetName( tmp );
228 foundSymbol = nullptr;
229 }
230
231 if( !foundSymbol )
232 {
233 int cnt = 1;
234
235 newName.Printf( wxT( "%s_%d" ),
237 cnt );
238
239 while( m_libSymbols.find( newName ) != m_libSymbols.end() )
240 {
241 cnt += 1;
242 newName.Printf( wxT( "%s_%d" ),
244 cnt );
245 }
246 }
247
248 // Update the schematic symbol library link as this symbol only exists
249 // in the schematic.
250 symbol->SetSchSymbolLibraryName( newName );
251
252 if( !foundSymbol )
253 {
254 // Update the schematic symbol library link as this symbol does not
255 // exist in any symbol library.
256 LIB_ID newLibId( wxEmptyString, newName );
257 LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
258
259 newLibSymbol->SetLibId( newLibId );
260 newLibSymbol->SetName( newName );
261 symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
262 m_libSymbols[newName] = newLibSymbol;
263 }
264 }
265 }
266 }
267 }
268
269 m_rtree.insert( aItem );
271 }
272}
273
274
276{
277 wxCHECK_RET( aScreen, "Invalid screen object." );
278
279 // No need to descend the hierarchy. Once the top level screen is copied, all of its
280 // children are copied as well.
281 for( SCH_ITEM* aItem : aScreen->m_rtree )
282 Append( aItem );
283
284 aScreen->Clear( false );
285}
286
287
288void SCH_SCREEN::Clear( bool aFree )
289{
290 if( aFree )
291 {
292 FreeDrawList();
294 }
295 else
296 {
297 m_rtree.clear();
298 }
299
300 // Clear the project settings
302
303 m_titles.Clear();
304}
305
306
308{
309 // We don't know which order we will encounter dependent items (e.g. pins or fields), so
310 // we store the items to be deleted until we've fully cleared the tree before deleting
311 std::vector<SCH_ITEM*> delete_list;
312
313 std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
314 []( SCH_ITEM* aItem )
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_ITEM* aItem, 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_ITEM*> toSearch;
424
425 auto getItemEndpoints = []( SCH_ITEM* aCandidate ) -> std::vector<VECTOR2I>
426 {
427 if( !aCandidate )
428 return {};
429
430 if( aCandidate->Type() == SCH_LINE_T )
431 {
432 SCH_LINE* line = static_cast<SCH_LINE*>( aCandidate );
433 return { line->GetStartPoint(), line->GetEndPoint() };
434 }
435
436 if( aCandidate->Type() == SCH_SHAPE_T )
437 {
438 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aCandidate );
439
440 if( shape->GetShape() == SHAPE_T::ARC || shape->GetShape() == SHAPE_T::BEZIER )
441 return { shape->GetStart(), shape->GetEnd() };
442 else if( shape->GetShape() == SHAPE_T::RECTANGLE )
443 return shape->GetRectCorners();
444 else if( shape->GetShape() == SHAPE_T::SEGMENT )
445 return { shape->GetStart(), shape->GetEnd() };
446 else if( shape->GetShape() == SHAPE_T::POLY )
447 return shape->GetPolyPoints();
448 }
449
450 return {};
451 };
452
453 if( !aItem || getItemEndpoints( aItem ).empty() )
454 return retval;
455
456 toSearch.push( aItem );
457
458 while( !toSearch.empty() )
459 {
460 SCH_ITEM* item = toSearch.top();
461 toSearch.pop();
462
463 if( item->HasFlag( PROCESSED ) )
464 continue;
465
466 item->SetFlags( PROCESSED );
467
468 const BOX2I bbox = item->GetBoundingBox();
469
470 for( KICAD_T type : { SCH_LINE_T, SCH_SHAPE_T } )
471 {
472 for( SCH_ITEM* candidate : Items().Overlapping( type, bbox ) )
473 {
474 if( candidate->HasFlag( PROCESSED ) )
475 continue;
476
477 std::vector<VECTOR2I> endpoints = getItemEndpoints( candidate );
478
479 if( endpoints.empty() )
480 continue;
481
482 // Skip connecting items on different layers (e.g. buses)
483 if( item->GetLayer() != candidate->GetLayer() )
484 continue;
485
486 bool sharesEndpoint = false;
487
488 for( const VECTOR2I& pt : endpoints )
489 {
490 if( item->IsEndPoint( pt ) )
491 {
492 sharesEndpoint = true;
493
494 if( aSecondPass && item->IsConnected( pt ) )
495 {
496 SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
497
498 if( junction )
499 retval.insert( junction );
500 }
501 }
502 }
503
504 if( !sharesEndpoint )
505 continue;
506
507 toSearch.push( candidate );
508 retval.insert( candidate );
509 }
510 }
511 }
512
513 for( SCH_ITEM* item : Items() )
514 item->ClearTempFlags();
515
516 return retval;
517}
518
519
520bool SCH_SCREEN::IsJunction( const VECTOR2I& aPosition ) const
521{
523 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
524 return info.isJunction;
525}
526
527
528bool SCH_SCREEN::IsExplicitJunction( const VECTOR2I& aPosition ) const
529{
531 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
532
533 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires );
534}
535
536
537bool SCH_SCREEN::IsExplicitJunctionNeeded( const VECTOR2I& aPosition ) const
538{
540 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, false );
541
542 return info.isJunction && ( !info.hasBusEntry || info.hasBusEntryToMultipleWires )
543 && !info.hasExplicitJunctionDot;
544}
545
546
548{
550 JUNCTION_HELPERS::AnalyzePoint( Items(), aPosition, true );
551
552 return info.isJunction && (!info.hasBusEntry || info.hasBusEntryToMultipleWires );
553}
554
555
557 SPIN_STYLE aDefaultOrientation,
558 const SCH_SHEET_PATH* aSheet ) const
559{
560 auto ret = aDefaultOrientation;
561
562 for( SCH_ITEM* item : Items().Overlapping( aPosition ) )
563 {
564 if( item->GetEditFlags() & STRUCT_DELETED )
565 continue;
566
567 switch( item->Type() )
568 {
570 {
571 auto busEntry = static_cast<const SCH_BUS_WIRE_ENTRY*>( item );
572 if( busEntry->m_connected_bus_item )
573 {
574 // bus connected, take the bus direction into consideration only if it is
575 // vertical or horizontal
576 auto bus = static_cast<const SCH_LINE*>( busEntry->m_connected_bus_item );
577 if( bus->Angle().AsDegrees() == 90.0 )
578 {
579 // bus is vertical -> label shall be horizontal and
580 // shall be placed to the side where the bus entry is
581 if( aPosition.x < bus->GetPosition().x )
582 ret = SPIN_STYLE::LEFT;
583 else if( aPosition.x > bus->GetPosition().x )
584 ret = SPIN_STYLE::RIGHT;
585 }
586 else if( bus->Angle().AsDegrees() == 0.0 )
587 {
588 // bus is horizontal -> label shall be vertical and
589 // shall be placed to the side where the bus entry is
590 if( aPosition.y < bus->GetPosition().y )
591 ret = SPIN_STYLE::UP;
592 else if( aPosition.y > bus->GetPosition().y )
593 ret = SPIN_STYLE::BOTTOM;
594 }
595 }
596 }
597 break;
598
599 case SCH_LINE_T:
600 {
601 auto line = static_cast<const SCH_LINE*>( item );
602 // line angles goes between -90 and 90 degrees, but normalize
603 auto angle = line->Angle().Normalize90().AsDegrees();
604
605 if( -45 < angle && angle <= 45 )
606 {
607 if( line->GetStartPoint().x <= line->GetEndPoint().x )
608 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::RIGHT : SPIN_STYLE::LEFT;
609 else
610 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::LEFT : SPIN_STYLE::RIGHT;
611 }
612 else
613 {
614 if( line->GetStartPoint().y <= line->GetEndPoint().y )
615 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::BOTTOM : SPIN_STYLE::UP;
616 else
617 ret = line->GetEndPoint() == aPosition ? SPIN_STYLE::UP : SPIN_STYLE::BOTTOM;
618 }
619 }
620 break;
621
622 case SCH_SYMBOL_T:
623 {
624 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
625
626 for( SCH_PIN* pin : symbol->GetPins( aSheet ) )
627 {
628 if( pin->GetPosition() == aPosition )
629 {
630 ret = GetPinSpinStyle( *pin, *symbol );
631 break;
632 }
633 }
634 }
635 break;
636
637 default: break;
638 }
639 }
640
641 return ret;
642}
643
644
645bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
646{
647 wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false,
648 wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) );
649
650 SCH_SHEET_PIN* sheetPin;
651 SCH_LABEL_BASE* label;
652
653 switch( aLayer )
654 {
655 case LAYER_BUS:
656 if( GetBus( aPosition ) )
657 return true;
658
659 sheetPin = GetSheetPin( aPosition );
660
661 if( sheetPin && sheetPin->IsConnected( aPosition ) )
662 return true;
663
664 label = GetLabel( aPosition );
665
666 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
667 return true;
668
669 break;
670
671 case LAYER_NOTES:
672 if( GetLine( aPosition ) )
673 return true;
674
675 break;
676
677 case LAYER_WIRE:
678 if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T ) )
679 return true;
680
681 if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
682 return true;
683
684 if( GetPin( aPosition, nullptr, true ) )
685 return true;
686
687 if( GetWire( aPosition ) )
688 return true;
689
690 label = GetLabel( aPosition, 1 );
691
692 if( label && !label->IsNew() && label->IsConnected( aPosition ) )
693 return true;
694
695 sheetPin = GetSheetPin( aPosition );
696
697 if( sheetPin && sheetPin->IsConnected( aPosition ) )
698 return true;
699
700 break;
701
702 default:
703 break;
704 }
705
706 return false;
707}
708
709
711{
712 wxCHECK_RET( Schematic(), "Cannot call SCH_SCREEN::UpdateSymbolLinks with no SCHEMATIC" );
713
714 wxString msg;
715 std::vector<SCH_SYMBOL*> symbols;
717
718 // This will be a nullptr if an s-expression schematic is loaded.
719 LEGACY_SYMBOL_LIBS* legacyLibs = PROJECT_SCH::LegacySchLibs( &Schematic()->Project() );
720
721 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
722 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
723
724 // Remove them from the R tree. Their bounding box size may change.
725 for( SCH_SYMBOL* symbol : symbols )
726 Remove( symbol );
727
728 // Clear all existing symbol links.
730
731 for( SCH_SYMBOL* symbol : symbols )
732 {
733 LIB_SYMBOL* tmp = nullptr;
734
735 // If the symbol is already in the internal library, map the symbol to it.
736 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
737
738 if( ( it != m_libSymbols.end() ) )
739 {
740 if( aReporter )
741 {
742 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
743 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
744 symbol->GetField( FIELD_T::VALUE )->GetText(),
745 UnescapeString( symbol->GetLibId().Format() ) );
746 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
747 }
748
749 // Internal library symbols are already flattened so just make a copy.
750 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
751 continue;
752 }
753
754 if( !symbol->GetLibId().IsValid() )
755 {
756 if( aReporter )
757 {
758 msg.Printf( _( "Schematic symbol reference '%s' library identifier is not valid. "
759 "Unable to link library symbol." ),
760 UnescapeString( symbol->GetLibId().Format() ) );
761 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
762 }
763
764 continue;
765 }
766
767 // LIB_TABLE_BASE::LoadSymbol() throws an IO_ERROR if the library nickname
768 // is not found in the table so check if the library still exists in the table
769 // before attempting to load the symbol.
770 if( !libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) && !legacyLibs )
771 {
772 if( aReporter )
773 {
774 msg.Printf( _( "Symbol library '%s' not found and no fallback cache library "
775 "available. Unable to link library symbol." ),
776 symbol->GetLibId().GetLibNickname().wx_str() );
777 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
778 }
779
780 continue;
781 }
782
783 if( libs->HasLibrary( symbol->GetLibId().GetLibNickname() ) )
784 {
785 try
786 {
787 tmp = libs->LoadSymbol( symbol->GetLibId() );
788 }
789 catch( const IO_ERROR& ioe )
790 {
791 if( aReporter )
792 {
793 msg.Printf( _( "I/O error %s resolving library symbol %s" ), ioe.What(),
794 UnescapeString( symbol->GetLibId().Format() ) );
795 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
796 }
797 }
798 }
799
800 if( !tmp && legacyLibs && legacyLibs->GetLibraryCount() )
801 {
802 LEGACY_SYMBOL_LIB& legacyCacheLib = legacyLibs->back();
803
804 // It better be the cache library.
805 wxCHECK2( legacyCacheLib.IsCache(), continue );
806
807 wxString id = symbol->GetLibId().Format();
808
809 id.Replace( ':', '_' );
810
811 if( aReporter )
812 {
813 msg.Printf( _( "Falling back to cache to set symbol '%s:%s' link '%s'." ),
814 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
815 symbol->GetField( FIELD_T::VALUE )->GetText(),
816 UnescapeString( id ) );
817 aReporter->ReportTail( msg, RPT_SEVERITY_WARNING );
818 }
819
820 tmp = legacyCacheLib.FindSymbol( id );
821 }
822
823 if( tmp )
824 {
825 // We want a full symbol not just the top level child symbol.
826 std::unique_ptr<LIB_SYMBOL> libSymbol = tmp->Flatten();
827 libSymbol->SetParent();
828
829 m_libSymbols.insert( { symbol->GetSchSymbolLibraryName(),
830 new LIB_SYMBOL( *libSymbol ) } );
831
832 if( aReporter )
833 {
834 msg.Printf( _( "Setting schematic symbol '%s %s' library identifier to '%s'." ),
835 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
836 symbol->GetField( FIELD_T::VALUE )->GetText(),
837 UnescapeString( symbol->GetLibId().Format() ) );
838 aReporter->ReportTail( msg, RPT_SEVERITY_INFO );
839 }
840
841 symbol->SetLibSymbol( libSymbol.release() );
842 }
843 else
844 {
845 if( aReporter )
846 {
847 msg.Printf( _( "No library symbol found for schematic symbol '%s %s'." ),
848 symbol->GetField( FIELD_T::REFERENCE )->GetText(),
849 symbol->GetField( FIELD_T::VALUE )->GetText() );
850 aReporter->ReportTail( msg, RPT_SEVERITY_ERROR );
851 }
852 }
853 }
854
855 // Changing the symbol may adjust the bbox of the symbol. This re-inserts the
856 // item with the new bbox
857 for( SCH_SYMBOL* symbol : symbols )
858 Append( symbol );
859}
860
861
863{
864 std::vector<SCH_SYMBOL*> symbols;
865
866 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
867 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
868
869 for( SCH_SYMBOL* symbol : symbols )
870 {
871 // Changing the symbol may adjust the bbox of the symbol; remove and reinsert it afterwards.
872 m_rtree.remove( symbol );
873
874 auto it = m_libSymbols.find( symbol->GetSchSymbolLibraryName() );
875
876 if( it != m_libSymbols.end() )
877 symbol->SetLibSymbol( new LIB_SYMBOL( *it->second ) );
878 else
879 symbol->SetLibSymbol( nullptr );
880
881 m_rtree.insert( symbol );
882 }
883}
884
885
887{
888 for( SCH_ITEM* item : Items() )
889 item->SetConnectivityDirty( true );
890}
891
892
893void SCH_SCREEN::Plot( PLOTTER* aPlotter, const SCH_PLOT_OPTS& aPlotOpts ) const
894{
895 // Ensure links are up to date, even if a library was reloaded for some reason:
896 std::vector<SCH_ITEM*> junctions;
897 std::vector<SCH_ITEM*> bitmaps;
898 std::vector<SCH_SYMBOL*> symbols;
899 std::vector<SCH_ITEM*> other;
900
901 for( SCH_ITEM* item : Items() )
902 {
903 if( item->IsMoving() )
904 continue;
905
906 if( item->Type() == SCH_JUNCTION_T )
907 junctions.push_back( item );
908 else if( item->Type() == SCH_BITMAP_T )
909 bitmaps.push_back( item );
910 else
911 other.push_back( item );
912
913 // Where the symbols overlap each other, we need to plot the text items a second
914 // time to get them on top of the overlapping element. This collection is in addition
915 // to the symbols already collected in `other`
916 if( item->Type() == SCH_SYMBOL_T )
917 {
918 for( SCH_ITEM* sym : m_rtree.Overlapping( SCH_SYMBOL_T, item->GetBoundingBox() ) )
919 {
920 if( sym != item )
921 {
922 symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
923 break;
924 }
925 }
926 }
927 }
928
930 std::sort( other.begin(), other.end(),
931 []( const SCH_ITEM* a, const SCH_ITEM* b )
932 {
933 if( a->Type() == b->Type() )
934 return a->GetLayer() > b->GetLayer();
935
936 return a->Type() > b->Type();
937 } );
938
939 auto* renderSettings = static_cast<SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
940 constexpr bool background = true;
941
942 // Bitmaps are drawn first to ensure they are in the background
943 // This is particularly important for the wxPostscriptDC (used in *nix printers) as
944 // the bitmap PS command clears the screen
945 for( SCH_ITEM* item : bitmaps )
946 {
947 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
948 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
949 }
950
951 // Plot the background items
952 for( SCH_ITEM* item : other )
953 {
954 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
955 item->Plot( aPlotter, background, aPlotOpts, 0, 0, { 0, 0 }, false );
956 }
957
958 // Plot the foreground items
959 for( SCH_ITEM* item : other )
960 {
961 double lineWidth = item->GetEffectivePenWidth( renderSettings );
962 aPlotter->SetCurrentLineWidth( lineWidth );
963
964 if( item->Type() != SCH_LINE_T )
965 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
966 else
967 {
968 SCH_LINE* aLine = static_cast<SCH_LINE*>( item );
969
970 if( !aLine->IsWire() || !aPlotOpts.m_plotHopOver )
971 {
972 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
973 }
974 else
975 {
976 double arcRadius = lineWidth * aLine->Schematic()->Settings().m_HopOverScale;
977 std::vector<VECTOR3I> curr_wire_shape = aLine->BuildWireWithHopShape( this, arcRadius );
978
979 for( size_t ii = 1; ii < curr_wire_shape.size(); ii++ )
980 {
981 VECTOR2I start( curr_wire_shape[ii-1].x, curr_wire_shape[ii-1].y );
982
983 if( curr_wire_shape[ii-1].z == 0 ) // This is the start point of a segment
984 // there are always 2 points in list for a segment
985 {
986 VECTOR2I end( curr_wire_shape[ii].x, curr_wire_shape[ii].y );
987
988 SCH_LINE curr_line( *aLine );
989 curr_line.SetStartPoint( start );
990 curr_line.SetEndPoint( end );
991 curr_line.Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
992 }
993 else // This is the start point of a arc. there are always 3 points in list for an arc
994 {
995 VECTOR2I arc_middle( curr_wire_shape[ii].x, curr_wire_shape[ii].y );
996 ii++;
997 VECTOR2I arc_end( curr_wire_shape[ii].x, curr_wire_shape[ii].y );
998 ii++;
999
1000 SCH_SHAPE arc( SHAPE_T::ARC, aLine->GetLayer(), lineWidth );
1001
1002 arc.SetArcGeometry( start, arc_middle, arc_end );
1003 // Hop are a small arc, so use a solid line style gives best results
1005 arc.Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
1006 }
1007 }
1008 }
1009 }
1010 }
1011
1012 // After plotting the symbols as a group above (in `other`), we need to overplot the pins
1013 // and symbols to ensure that they are always visible
1014 TRANSFORM savedTransform = renderSettings->m_Transform;
1015
1016 for( const SCH_SYMBOL* sym :symbols )
1017 {
1018 renderSettings->m_Transform = sym->GetTransform();
1019 aPlotter->SetCurrentLineWidth( sym->GetEffectivePenWidth( renderSettings ) );
1020
1021 for( SCH_FIELD field : sym->GetFields() )
1022 {
1023 field.ClearRenderCache();
1024 field.Plot( aPlotter, false, aPlotOpts, sym->GetUnit(), sym->GetBodyStyle(), { 0, 0 },
1025 static_cast<const SYMBOL*>( sym )->GetDNP() );
1026
1027 if( sym->IsSymbolLikePowerLocalLabel() && field.GetId() == FIELD_T::VALUE
1028 && ( field.IsVisible() || field.IsForceVisible() ) )
1029 {
1030 sym->PlotLocalPowerIconShape( aPlotter );
1031 }
1032 }
1033
1034 sym->PlotPins( aPlotter );
1035
1036 if( static_cast<const SYMBOL*>( sym )->GetDNP() )
1037 sym->PlotDNP( aPlotter );
1038 }
1039
1040 renderSettings->m_Transform = savedTransform;
1041
1042 for( SCH_ITEM* item : junctions )
1043 {
1044 aPlotter->SetCurrentLineWidth( item->GetEffectivePenWidth( renderSettings ) );
1045 item->Plot( aPlotter, !background, aPlotOpts, 0, 0, { 0, 0 }, false );
1046 }
1047}
1048
1049
1051{
1052 for( SCH_ITEM* item : Items() )
1053 item->ClearTempFlags();
1054}
1055
1056
1057SCH_PIN* SCH_SCREEN::GetPin( const VECTOR2I& aPosition, SCH_SYMBOL** aSymbol,
1058 bool aEndPointOnly ) const
1059{
1060 SCH_SYMBOL* candidate = nullptr;
1061 SCH_PIN* pin = nullptr;
1062
1063 for( SCH_ITEM* item : Items().Overlapping( SCH_SYMBOL_T, aPosition ) )
1064 {
1065 candidate = static_cast<SCH_SYMBOL*>( item );
1066
1067 if( aEndPointOnly )
1068 {
1069 pin = nullptr;
1070
1071 if( !candidate->GetLibSymbolRef() )
1072 continue;
1073
1074 for( SCH_PIN* test_pin : candidate->GetLibPins() )
1075 {
1076 if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
1077 {
1078 pin = test_pin;
1079 break;
1080 }
1081 }
1082
1083 if( pin )
1084 break;
1085 }
1086 else
1087 {
1088 pin = static_cast<SCH_PIN*>( candidate->GetDrawItem( aPosition, SCH_PIN_T ) );
1089
1090 if( pin )
1091 break;
1092 }
1093 }
1094
1095 if( pin && aSymbol )
1096 *aSymbol = candidate;
1097
1098 return pin;
1099}
1100
1101
1103{
1104 SCH_SHEET_PIN* sheetPin = nullptr;
1105
1106 for( SCH_ITEM* item : Items().Overlapping( SCH_SHEET_T, aPosition ) )
1107 {
1108 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1109
1110 sheetPin = sheet->GetPin( aPosition );
1111
1112 if( sheetPin )
1113 break;
1114 }
1115
1116 return sheetPin;
1117}
1118
1119
1120size_t SCH_SCREEN::CountConnectedItems( const VECTOR2I& aPos, bool aTestJunctions ) const
1121{
1122 size_t count = 0;
1123
1124 for( const SCH_ITEM* item : Items().Overlapping( aPos ) )
1125 {
1126 if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
1127 count++;
1128 }
1129
1130 return count;
1131}
1132
1133
1134void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath, bool aResetPrefix )
1135{
1136
1137 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1138 {
1139 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1140
1141 symbol->ClearAnnotation( aSheetPath, aResetPrefix );
1142 }
1143}
1144
1145
1147{
1148 if( GetClientSheetPaths().size() <= 1 ) // No need for alternate reference
1149 return;
1150
1151 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1152 {
1153 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1154
1155 // Add (when not existing) all sheet path entries
1156 for( const SCH_SHEET_PATH& sheet : GetClientSheetPaths() )
1157 symbol->AddSheetPathReferenceEntryIfMissing( sheet.Path() );
1158 }
1159}
1160
1161
1162void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems ) const
1163{
1164 static const std::vector<KICAD_T> hierarchicalTypes = { SCH_SYMBOL_T,
1167
1168 for( SCH_ITEM* item : Items() )
1169 {
1170 if( item->IsType( hierarchicalTypes ) )
1171 aItems->push_back( item );
1172 }
1173}
1174
1175
1176void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
1177{
1178 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1179 aItems->push_back( item );
1180
1181 std::sort( aItems->begin(), aItems->end(),
1182 []( EDA_ITEM* a, EDA_ITEM* b ) -> bool
1183 {
1184 if( a->GetPosition().x == b->GetPosition().x )
1185 {
1186 // Ensure deterministic sort
1187 if( a->GetPosition().y == b->GetPosition().y )
1188 return a->m_Uuid < b->m_Uuid;
1189
1190 return a->GetPosition().y < b->GetPosition().y;
1191 }
1192 else
1193 {
1194 return a->GetPosition().x < b->GetPosition().x;
1195 }
1196 } );
1197}
1198
1199
1201 std::function<void( SCH_ITEM* )>* aChangedHandler ) const
1202{
1203 PROF_TIMER timer( __FUNCTION__ );
1204
1205 std::vector<DANGLING_END_ITEM> endPointsByPos;
1206 std::vector<DANGLING_END_ITEM> endPointsByType;
1207
1208 auto get_ends =
1209 [&]( SCH_ITEM* item )
1210 {
1211 if( item->IsConnectable() )
1212 item->GetEndPoints( endPointsByType );
1213 };
1214
1215 auto update_state =
1216 [&]( SCH_ITEM* item )
1217 {
1218 if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
1219 {
1220 if( aChangedHandler )
1221 ( *aChangedHandler )( item );
1222 }
1223 };
1224
1225 for( SCH_ITEM* item : Items() )
1226 {
1227 get_ends( item );
1228 item->RunOnChildren( get_ends, RECURSE_MODE::NO_RECURSE );
1229 }
1230
1231 PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
1232 endPointsByPos = endPointsByType;
1233 DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
1234 sortTimer.Stop();
1235
1236 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1237 sortTimer.Show();
1238
1239 for( SCH_ITEM* item : Items() )
1240 {
1241 update_state( item );
1242 item->RunOnChildren( update_state, RECURSE_MODE::NO_RECURSE );
1243 }
1244
1245 if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
1246 timer.Show();
1247}
1248
1249
1250SCH_LINE* SCH_SCREEN::GetLine( const VECTOR2I& aPosition, int aAccuracy, int aLayer,
1251 SCH_LINE_TEST_T aSearchType ) const
1252{
1253 // an accuracy of 0 had problems with rounding errors; use at least 1
1254 aAccuracy = std::max( aAccuracy, 1 );
1255
1256 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1257 {
1258 if( item->Type() != SCH_LINE_T )
1259 continue;
1260
1261 if( item->GetLayer() != aLayer )
1262 continue;
1263
1264 if( !item->HitTest( aPosition, aAccuracy ) )
1265 continue;
1266
1267 switch( aSearchType )
1268 {
1269 case ENTIRE_LENGTH_T:
1270 return (SCH_LINE*) item;
1271
1273 if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1274 return (SCH_LINE*) item;
1275 break;
1276
1277 case END_POINTS_ONLY_T:
1278 if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) )
1279 return (SCH_LINE*) item;
1280 }
1281 }
1282
1283 return nullptr;
1284}
1285
1286
1287std::vector<SCH_LINE*> SCH_SCREEN::GetBusesAndWires( const VECTOR2I& aPosition,
1288 bool aIgnoreEndpoints ) const
1289{
1290 std::vector<SCH_LINE*> retVal;
1291
1292 for( SCH_ITEM* item : Items().Overlapping( SCH_LINE_T, aPosition ) )
1293 {
1294 if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T } ) )
1295 {
1296 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
1297
1298 if( aIgnoreEndpoints && wire->IsEndPoint( aPosition ) )
1299 continue;
1300
1301 if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), aPosition ) )
1302 retVal.push_back( wire );
1303 }
1304 }
1305
1306 return retVal;
1307}
1308
1309
1310std::vector<VECTOR2I> SCH_SCREEN::GetConnections() const
1311{
1312 std::vector<VECTOR2I> retval;
1313
1314 for( SCH_ITEM* item : Items() )
1315 {
1316 // Avoid items that are changing
1317 if( !( item->GetEditFlags() & ( IS_MOVING | IS_DELETED ) ) )
1318 {
1319 std::vector<VECTOR2I> pts = item->GetConnectionPoints();
1320 retval.insert( retval.end(), pts.begin(), pts.end() );
1321 }
1322 }
1323
1324 // We always have some overlapping connection points. Drop duplicates here
1325 std::sort( retval.begin(), retval.end(),
1326 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1327 {
1328 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1329 } );
1330
1331 retval.erase( std::unique( retval.begin(), retval.end() ), retval.end() );
1332
1333 return retval;
1334}
1335
1336
1337std::vector<VECTOR2I> SCH_SCREEN::GetNeededJunctions( const std::deque<EDA_ITEM*>& aItems ) const
1338{
1339 std::vector<VECTOR2I> pts;
1340 std::vector<VECTOR2I> connections = GetConnections();
1341
1342 for( const EDA_ITEM* edaItem : aItems )
1343 {
1344 const SCH_ITEM* item = dynamic_cast<const SCH_ITEM*>( edaItem );
1345
1346 if( !item || !item->IsConnectable() )
1347 continue;
1348
1349 std::vector<VECTOR2I> new_pts = item->GetConnectionPoints();
1350 pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
1351
1352 // If the item is a line, we also add any connection points from the rest of the schematic
1353 // that terminate on the line after it is moved.
1354 if( item->Type() == SCH_LINE_T )
1355 {
1356 SCH_LINE* line = (SCH_LINE*) item;
1357
1358 for( const VECTOR2I& pt : connections )
1359 {
1360 if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
1361 pts.push_back( pt );
1362 }
1363 }
1364 }
1365
1366 // We always have some overlapping connection points. Drop duplicates here
1367 std::sort( pts.begin(), pts.end(),
1368 []( const VECTOR2I& a, const VECTOR2I& b ) -> bool
1369 {
1370 return a.x < b.x || ( a.x == b.x && a.y < b.y );
1371 } );
1372
1373 pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1374
1375 // We only want the needed junction points, remove all the others
1376 pts.erase( std::remove_if( pts.begin(), pts.end(),
1377 [this]( const VECTOR2I& a ) -> bool
1378 {
1379 return !IsExplicitJunctionNeeded( a );
1380 } ),
1381 pts.end() );
1382
1383 return pts;
1384}
1385
1386
1387SCH_LABEL_BASE* SCH_SCREEN::GetLabel( const VECTOR2I& aPosition, int aAccuracy ) const
1388{
1389 for( SCH_ITEM* item : Items().Overlapping( aPosition, aAccuracy ) )
1390 {
1391 switch( item->Type() )
1392 {
1393 case SCH_LABEL_T:
1394 case SCH_GLOBAL_LABEL_T:
1395 case SCH_HIER_LABEL_T:
1397 if( item->HitTest( aPosition, aAccuracy ) )
1398 return static_cast<SCH_LABEL_BASE*>( item );
1399
1400 break;
1401
1402 default:
1403 ;
1404 }
1405 }
1406
1407 return nullptr;
1408}
1409
1410
1412{
1413 wxCHECK( aLibSymbol, /* void */ );
1414
1415 wxString libSymbolName = aLibSymbol->GetLibId().Format().wx_str();
1416
1417 auto it = m_libSymbols.find( libSymbolName );
1418
1419 if( it != m_libSymbols.end() )
1420 {
1421 delete it->second;
1422 m_libSymbols.erase( it );
1423 }
1424
1425 m_libSymbols[libSymbolName] = aLibSymbol;
1426}
1427
1428
1430{
1431 SCHEMATIC* schematic = Schematic();
1432
1433 const std::vector<wxString>* embeddedFonts = schematic->GetEmbeddedFiles()->UpdateFontFiles();
1434
1435 for( auto& [name, libSym] : m_libSymbols )
1436 {
1437 for( auto& [filename, embeddedFile] : libSym->EmbeddedFileMap() )
1438 {
1439 EMBEDDED_FILES::EMBEDDED_FILE* file = schematic->GetEmbeddedFile( filename );
1440
1441 if( file )
1442 {
1443 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1444 embeddedFile->decompressedData = file->decompressedData;
1445 embeddedFile->data_hash = file->data_hash;
1446 embeddedFile->is_valid = file->is_valid;
1447 }
1448 }
1449
1450 libSym->RunOnChildren(
1451 [&]( SCH_ITEM* aChild )
1452 {
1453 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1454 textItem->ResolveFont( embeddedFonts );
1455 },
1457 }
1458
1459 std::vector<SCH_ITEM*> items_to_update;
1460
1461 for( SCH_ITEM* item : Items() )
1462 {
1463 bool update = false;
1464
1465 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( item ) )
1466 update |= textItem->ResolveFont( embeddedFonts );
1467
1468 item->RunOnChildren(
1469 [&]( SCH_ITEM* aChild )
1470 {
1471 if( EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aChild ) )
1472 update |= textItem->ResolveFont( embeddedFonts );
1473 },
1475
1476 if( update )
1477 items_to_update.push_back( item );
1478 }
1479
1480 for( SCH_ITEM* item : items_to_update )
1481 Update( item );
1482}
1483
1484
1485void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
1486{
1487 if( SCHEMATIC* schematic = Schematic() )
1488 schematic->AddBusAlias( aAlias );
1489}
1490
1491
1493{
1494 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1495 {
1496 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1497
1498 // Add missing value and footprint instance data for legacy schematics.
1499 for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstances() )
1500 {
1501 symbol->AddHierarchicalReference( instance.m_Path, instance.m_Reference,
1502 instance.m_Unit );
1503 }
1504 }
1505}
1506
1507
1509{
1510 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1511 {
1512 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1513
1514 // Fix pre-8.0 legacy power symbols with invisible pins
1515 // that have mismatched pin names and value fields
1516 if( symbol->GetLibSymbolRef()
1517 && symbol->GetLibSymbolRef()->IsGlobalPower()
1518 && symbol->GetAllLibPins().size() > 0
1519 && symbol->GetAllLibPins()[0]->IsGlobalPower()
1520 && !symbol->GetAllLibPins()[0]->IsVisible() )
1521 {
1522 symbol->SetValueFieldText( symbol->GetAllLibPins()[0]->GetName() );
1523 }
1524 }
1525}
1526
1527
1529 std::vector<wxString>& aMatches )
1530{
1531 wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
1532
1533 if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
1534 aMatches.emplace_back( searchName );
1535
1536 searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
1537
1538 long tmp;
1539 wxString suffix;
1540
1541 for( auto& pair : m_libSymbols )
1542 {
1543 if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
1544 aMatches.emplace_back( pair.first );
1545 }
1546
1547 return aMatches.size();
1548}
1549
1550
1551void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
1552 const SCH_SHEET_LIST& aValidSheetPaths )
1553{
1554 // The project name cannot be empty. Projects older than 7.0 did not save project names
1555 // when saving instance data. Running this algorithm with an empty project name would
1556 // clobber all instance data for projects other than the current one when a schematic
1557 // file is shared across multiple projects. Because running the schematic editor in
1558 // stand alone mode can result in an empty project name, do not assert here.
1559 if( aProjectName.IsEmpty() )
1560 return;
1561
1562 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1563 {
1564 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1565
1566 wxCHECK2( symbol, continue );
1567
1568 std::set<KIID_PATH> pathsToPrune;
1569 const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstances();
1570
1571 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1572 {
1573 // Ignore instance paths from other projects.
1574 if( aProjectName != instance.m_ProjectName )
1575 continue;
1576
1577 std::optional<SCH_SHEET_PATH> pathFound =
1578 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1579
1580 // Check for paths that do not exist in the current project and paths that do
1581 // not contain the current symbol.
1582 if( !pathFound )
1583 pathsToPrune.emplace( instance.m_Path );
1584 else if( pathFound.value().LastScreen() != this )
1585 pathsToPrune.emplace( pathFound.value().Path() );
1586 }
1587
1588 for( const KIID_PATH& sheetPath : pathsToPrune )
1589 {
1590 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
1591 aProjectName, sheetPath.AsString() );
1592 symbol->RemoveInstance( sheetPath );
1593 }
1594 }
1595}
1596
1597
1598void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
1599 const SCH_SHEET_LIST& aValidSheetPaths )
1600{
1601 // The project name cannot be empty. Projects older than 7.0 did not save project names
1602 // when saving instance data. Running this algorithm with an empty project name would
1603 // clobber all instance data for projects other than the current one when a schematic
1604 // file is shared across multiple projects. Because running the schematic editor in
1605 // stand alone mode can result in an empty project name, do not assert here.
1606 if( aProjectName.IsEmpty() )
1607 return;
1608
1609 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1610 {
1611 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1612
1613 wxCHECK2( sheet, continue );
1614
1615 std::set<KIID_PATH> pathsToPrune;
1616 const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
1617
1618 for( const SCH_SHEET_INSTANCE& instance : instances )
1619 {
1620 // Ignore instance paths from other projects.
1621 if( aProjectName != instance.m_ProjectName )
1622 continue;
1623
1624 std::optional<SCH_SHEET_PATH> pathFound =
1625 aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
1626
1627 // Check for paths that do not exist in the current project and paths that do
1628 // not contain the current symbol.
1629 if( !pathFound )
1630 pathsToPrune.emplace( instance.m_Path );
1631 else if( pathFound.value().LastScreen() != this )
1632 pathsToPrune.emplace( pathFound.value().Path() );
1633 }
1634
1635 for( const KIID_PATH& sheetPath : pathsToPrune )
1636 {
1637 wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
1638 aProjectName, sheetPath.AsString() );
1639 sheet->RemoveInstance( sheetPath );
1640 }
1641 }
1642}
1643
1644
1646{
1647 wxString trimmedFieldName;
1648
1649 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1650 {
1651 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1652
1653 wxCHECK2( symbol, continue );
1654
1655 for( const SCH_FIELD& field : symbol->GetFields() )
1656 {
1657 trimmedFieldName = field.GetName();
1658 trimmedFieldName.Trim();
1659 trimmedFieldName.Trim( false );
1660
1661 if( field.GetName() != trimmedFieldName )
1662 return true;
1663 }
1664 }
1665
1666 return false;
1667}
1668
1669
1670std::set<wxString> SCH_SCREEN::GetSheetNames() const
1671{
1672 std::set<wxString> retv;
1673
1674 for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1675 {
1676 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1677
1678 wxCHECK2( sheet, continue );
1679
1680 retv.emplace( sheet->GetName() );
1681 }
1682
1683 return retv;
1684}
1685
1686
1688{
1689 wxCHECK( Schematic(), false );
1690
1691 SCH_SHEET_LIST hierarchy = Schematic()->Hierarchy();
1692
1693 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1694 {
1695 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1696
1697 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1698
1699 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1700 {
1701 if( !hierarchy.HasPath( instance.m_Path ) )
1702 return true;
1703 }
1704 }
1705
1706 return false;
1707}
1708
1709
1710wxString SCH_SCREEN::GroupsSanityCheck( bool repair )
1711{
1712 if( repair )
1713 {
1714 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
1715 {
1716 };
1717
1718 return wxEmptyString;
1719 }
1720 return GroupsSanityCheckInternal( repair );
1721}
1722
1723
1725{
1726 // Cycle detection
1727 //
1728 // Each group has at most one parent group.
1729 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
1730 // If we ever see a group that we've already marked, that's a cycle.
1731 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
1732 //
1733 // Algorithm below is linear in the # of groups because each group is visited only once.
1734 // There may be extra time taken due to the container access calls and iterators.
1735 //
1736 // Groups we know are cycle free
1737 std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
1738 // Groups in the current chain we're exploring.
1739 std::unordered_set<EDA_GROUP*> currentChainGroups;
1740 // Groups we haven't checked yet.
1741 std::unordered_set<EDA_GROUP*> toCheckGroups;
1742
1743 // Initialize set of groups and generators to check that could participate in a cycle.
1744 for( SCH_ITEM* item : Items().OfType( SCH_GROUP_T ) )
1745 toCheckGroups.insert( static_cast<SCH_GROUP*>( item ) );
1746
1747 while( !toCheckGroups.empty() )
1748 {
1749 currentChainGroups.clear();
1750 EDA_GROUP* group = *toCheckGroups.begin();
1751
1752 while( true )
1753 {
1754 if( currentChainGroups.find( group ) != currentChainGroups.end() )
1755 {
1756 if( repair )
1757 Remove( static_cast<SCH_ITEM*>( group->AsEdaItem() ) );
1758
1759 return "Cycle detected in group membership";
1760 }
1761 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
1762 {
1763 // Parent is a group we know does not lead to a cycle
1764 break;
1765 }
1766
1767 currentChainGroups.insert( group );
1768 // We haven't visited currIdx yet, so it must be in toCheckGroups
1769 toCheckGroups.erase( group );
1770
1771 group = group->AsEdaItem()->GetParentGroup();
1772
1773 if( !group )
1774 {
1775 // end of chain and no cycles found in this chain
1776 break;
1777 }
1778 }
1779
1780 // No cycles found in chain, so add it to set of groups we know don't participate
1781 // in a cycle.
1782 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
1783 }
1784
1785 // Success
1786 return "";
1787}
1788
1789
1791{
1792 wxCHECK( Schematic() && !m_fileName.IsEmpty(), false );
1793
1794 wxFileName thisScreenFn( m_fileName );
1795 wxFileName thisProjectFn( Schematic()->Project().GetProjectFullName() );
1796
1797 wxCHECK( thisProjectFn.IsAbsolute(), false );
1798
1799 if( thisScreenFn.GetDirCount() < thisProjectFn.GetDirCount() )
1800 return false;
1801
1802 while( thisProjectFn.GetDirCount() != thisScreenFn.GetDirCount() )
1803 thisScreenFn.RemoveLastDir();
1804
1805 return thisScreenFn.GetPath() == thisProjectFn.GetPath();
1806}
1807
1808
1809std::set<wxString> SCH_SCREEN::GetVariantNames() const
1810{
1811 std::set<wxString> variantNames;
1812
1813 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1814 {
1815 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1816
1817 wxCHECK2( symbol, continue );
1818
1819 const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1820
1821 for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1822 {
1823 for( const auto& [name, variant] : instance.m_Variants )
1824 variantNames.emplace( name );
1825 }
1826 }
1827
1828 for( const SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1829 {
1830 const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( item );
1831
1832 wxCHECK2( sheet, continue );
1833
1834 const std::vector<SCH_SHEET_INSTANCE> sheetInstances = sheet->GetInstances();
1835
1836 for( const SCH_SHEET_INSTANCE& instance : sheetInstances )
1837 {
1838 for( const auto& [name, variant] : instance.m_Variants )
1839 variantNames.emplace( name );
1840 }
1841 }
1842
1843 return variantNames;
1844}
1845
1846
1847void SCH_SCREEN::DeleteVariant( const wxString& aVariantName )
1848{
1849 wxCHECK( !aVariantName.IsEmpty(), /* void */ );
1850
1851 for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
1852 {
1853 const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
1854
1855 wxCHECK2( symbol, continue );
1856
1857 std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances();
1858
1859 for( SCH_SYMBOL_INSTANCE& instance : symbolInstances )
1860 {
1861 if( instance.m_Variants.contains( aVariantName ) )
1862 instance.m_Variants.erase( aVariantName );
1863 }
1864 }
1865
1866 for( const SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
1867 {
1868 const SCH_SHEET* sheet = static_cast<const SCH_SHEET*>( item );
1869
1870 wxCHECK2( sheet, continue );
1871
1872 std::vector<SCH_SHEET_INSTANCE> sheetInstances = sheet->GetInstances();
1873
1874 for( SCH_SHEET_INSTANCE& instance : sheetInstances )
1875 {
1876 if( instance.m_Variants.contains( aVariantName ) )
1877 instance.m_Variants.erase( aVariantName );
1878 }
1879 }
1880}
1881
1882
1883#if defined(DEBUG)
1884void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
1885{
1886 // for now, make it look like XML, expand on this later.
1887 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
1888
1889 for( const SCH_ITEM* item : Items() )
1890 item->Show( nestLevel + 1, os );
1891
1892 NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1893}
1894#endif
1895
1896
1898{
1899 m_index = 0;
1900 buildScreenList( aSheet );
1901}
1902
1903
1907
1908
1910{
1911 m_index = 0;
1912
1913 if( m_screens.size() > 0 )
1914 return m_screens[0];
1915
1916 return nullptr;
1917}
1918
1919
1921{
1922 if( m_index < m_screens.size() )
1923 m_index++;
1924
1925 return GetScreen( m_index );
1926}
1927
1928
1929SCH_SCREEN* SCH_SCREENS::GetScreen( unsigned int aIndex ) const
1930{
1931 if( aIndex < m_screens.size() )
1932 return m_screens[ aIndex ];
1933
1934 return nullptr;
1935}
1936
1937
1938SCH_SHEET* SCH_SCREENS::GetSheet( unsigned int aIndex ) const
1939{
1940 if( aIndex < m_sheets.size() )
1941 return m_sheets[ aIndex ];
1942
1943 return nullptr;
1944}
1945
1946
1948{
1949 if( aScreen == nullptr )
1950 return;
1951
1952 for( const SCH_SCREEN* screen : m_screens )
1953 {
1954 if( screen == aScreen )
1955 return;
1956 }
1957
1958 m_screens.push_back( aScreen );
1959 m_sheets.push_back( aSheet );
1960}
1961
1962
1964{
1965 if( aSheet && aSheet->Type() == SCH_SHEET_T )
1966 {
1967 SCH_SCREEN* screen = aSheet->GetScreen();
1968
1969 if( !screen )
1970 return;
1971
1972 addScreenToList( screen, aSheet );
1973
1974 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1975 buildScreenList( static_cast<SCH_SHEET*>( item ) );
1976 }
1977}
1978
1979
1981{
1982 SCH_SCREEN* first = GetFirst();
1983
1984 if( !first )
1985 return;
1986
1987 SCHEMATIC* sch = first->Schematic();
1988
1989 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::ClearAnnotationOfNewSheetPaths" );
1990
1991 // Clear the annotation for symbols inside new sheetpaths not already in aInitialSheetList
1992 SCH_SCREENS screensList( sch->Root() ); // The list of screens, shared by sheet paths
1993 screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
1994
1995 // Search for new sheet paths, not existing in aInitialSheetPathList
1996 // and existing in sheetpathList
1997 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
1998 {
1999 bool path_exists = false;
2000
2001 for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
2002 {
2003 if( existing_sheetpath.Path() == sheetpath.Path() )
2004 {
2005 path_exists = true;
2006 break;
2007 }
2008 }
2009
2010 if( !path_exists )
2011 {
2012 // A new sheet path is found: clear the annotation corresponding to this new path:
2013 SCH_SCREEN* curr_screen = sheetpath.LastScreen();
2014
2015 // Clear annotation and create the AR for this path, if not exists,
2016 // when the screen is shared by sheet paths.
2017 // Otherwise ClearAnnotation do nothing, because the F1 field is used as
2018 // reference default value and takes the latest displayed value
2019 curr_screen->EnsureAlternateReferencesExist();
2020 curr_screen->ClearAnnotation( &sheetpath, false );
2021 }
2022 }
2023}
2024
2025
2027{
2028 std::vector<SCH_ITEM*> items;
2029 int count = 0;
2030
2031 auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
2032 {
2033 return a->m_Uuid < b->m_Uuid;
2034 };
2035
2036 std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
2037
2038 for( SCH_SCREEN* screen : m_screens )
2039 screen->GetHierarchicalItems( &items );
2040
2041 if( items.size() < 2 )
2042 return 0;
2043
2044 for( EDA_ITEM* item : items )
2045 {
2046 if( !unique_stamps.insert( item ).second )
2047 {
2048 // Reset to fully random UUID. This may lose reference, but better to be
2049 // deterministic about it rather than to have duplicate UUIDs with random
2050 // side-effects.
2051 const_cast<KIID&>( item->m_Uuid ) = KIID();
2052 count++;
2053
2054 // @todo If the item is a sheet, we need to descend the hierarchy from the sheet
2055 // and replace all instances of the changed UUID in sheet paths. Otherwise,
2056 // all instance paths with the sheet's UUID will get clobbered.
2057 }
2058 }
2059
2060 return count;
2061}
2062
2063
2065{
2066 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2067 {
2068 for( SCH_ITEM* item : screen->Items() )
2069 item->ClearEditFlags();
2070 }
2071}
2072
2073
2075{
2076 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2077 {
2078 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
2079 {
2080 if( item == aMarker )
2081 {
2082 screen->DeleteItem( item );
2083 return;
2084 }
2085 }
2086 }
2087}
2088
2089
2090void SCH_SCREENS::DeleteMarkers( enum MARKER_BASE::MARKER_T aMarkerType, int aErrorCode,
2091 bool aIncludeExclusions )
2092{
2093 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2094 {
2095 std::vector<SCH_ITEM*> markers;
2096
2097 for( SCH_ITEM* item : screen->Items().OfType( SCH_MARKER_T ) )
2098 {
2099 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
2100 std::shared_ptr<RC_ITEM>rcItem = marker->GetRCItem();
2101
2102 if( marker->GetMarkerType() == aMarkerType
2103 && ( aErrorCode == ERCE_UNSPECIFIED || rcItem->GetErrorCode() == aErrorCode )
2104 && ( !marker->IsExcluded() || aIncludeExclusions ) )
2105 {
2106 markers.push_back( item );
2107 }
2108 }
2109
2110 for( SCH_ITEM* marker : markers )
2111 screen->DeleteItem( marker );
2112 }
2113}
2114
2115
2117 bool aIncludeExclusions )
2118{
2119 DeleteMarkers( aMarkerType, ERCE_UNSPECIFIED, aIncludeExclusions );
2120}
2121
2122
2124{
2125 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2126 screen->UpdateSymbolLinks( aReporter );
2127
2128 SCH_SCREEN* first = GetFirst();
2129
2130 if( !first )
2131 return;
2132
2133 SCHEMATIC* sch = first->Schematic();
2134
2135 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::UpdateSymbolLinks" );
2136
2137 SCH_SHEET_LIST sheets = sch->Hierarchy();
2138
2139 // All of the library symbols have been replaced with copies so the connection graph
2140 // pointers are stale.
2141 if( sch->ConnectionGraph() )
2142 sch->ConnectionGraph()->Recalculate( sheets, true );
2143}
2144
2145
2147{
2148 bool has_symbols = false;
2149
2150 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2151 {
2152 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2153 {
2154 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2155 has_symbols = true;
2156
2157 if( !symbol->GetLibId().GetLibNickname().empty() )
2158 return false;
2159 }
2160 }
2161
2162 // return true (i.e. has no fully defined symbol) only if at least one symbol is found
2163 return has_symbols ? true : false;
2164}
2165
2166
2167size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
2168{
2169 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2170 {
2171 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2172 {
2173 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2174 const UTF8& nickname = symbol->GetLibId().GetLibNickname();
2175
2176 if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
2177 aLibNicknames.Add( nickname );
2178 }
2179 }
2180
2181 return aLibNicknames.GetCount();
2182}
2183
2184
2185int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
2186{
2187 SCH_SCREEN* screen;
2188 int cnt = 0;
2189
2190 for( screen = GetFirst(); screen; screen = GetNext() )
2191 {
2192 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
2193 {
2194 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2195
2196 if( symbol->GetLibId().GetLibNickname().wx_str() != aFrom )
2197 continue;
2198
2199 LIB_ID id = symbol->GetLibId();
2200 id.SetLibNickname( aTo );
2201 symbol->SetLibId( id );
2202 cnt++;
2203 }
2204 }
2205
2206 return cnt;
2207}
2208
2209
2210bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
2211{
2212 for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2213 {
2214 if( screen->GetFileName() == aSchematicFileName )
2215 return true;
2216 }
2217
2218 return false;
2219}
2220
2221
2223{
2224 SCH_SCREEN* first = GetFirst();
2225
2226 if( !first )
2227 return;
2228
2229 SCHEMATIC* sch = first->Schematic();
2230
2231 wxCHECK_RET( sch, "Null schematic in SCH_SCREENS::BuildClientSheetPathList" );
2232
2233 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2234 curr_screen->GetClientSheetPaths().clear();
2235
2236 for( SCH_SHEET_PATH& sheetpath : sch->Hierarchy() )
2237 {
2238 SCH_SCREEN* used_screen = sheetpath.LastScreen();
2239
2240 // Search for the used_screen in list and add this unique sheet path:
2241 for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
2242 {
2243 if( used_screen == curr_screen )
2244 {
2245 curr_screen->GetClientSheetPaths().push_back( sheetpath );
2246 break;
2247 }
2248 }
2249 }
2250}
2251
2252
2254{
2255 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2256 screen->SetLegacySymbolInstanceData();
2257}
2258
2259
2261{
2262 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2263 screen->FixLegacyPowerSymbolMismatches();
2264}
2265
2266
2268{
2269 LOCALE_IO toggle;
2270
2271 // V6 schematics may specify model names in Value fields, which we don't do in V7.
2272 // Migrate by adding an equivalent model for these symbols.
2273
2274 for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
2275 {
2276 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2277 SIM_MODEL::MigrateSimModel<SCH_SYMBOL>( *symbol, &Schematic()->Project() );
2278 }
2279}
2280
2281
2282void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
2283 const SCH_SHEET_LIST& aValidSheetPaths )
2284{
2285 if( aProjectName.IsEmpty() )
2286 return;
2287
2288 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2289 screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
2290}
2291
2292
2293void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
2294 const SCH_SHEET_LIST& aValidSheetPaths )
2295{
2296 if( aProjectName.IsEmpty() )
2297 return;
2298
2299 for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
2300 screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
2301}
2302
2303
2305{
2306 for( const SCH_SCREEN* screen : m_screens )
2307 {
2308 if( screen->HasSymbolFieldNamesWithWhiteSpace() )
2309 return true;
2310 }
2311
2312 return false;
2313}
2314
2315
2316std::set<wxString> SCH_SCREENS::GetVariantNames() const
2317{
2318 std::set<wxString> variantNames;
2319
2320 for( const SCH_SCREEN* screen : m_screens )
2321 {
2322 for( const wxString& variantName : screen->GetVariantNames() )
2323 variantNames.emplace( variantName );
2324 }
2325
2326 return variantNames;
2327}
2328
2329
2330void SCH_SCREENS::DeleteVariant( const wxString& aVariantName )
2331{
2332 wxCHECK( !aVariantName.IsEmpty(), /* void */ );
2333
2334 for( SCH_SCREEN* screen : m_screens )
2335 screen->DeleteVariant( aVariantName );
2336}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
int m_virtualPageNumber
An integer based page number used for printing a range of pages.
bool m_Center
Center on screen.
Definition base_screen.h:96
int m_pageCount
The number of BASE_SCREEN objects in this design.
BASE_SCREEN(EDA_ITEM *aParent, KICAD_T aType=SCREEN_T)
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
void InitDataPoints(const VECTOR2I &aPageSizeInternalUnits)
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, PROGRESS_REPORTER *aProgressReporter=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:841
EDA_ANGLE Normalize90()
Definition eda_angle.h:257
double AsDegrees() const
Definition eda_angle.h:116
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:110
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
const KIID m_Uuid
Definition eda_item.h:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
EDA_ITEM * GetParent() const
Definition eda_item.h:112
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:146
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
bool IsNew() const
Definition eda_item.h:124
std::vector< VECTOR2I > GetPolyPoints() const
Duplicate the polygon outlines into a flat list of VECTOR2I points.
void SetLineStyle(const LINE_STYLE aStyle)
SHAPE_T GetShape() const
Definition eda_shape.h:168
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:215
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:173
std::vector< VECTOR2I > GetRectCorners() const
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
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.
virtual const wxString What() const
A composite of Problem() and Where()
Definition kiid.h:49
A collection of #SYMBOL_LIB objects.
Object used to load, save, search, and otherwise manipulate symbol library files.
LIB_SYMBOL * FindSymbol(const wxString &aName) const
Find LIB_SYMBOL by aName.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
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:688
wxString GetName() const override
Definition lib_symbol.h:148
bool IsGlobalPower() const override
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
void SetLibId(const LIB_ID &aLibId)
Definition lib_symbol.h:156
virtual void SetName(const wxString &aName)
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:93
std::shared_ptr< RC_ITEM > GetRCItem() const
enum MARKER_T GetMarkerType() const
Definition marker_base.h:91
Base plotter engine class.
Definition plotter.h:121
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:152
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_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
static LEGACY_SYMBOL_LIBS * LegacySchLibs(PROJECT *aProject)
Returns the list of symbol libraries from a legacy (pre-5.x) design This is only used from the remapp...
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:88
SCHEMATIC_SETTINGS & Settings() const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
EMBEDDED_FILES * GetEmbeddedFiles() override
CONNECTION_GRAPH * ConnectionGraph() const
Definition schematic.h:198
SCH_SHEET & Root() const
Definition schematic.h:125
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 IsEndPoint(const VECTOR2I &aPt) const
Test if aPt is an end point of this schematic object.
Definition sch_item.h:498
virtual bool IsConnectable() const
Definition sch_item.h:507
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:244
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:321
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition sch_item.cpp:343
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:522
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
void SetStartPoint(const VECTOR2I &aPosition)
Definition sch_line.h:140
std::vector< VECTOR3I > BuildWireWithHopShape(const SCH_SCREEN *aScreen, double aArcRadius) const
For wires only: build the list of points to draw the shape using segments and 180 deg arcs Points are...
bool IsWire() const
Return true if the line is a wire.
Definition sch_line.cpp:989
EDA_ANGLE Angle() const
Get the angle between the start and end lines.
Definition sch_line.h:104
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
Definition sch_line.cpp:880
VECTOR2I GetEndPoint() const
Definition sch_line.h:148
VECTOR2I GetStartPoint() const
Definition sch_line.h:139
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
Definition sch_line.h:91
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:149
SCH_SCREEN * GetNext()
unsigned int m_index
Definition sch_screen.h:868
std::vector< SCH_SHEET * > m_sheets
Definition sch_screen.h:867
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 DeleteVariant(const wxString &aVariantName)
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::set< wxString > GetVariantNames() const
std::vector< SCH_SCREEN * > m_screens
Definition sch_screen.h:866
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::set< wxString > GetVariantNames() const
std::map< wxString, LIB_SYMBOL * > m_libSymbols
Library symbols required for this schematic.
Definition sch_screen.h:689
SCH_PIN * GetPin(const VECTOR2I &aPosition, SCH_SYMBOL **aSymbol=nullptr, bool aEndPointOnly=false) const
Test the screen for a symbol pin item at aPosition.
bool m_fileExists
Flag to indicate the file associated with this screen has been created.
Definition sch_screen.h:686
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)
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.
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
bool HasItems(KICAD_T aItemType) const
void Clear(bool aFree=true)
Delete all draw items and clears the project settings.
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:186
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic from the project #SYM...
SCH_LINE * GetWire(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition sch_screen.h:433
std::set< SCH_ITEM * > MarkConnections(SCH_ITEM *aItem, bool aSecondPass)
Return all wires and junctions connected to aItem which are not connected any symbol pin or all graph...
std::set< wxString > GetSheetNames() const
TITLE_BLOCK m_titles
Definition sch_screen.h:673
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:677
double m_LastZoomLevel
last value for the zoom level, useful in Eeschema when changing the current displayed sheet to reuse ...
Definition sch_screen.h:655
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicate that a junction dot is necessary at the given location.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:117
int m_fileFormatVersionAtLoad
Definition sch_screen.h:659
void DecRefCount()
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.
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicate that a junction dot may be placed at the given location.
void clearLibSymbols()
wxString m_fileName
Definition sch_screen.h:658
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void IncRefCount()
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
static bool ClassOf(const EDA_ITEM *aItem)
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
void DeleteVariant(const wxString &aVariantName)
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
Definition sch_screen.h:439
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
SCH_SCREEN(EDA_ITEM *aParent=nullptr)
SCHEMATIC * Schematic() const
EE_RTREE m_rtree
Definition sch_screen.h:675
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.
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.
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
virtual wxString GetClass() const override
Return the class name.
Definition sch_screen.h:131
void Update(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Update aItem's bounding box in the tree.
void SetConnectivityDirty()
bool m_zoomInitialized
Definition sch_screen.h:680
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:672
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
bool m_isReadOnly
Read only status of the screen file.
Definition sch_screen.h:683
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
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
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.
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.
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
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.
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)
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.
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:478
Schematic symbol object.
Definition sch_symbol.h:76
void SetLibId(const LIB_ID &aName)
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:135
void RemoveInstance(const SCH_SHEET_PATH &aInstancePath)
void SetValueFieldText(const wxString &aValue)
wxString GetSchSymbolLibraryName() const
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.
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.
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:165
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
Definition sch_symbol.h:180
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:184
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
VECTOR2I GetPinPhysicalPosition(const SCH_PIN *Pin) const
static void MigrateSimModel(T &aSymbol, const PROJECT *aProject)
An interface to the global shared library manager that is schematic-specific and linked to one projec...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition symbol.h:63
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
Definition symbol.h:213
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:110
wxString wx_str() const
Definition utf8.cpp:45
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
@ NO_RECURSE
Definition eda_item.h:52
#define IS_DELETED
#define STRUCT_DELETED
flag indication structures to be erased
#define IS_MOVING
Item being moved.
@ SEGMENT
Definition eda_shape.h:45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:46
@ ERCE_UNSPECIFIED
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
const wxChar *const traceSchSheetPaths
Flag to enable debug output of schematic symbol sheet path manipulation code.
@ LAYER_WIRE
Definition layer_ids.h:452
@ LAYER_NOTES
Definition layer_ids.h:467
@ LAYER_BUS
Definition layer_ids.h:453
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,...
PAGE_SIZE_TYPE
Definition page_info.h:50
@ 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)
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...
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
VECTOR2I end
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:177
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_SYMBOL_T
Definition typeinfo.h:176
@ SCH_FIELD_T
Definition typeinfo.h:154
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:175
@ SCH_LABEL_T
Definition typeinfo.h:171
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_MARKER_T
Definition typeinfo.h:162
@ SCH_SHAPE_T
Definition typeinfo.h:153
@ SCH_HIER_LABEL_T
Definition typeinfo.h:173
@ SCH_SCREEN_T
Definition typeinfo.h:206
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:195
@ SCHEMATIC_T
Definition typeinfo.h:208
@ SCH_SHEET_PIN_T
Definition typeinfo.h:178
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:165
@ SCH_BITMAP_T
Definition typeinfo.h:168
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:172
@ SCH_JUNCTION_T
Definition typeinfo.h:163
@ SCH_PIN_T
Definition typeinfo.h:157
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695